Skip to content

Commit 06c95d6

Browse files
committed
C library: Avoid arithmetic overflow with pipe operations
We may be trying to access file descriptors that haven't been fully initialised. Don't yield spurious arithmetic overflows (that are just caused by our modelling) in such situations. Fixes: #5570
1 parent d932d6f commit 06c95d6

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
#include <assert.h>
1+
#include <limits.h>
22
#include <unistd.h>
33

4+
extern const __CPROVER_size_t SIZE;
5+
46
int main()
57
{
6-
write();
7-
assert(0);
8-
return 0;
8+
__CPROVER_assume(SIZE < SSIZE_MAX);
9+
10+
int fd;
11+
char ptr[SIZE];
12+
__CPROVER_size_t nbytes;
13+
14+
__CPROVER_assume(fd >= 0);
15+
__CPROVER_assume(nbytes < SIZE);
16+
17+
write(fd, ptr, nbytes);
918
}

regression/cbmc-library/write-01/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE unix
22
main.c
3-
--pointer-check --bounds-check
3+
--pointer-check --bounds-check --conversion-check --unwind 1
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

src/ansi-c/library/unistd.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ int pipe(int fildes[2])
6363
}
6464

6565
__CPROVER_atomic_begin();
66+
__CPROVER_assume(__CPROVER_pipe_offset >= 0);
6667
__CPROVER_assume(__CPROVER_pipe_offset%2==0);
6768
__CPROVER_assume(__CPROVER_pipe_offset<=(int)(__CPROVER_pipe_offset+__CPROVER_pipe_count));
6869
fildes[0]=__CPROVER_pipe_offset+__CPROVER_pipe_count;
@@ -106,6 +107,8 @@ int close(int fildes)
106107
if((fildes>=0 && fildes<=2) || fildes < __CPROVER_pipe_offset)
107108
return 0;
108109

110+
__CPROVER_assume(__CPROVER_pipe_offset >= 0);
111+
109112
int retval=-1;
110113
fildes-=__CPROVER_pipe_offset;
111114
if(fildes%2==1)
@@ -164,14 +167,18 @@ ret_type write(int fildes, const void *buf, size_type nbyte)
164167
return retval;
165168
}
166169

170+
__CPROVER_assume(__CPROVER_pipe_offset >= 0);
171+
167172
int retval=-1;
168173
fildes-=__CPROVER_pipe_offset;
169174
if(fildes%2==1)
170175
--fildes;
171176
__CPROVER_atomic_begin();
172-
if(!__CPROVER_pipes[fildes].widowed &&
173-
sizeof(__CPROVER_pipes[fildes].data) >=
174-
__CPROVER_pipes[fildes].next_avail+nbyte)
177+
if(
178+
!__CPROVER_pipes[fildes].widowed &&
179+
__CPROVER_pipes[fildes].next_avail >= 0 &&
180+
sizeof(__CPROVER_pipes[fildes].data) >=
181+
__CPROVER_pipes[fildes].next_avail + nbyte)
175182
{
176183
for(size_type i=0; i<nbyte; ++i)
177184
__CPROVER_pipes[fildes].data[i+__CPROVER_pipes[fildes].next_avail]=
@@ -262,12 +269,16 @@ ret_type read(int fildes, void *buf, size_type nbyte)
262269
return error ? -1 : nread;
263270
}
264271

272+
__CPROVER_assume(__CPROVER_pipe_offset >= 0);
273+
265274
int retval=0;
266275
fildes-=__CPROVER_pipe_offset;
267276
if(fildes%2==1)
268277
--fildes;
269278
__CPROVER_atomic_begin();
270-
if(!__CPROVER_pipes[fildes].widowed)
279+
if(
280+
!__CPROVER_pipes[fildes].widowed &&
281+
__CPROVER_pipes[fildes].next_unread >= 0)
271282
{
272283
for(size_type i=0; i<nbyte &&
273284
__CPROVER_pipes[fildes].next_unread <

0 commit comments

Comments
 (0)