Skip to content

Commit 9d91abc

Browse files
committed
C library: avoid duplicate multiplication around overflow checks
The use of GCC built-ins allows us to avoid the duplicate multiplication (and addition) that __CPROVER_overflow_OP plus the actual result computation would entail.
1 parent 6a99d3b commit 9d91abc

File tree

2 files changed

+13
-17
lines changed

2 files changed

+13
-17
lines changed

src/ansi-c/library/stdlib.c

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,16 @@ inline void abort(void)
7171
#undef calloc
7272

7373
__CPROVER_bool __VERIFIER_nondet___CPROVER_bool();
74+
#ifndef __GNUC__
75+
_Bool __builtin_mul_overflow();
76+
#endif
7477

7578
inline void *calloc(__CPROVER_size_t nmemb, __CPROVER_size_t size)
7679
{
7780
__CPROVER_HIDE:;
78-
#pragma CPROVER check push
79-
#pragma CPROVER check disable "unsigned-overflow"
80-
if(__CPROVER_overflow_mult(nmemb, size))
81+
__CPROVER_size_t alloc_size;
82+
if(__builtin_mul_overflow(nmemb, size, &alloc_size))
8183
return (void *)0;
82-
// This is now safe; still do it within the scope of the pragma to avoid an
83-
// unnecessary assertion to be generated.
84-
__CPROVER_size_t alloc_size = nmemb * size;
85-
#pragma CPROVER check pop
8684

8785
if(__CPROVER_malloc_failure_mode == __CPROVER_malloc_failure_mode_return_null)
8886
{
@@ -302,6 +300,11 @@ inline void free(void *ptr)
302300
int isspace(int);
303301
int isdigit(int);
304302

303+
#ifndef __GNUC__
304+
_Bool __builtin_add_overflow();
305+
_Bool __builtin_mul_overflow();
306+
#endif
307+
305308
inline long strtol(const char *nptr, char **endptr, int base)
306309
{
307310
__CPROVER_HIDE:;
@@ -362,23 +365,15 @@ inline long strtol(const char *nptr, char **endptr, int base)
362365
break;
363366

364367
in_number=1;
365-
_Bool overflow = __CPROVER_overflow_mult(res, (long)base);
366-
#pragma CPROVER check push
367-
#pragma CPROVER check disable "signed-overflow"
368-
// This is now safe; still do it within the scope of the pragma to avoid an
369-
// unnecessary assertion to be generated.
370-
if(!overflow)
371-
res *= base;
372-
#pragma CPROVER check pop
373-
if(overflow || __CPROVER_overflow_plus(res, (long)(ch - sub)))
368+
_Bool overflow = __builtin_mul_overflow(res, (long)base, &res);
369+
if(overflow || __builtin_add_overflow(res, (long)(ch - sub), &res))
374370
{
375371
errno=ERANGE;
376372
if(sign=='-')
377373
return LONG_MIN;
378374
else
379375
return LONG_MAX;
380376
}
381-
res += ch - sub;
382377
}
383378

384379
if(endptr!=0)

src/ansi-c/library_check.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ for f in "$@"; do
88
cp "${f}" __libcheck.c
99
perl -p -i -e 's/(__builtin_[^v])/s$1/' __libcheck.c
1010
perl -p -i -e 's/s(__builtin_unreachable)/$1/' __libcheck.c
11+
perl -p -i -e 's/s(__builtin_(add|mul)_overflow)/$1/' __libcheck.c
1112
perl -p -i -e 's/(_mm_.fence)/s$1/' __libcheck.c
1213
perl -p -i -e 's/(__sync_)/s$1/' __libcheck.c
1314
perl -p -i -e 's/(__atomic_)/s$1/' __libcheck.c

0 commit comments

Comments
 (0)