Skip to content

Commit 723ea09

Browse files
author
Remi Delmas
committed
CONTRACTS: take unsigned offsets into account
1 parent 1cfb9cf commit 723ea09

File tree

3 files changed

+24
-27
lines changed
  • regression/contracts-dfcc
    • memory-predicates-is-fresh-failure-modes
    • memory-predicates-pointer-in-range-requires
  • src/ansi-c/library

3 files changed

+24
-27
lines changed

regression/contracts-dfcc/memory-predicates-is-fresh-failure-modes/main.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ __CPROVER_assigns(__CPROVER_object_from(arr))
77
// clang-format on
88
{
99
__CPROVER_assert(arr != NULL, "arr is not NULL");
10-
__CPROVER_assert(size < __CPROVER_max_malloc_size, "size is capped");
11-
if(size > 0 && size < __CPROVER_max_malloc_size)
10+
__CPROVER_assert(size <= __CPROVER_max_malloc_size, "size is capped");
11+
if(size > 0 && size <= __CPROVER_max_malloc_size)
1212
{
1313
arr[0] = 0;
1414
arr[size - 1] = 0;

regression/contracts-dfcc/memory-predicates-pointer-in-range-requires/main.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
void foo(char *arr, size_t size, char *cur)
55
// clang-format off
66
__CPROVER_requires(0 < size && __CPROVER_is_fresh(arr, size) &&
7-
__CPROVER_pointer_in_range_dfcc(arr, cur, arr + size))
8-
__CPROVER_ensures(__CPROVER_pointer_in_range_dfcc(arr, cur, arr + size))
7+
__CPROVER_pointer_in_range_dfcc(arr, cur, arr + (size - 1)))
8+
__CPROVER_ensures(__CPROVER_pointer_in_range_dfcc(arr, cur, arr + (size - 1)))
99
// clang-format on
1010
{
1111
assert(__CPROVER_r_ok(arr, size));
1212
assert(__CPROVER_same_object(arr, cur));
13-
assert(arr <= cur && cur <= arr + size);
13+
assert(arr <= cur && cur <= arr + (size - 1));
1414
}
1515

1616
int main()

src/ansi-c/library/cprover_contracts.c

+19-22
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,11 @@ __CPROVER_HIDE:;
114114
((ptr == 0) | __CPROVER_rw_ok(ptr, size)),
115115
"ptr NULL or writable up to size");
116116
__CPROVER_assert(
117-
size < __CPROVER_max_malloc_size,
117+
size <= __CPROVER_max_malloc_size,
118118
"CAR size is less than __CPROVER_max_malloc_size");
119-
__CPROVER_ssize_t offset = __CPROVER_POINTER_OFFSET(ptr);
119+
__CPROVER_size_t offset = __CPROVER_POINTER_OFFSET(ptr);
120120
__CPROVER_assert(
121-
!(offset > 0) |
122-
((__CPROVER_size_t)offset + size < __CPROVER_max_malloc_size),
121+
!(offset > 0) | (offset + size <= __CPROVER_max_malloc_size),
123122
"no offset bits overflow on CAR upper bound computation");
124123
return (__CPROVER_contracts_car_t){
125124
.is_writable = ptr != 0, .size = size, .lb = ptr, .ub = (char *)ptr + size};
@@ -163,12 +162,11 @@ __CPROVER_HIDE:;
163162
((ptr == 0) | __CPROVER_rw_ok(ptr, size)),
164163
"ptr NULL or writable up to size");
165164
__CPROVER_assert(
166-
size < __CPROVER_max_malloc_size,
165+
size <= __CPROVER_max_malloc_size,
167166
"CAR size is less than __CPROVER_max_malloc_size");
168-
__CPROVER_ssize_t offset = __CPROVER_POINTER_OFFSET(ptr);
167+
__CPROVER_size_t offset = __CPROVER_POINTER_OFFSET(ptr);
169168
__CPROVER_assert(
170-
!(offset > 0) |
171-
((__CPROVER_size_t)offset + size < __CPROVER_max_malloc_size),
169+
!(offset > 0) | (offset + size <= __CPROVER_max_malloc_size),
172170
"no offset bits overflow on CAR upper bound computation");
173171
__CPROVER_contracts_car_t *elem = set->elems + idx;
174172
*elem = (__CPROVER_contracts_car_t){
@@ -783,14 +781,13 @@ __CPROVER_HIDE:;
783781

784782
// Compute the upper bound, perform inclusion check against contract-assigns
785783
__CPROVER_assert(
786-
size < __CPROVER_max_malloc_size,
784+
size <= __CPROVER_max_malloc_size,
787785
"CAR size is less than __CPROVER_max_malloc_size");
788786

789787
__CPROVER_size_t offset = __CPROVER_POINTER_OFFSET(ptr);
790788

791789
__CPROVER_assert(
792-
!(offset > 0) |
793-
((__CPROVER_size_t)offset + size < __CPROVER_max_malloc_size),
790+
!(offset > 0) | (offset + size <= __CPROVER_max_malloc_size),
794791
"no offset bits overflow on CAR upper bound computation");
795792
void *ub = (void *)((char *)ptr + size);
796793
__CPROVER_contracts_car_t *elem = set->contract_assigns.elems;
@@ -1198,7 +1195,7 @@ __CPROVER_HIDE:;
11981195
{
11991196
// When --malloc-may-fail --malloc-fail-null
12001197
// add implicit assumption that the size is capped
1201-
__CPROVER_assume(size < __CPROVER_max_malloc_size);
1198+
__CPROVER_assume(size <= __CPROVER_max_malloc_size);
12021199
}
12031200
else if(
12041201
__CPROVER_malloc_failure_mode ==
@@ -1208,9 +1205,9 @@ __CPROVER_HIDE:;
12081205
// check if max allocation size is exceeded and
12091206
// add implicit assumption that the size is capped
12101207
__CPROVER_assert(
1211-
size < __CPROVER_max_malloc_size,
1208+
size <= __CPROVER_max_malloc_size,
12121209
"__CPROVER_is_fresh max allocation size exceeded");
1213-
__CPROVER_assume(size < __CPROVER_max_malloc_size);
1210+
__CPROVER_assume(size <= __CPROVER_max_malloc_size);
12141211
}
12151212

12161213
void *ptr = __CPROVER_allocate(size, 0);
@@ -1255,16 +1252,16 @@ __CPROVER_HIDE:;
12551252
__CPROVER_malloc_failure_mode ==
12561253
__CPROVER_malloc_failure_mode_return_null)
12571254
{
1258-
__CPROVER_assume(size < __CPROVER_max_malloc_size);
1255+
__CPROVER_assume(size <= __CPROVER_max_malloc_size);
12591256
}
12601257
else if(
12611258
__CPROVER_malloc_failure_mode ==
12621259
__CPROVER_malloc_failure_mode_assert_then_assume)
12631260
{
12641261
__CPROVER_assert(
1265-
size < __CPROVER_max_malloc_size,
1266-
"__CPROVER_is_fresh requires size < __CPROVER_max_malloc_size");
1267-
__CPROVER_assume(size < __CPROVER_max_malloc_size);
1262+
size <= __CPROVER_max_malloc_size,
1263+
"__CPROVER_is_fresh requires size <= __CPROVER_max_malloc_size");
1264+
__CPROVER_assume(size <= __CPROVER_max_malloc_size);
12681265
}
12691266

12701267
void *ptr = __CPROVER_allocate(size, 0);
@@ -1360,8 +1357,8 @@ __CPROVER_HIDE:;
13601357
__CPROVER_assert(
13611358
__CPROVER_same_object(lb, ub),
13621359
"lb and ub pointers must have the same object");
1363-
__CPROVER_ssize_t lb_offset = __CPROVER_POINTER_OFFSET(lb);
1364-
__CPROVER_ssize_t ub_offset = __CPROVER_POINTER_OFFSET(ub);
1360+
__CPROVER_size_t lb_offset = __CPROVER_POINTER_OFFSET(lb);
1361+
__CPROVER_size_t ub_offset = __CPROVER_POINTER_OFFSET(ub);
13651362
__CPROVER_assert(
13661363
lb_offset <= ub_offset, "lb and ub pointers must be ordered");
13671364
if(write_set->assume_requires_ctx | write_set->assume_ensures_ctx)
@@ -1373,14 +1370,14 @@ __CPROVER_HIDE:;
13731370
__CPROVER_size_t offset = __VERIFIER_nondet_size();
13741371

13751372
// this cast is safe because we prove that ub and lb are ordered
1376-
__CPROVER_size_t max_offset = (__CPROVER_size_t)(ub_offset - lb_offset);
1373+
__CPROVER_size_t max_offset = ub_offset - lb_offset;
13771374
__CPROVER_assume(offset <= max_offset);
13781375
*ptr = (char *)lb + offset;
13791376
return 1;
13801377
}
13811378
else /* write_set->assert_requires_ctx | write_set->assert_ensures_ctx */
13821379
{
1383-
__CPROVER_ssize_t offset = __CPROVER_POINTER_OFFSET(*ptr);
1380+
__CPROVER_size_t offset = __CPROVER_POINTER_OFFSET(*ptr);
13841381
return __CPROVER_same_object(lb, *ptr) && lb_offset <= offset &&
13851382
offset <= ub_offset;
13861383
}

0 commit comments

Comments
 (0)