File tree 22 files changed +275
-59
lines changed
regression/contracts-dfcc
assigns-enforce-malloc-zero
assigns_replace_havoc_dependent_targets_fail
assigns_replace_havoc_dependent_targets_pass
function-pointer-contracts-enforce
memory-predicates-is-fresh-failure-modes
memory-predicates-is-fresh-requires-max-malloc-size
memory-predicates-pointer-in-range-requires
memory-predicates-pointer-in-range-typecheck-failure-01
memory-predicates-pointer-in-range-typecheck-failure-02
goto-instrument/contracts/doc/user
22 files changed +275
-59
lines changed Original file line number Diff line number Diff line change 7
7
^SIGNAL=0$
8
8
^VERIFICATION SUCCESSFUL$
9
9
--
10
- This test checks assuming is_fresh(ptr, size) with a non-deterministic size
11
- does not result in spurious falsifications when checking assigns clauses .
12
- An implicit strict upper bound of __CPROVER_max_malloc_size is imposed on the size by
13
- __CPROVER_is_fresh which guarantees the absence of pointer overflow when computing
14
- the address `ptr + size` .
10
+ This test checks that assuming is_fresh(ptr, size) with a non-deterministic size
11
+ checks that size < __CPROVER_max_malloc_size and then assumes it .
12
+ This guarantees that the address `ptr + size` can always be computed and
13
+ represented without offset bits overflowing into the object bits in the pointer
14
+ model used by CBMC .
Original file line number Diff line number Diff line change @@ -11,9 +11,9 @@ void resize_vec(vect *v, size_t incr)
11
11
// clang-format off
12
12
__CPROVER_requires (
13
13
__CPROVER_is_fresh (v , sizeof (vect )) &&
14
- __CPROVER_is_fresh ( v - > arr , v - > size ) &&
15
- 0 < v - > size && v - > size <= __CPROVER_max_malloc_size &&
16
- 0 < incr && incr < __CPROVER_max_malloc_size - v - > size
14
+ 0 < v - > size && v - > size < __CPROVER_max_malloc_size &&
15
+ 0 < incr && incr < __CPROVER_max_malloc_size - v - > size &&
16
+ __CPROVER_is_fresh ( v - > arr , v - > size )
17
17
)
18
18
__CPROVER_assigns (v - > size , v - > arr , __CPROVER_object_whole (v - > arr ))
19
19
__CPROVER_frees (v - > arr )
@@ -34,9 +34,9 @@ void resize_vec_incr10(vect *v)
34
34
// clang-format off
35
35
__CPROVER_requires (
36
36
__CPROVER_is_fresh (v , sizeof (vect )) &&
37
- __CPROVER_is_fresh ( v - > arr , v - > size ) &&
38
- 0 < v - > size && v - > size <= __CPROVER_max_malloc_size &&
39
- v - > size + 10 < __CPROVER_max_malloc_size
37
+ 0 < v - > size && v - > size < __CPROVER_max_malloc_size &&
38
+ v - > size + 10 < __CPROVER_max_malloc_size &&
39
+ __CPROVER_is_fresh ( v - > arr , v - > size )
40
40
)
41
41
__CPROVER_assigns (v - > size )
42
42
__CPROVER_ensures (
Original file line number Diff line number Diff line change @@ -11,8 +11,8 @@ void resize_vec(vect *v, size_t incr)
11
11
// clang-format off
12
12
__CPROVER_requires (
13
13
__CPROVER_is_fresh (v , sizeof (vect )) &&
14
+ 0 < v - > size && v - > size < __CPROVER_max_malloc_size &&
14
15
__CPROVER_is_fresh (v - > arr , v - > size ) &&
15
- 0 < v - > size && v - > size <= __CPROVER_max_malloc_size &&
16
16
0 < incr && incr < __CPROVER_max_malloc_size - v - > size
17
17
)
18
18
__CPROVER_assigns (v - > size , v - > arr , __CPROVER_object_whole (v - > arr ))
@@ -34,8 +34,8 @@ void resize_vec_incr10(vect *v)
34
34
// clang-format off
35
35
__CPROVER_requires (
36
36
__CPROVER_is_fresh (v , sizeof (vect )) &&
37
+ 0 < v - > size && v - > size < __CPROVER_max_malloc_size &&
37
38
__CPROVER_is_fresh (v - > arr , v - > size ) &&
38
- 0 < v - > size && v - > size <= __CPROVER_max_malloc_size &&
39
39
v - > size + 10 < __CPROVER_max_malloc_size
40
40
)
41
41
__CPROVER_assigns (* v , __CPROVER_object_whole (v - > arr ))
Original file line number Diff line number Diff line change @@ -9,7 +9,7 @@ typedef void (*arr_fun_t)(char *arr, size_t size);
9
9
// resets the first element to zero
10
10
void arr_fun_contract (char * arr , size_t size )
11
11
// clang-format off
12
- __CPROVER_requires (size > 0 && __CPROVER_is_fresh (arr , size ))
12
+ __CPROVER_requires (0 < size && __CPROVER_is_fresh (arr , size ))
13
13
__CPROVER_assigns (arr [0 ])
14
14
__CPROVER_ensures (arr [0 ] == 0 )
15
15
// clang-format on
Original file line number Diff line number Diff line change 1
1
CORE
2
2
main.c
3
- --restrict-function-pointer foo.CALL/arr_fun_contract --dfcc main --enforce-contract foo
3
+ --malloc-may-fail --malloc-fail-null -- restrict-function-pointer foo.CALL/arr_fun_contract --dfcc main --enforce-contract foo
4
4
^EXIT=0$
5
5
^SIGNAL=0$
6
6
^VERIFICATION SUCCESSFUL$
Original file line number Diff line number Diff line change @@ -6,7 +6,8 @@ __CPROVER_requires(__CPROVER_is_fresh(arr, size))
6
6
__CPROVER_assigns (__CPROVER_object_from (arr ))
7
7
// clang-format on
8
8
{
9
- assert (__CPROVER_same_object (arr , arr + size ));
9
+ __CPROVER_assert (arr != NULL , "arr is not NULL" );
10
+ __CPROVER_assert (size < __CPROVER_max_malloc_size , "size is capped" );
10
11
if (size > 0 )
11
12
{
12
13
arr [0 ] = 0 ;
Original file line number Diff line number Diff line change
1
+ #include <stdlib.h>
2
+
3
+ const size_t MAX_SIZE = 5000000 ;
4
+ void foo (char * arr , size_t size )
5
+ // clang-format off
6
+ __CPROVER_requires (size < MAX_SIZE )
7
+ __CPROVER_requires (__CPROVER_is_fresh (arr , size ))
8
+ __CPROVER_assigns (__CPROVER_object_from (arr ))
9
+ // clang-format on
10
+ {
11
+ __CPROVER_assert (arr != NULL , "arr is not NULL" );
12
+ __CPROVER_assert (size < __CPROVER_max_malloc_size , "size is capped" );
13
+ if (size > 0 )
14
+ {
15
+ arr [0 ] = 0 ;
16
+ arr [size - 1 ] = 0 ;
17
+ }
18
+ }
19
+
20
+ int main ()
21
+ {
22
+ char * arr ;
23
+ size_t size ;
24
+ foo (arr , size );
25
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main_bounded.c
3
+ --malloc-may-fail --malloc-fail-assert --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check --pointer-overflow-check
4
+ ^\[__CPROVER_contracts_is_fresh.assertion.\d+\] line \d+ __CPROVER_is_fresh max allocation size exceeded: SUCCESS$
5
+ ^\[__CPROVER_contracts_car_set_insert.assertion.\d+\] line \d+ CAR size is less than __CPROVER_max_malloc_size: SUCCESS$
6
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ ptr NULL or writable up to size: SUCCESS$
7
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ no offset bits overflow on CAR upper bound computation: SUCCESS$
8
+ ^\[foo.assertion.\d+\] line \d+ size is capped: SUCCESS$
9
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)0\] is assignable: SUCCESS$
10
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)\(size - \(.*\)1\)\] is assignable: SUCCESS$
11
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
12
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
13
+ ^\[foo.pointer_dereference.\d+\] line \d+ dereference failure: pointer outside object bounds in arr\[\(.*\)\(size - \(.*\)1\)\]: SUCCESS$
14
+ ^EXIT=0$
15
+ ^SIGNAL=0$
16
+ ^VERIFICATION SUCCESSFUL$
17
+ --
18
+ --
19
+ This tests shows that using is_fresh with --malloc-fail-assert active and
20
+ imposing a limit on the size parameter succeeds.
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --malloc-may-fail --malloc-fail-assert --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check --pointer-overflow-check
4
+ ^\[__CPROVER_contracts_is_fresh.assertion.\d+\] line \d+ __CPROVER_is_fresh max allocation size exceeded: FAILURE$
5
+ ^\[__CPROVER_contracts_car_set_insert.assertion.\d+\] line \d+ CAR size is less than __CPROVER_max_malloc_size: SUCCESS$
6
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ ptr NULL or writable up to size: SUCCESS$
7
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ no offset bits overflow on CAR upper bound computation: SUCCESS$
8
+ ^\[foo.assertion.\d+\] line \d+ size is capped: SUCCESS$
9
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)0\] is assignable: SUCCESS$
10
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)\(size - \(.*\)1\)\] is assignable: SUCCESS$
11
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
12
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
13
+ ^\[foo.pointer_dereference.\d+\] line \d+ dereference failure: pointer outside object bounds in arr\[\(.*\)\(size - \(.*\)1\)\]: SUCCESS$
14
+ ^EXIT=10$
15
+ ^SIGNAL=0$
16
+ ^VERIFICATION FAILED$
17
+ --
18
+ --
19
+ This tests shows that using is_fresh with --malloc-fail-assert active and
20
+ without imposing a limit on the size parameter results in an failed assertion
21
+ in is_fresh that detects that the size may be too large, but also results in an
22
+ implicit assumption that the size is less than the maximum allocation size
23
+ (just like when used with malloc).
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main_bounded.c
3
+ --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check --pointer-overflow-check
4
+ ^\[__CPROVER_contracts_car_set_insert.assertion.\d+\] line \d+ CAR size is less than __CPROVER_max_malloc_size: SUCCESS$
5
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ ptr NULL or writable up to size: SUCCESS$
6
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ no offset bits overflow on CAR upper bound computation: SUCCESS$
7
+ ^\[foo.assertion.\d+\] line \d+ size is capped: SUCCESS$
8
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)0\] is assignable: SUCCESS$
9
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)\(size - \(.*\)1\)\] is assignable: SUCCESS$
10
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
11
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
12
+ ^\[foo.pointer_dereference.\d+\] line \d+ dereference failure: pointer outside object bounds in arr\[\(.*\)\(size - \(.*\)1\)\]: SUCCESS$
13
+ ^EXIT=0$
14
+ ^SIGNAL=0$
15
+ ^VERIFICATION SUCCESSFUL$
16
+ --
17
+ --
18
+ This tests shows that using is_fresh without malloc failure modes active and
19
+ imposing a limit on the size parameter succeeds.
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check --pointer-overflow-check
4
+ ^\[__CPROVER_contracts_car_set_insert.assertion.\d+\] line \d+ CAR size is less than __CPROVER_max_malloc_size: FAILURE$
5
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ ptr NULL or writable up to size: FAILURE$
6
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ no offset bits overflow on CAR upper bound computation: FAILURE$
7
+ ^\[foo.assertion.\d+\] line \d+ size is capped: FAILURE$
8
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)0\] is assignable: FAILURE$
9
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)\(size - \(.*\)1\)\] is assignable: FAILURE$
10
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): FAILURE$
11
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): FAILURE$
12
+ ^\[foo.pointer_dereference.\d+\] line \d+ dereference failure: pointer outside object bounds in arr\[\(.*\)\(size - \(.*\)1\)\]: FAILURE$
13
+ ^EXIT=10$
14
+ ^SIGNAL=0$
15
+ ^VERIFICATION FAILED$
16
+ --
17
+ --
18
+ This tests shows that using is_fresh without malloc failure modes active and
19
+ without imposing a limit on the size parameter results in failures:
20
+ 1. in the contracts library because the addressable range of the allocated object
21
+ cannot be represented without pointer overflow
22
+ 2. in the assigns clause checking because the assignable range cannot be represented
23
+ 3. in pointer overflow checks generated by CBMC pointer checks
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main_bounded.c
3
+ --malloc-may-fail --malloc-fail-null --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check --pointer-overflow-check
4
+ ^\[__CPROVER_contracts_car_set_insert.assertion.\d+\] line \d+ CAR size is less than __CPROVER_max_malloc_size: SUCCESS$
5
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ ptr NULL or writable up to size: SUCCESS$
6
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ no offset bits overflow on CAR upper bound computation: SUCCESS$
7
+ ^\[foo.assertion.\d+\] line \d+ size is capped: SUCCESS$
8
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)0\] is assignable: SUCCESS$
9
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)\(size - \(.*\)1\)\] is assignable: SUCCESS$
10
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
11
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
12
+ ^\[foo.pointer_dereference.\d+\] line \d+ dereference failure: pointer outside object bounds in arr\[\(.*\)\(size - \(.*\)1\)\]: SUCCESS$
13
+ ^EXIT=0$
14
+ ^SIGNAL=0$
15
+ ^VERIFICATION SUCCESSFUL$
16
+ --
17
+ --
18
+ This tests shows that using is_fresh with --malloc-fail-null active and
19
+ imposing a limit on the size parameter succeeds.
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --malloc-may-fail --malloc-fail-null --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check --pointer-overflow-check
4
+ ^\[__CPROVER_contracts_car_set_insert.assertion.\d+\] line \d+ CAR size is less than __CPROVER_max_malloc_size: SUCCESS$
5
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ ptr NULL or writable up to size: SUCCESS$
6
+ ^\[__CPROVER_contracts_write_set_check_assignment.assertion.\d+\] line \d+ no offset bits overflow on CAR upper bound computation: SUCCESS$
7
+ ^\[foo.assertion.\d+\] line \d+ size is capped: SUCCESS$
8
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)0\] is assignable: SUCCESS$
9
+ ^\[foo.assigns.\d+\] line \d+ Check that arr\[\(.*\)\(size - \(.*\)1\)\] is assignable: SUCCESS$
10
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
11
+ ^\[foo.pointer_arithmetic.\d+\] line \d+ pointer arithmetic: pointer outside object bounds in arr \+ \(.*\)\(size - \(.*\)1\): SUCCESS$
12
+ ^\[foo.pointer_dereference.\d+\] line \d+ dereference failure: pointer outside object bounds in arr\[\(.*\)\(size - \(.*\)1\)\]: SUCCESS$
13
+ ^EXIT=0$
14
+ ^SIGNAL=0$
15
+ ^VERIFICATION SUCCESSFUL$
16
+ --
17
+ --
18
+ This tests shows that using is_fresh with --malloc-fail-null active and
19
+ without imposing a limit on the size parameter results in an implicit assumption
20
+ that the size is less than the maximum allocation size
21
+ (just like malloc does, except is_fresh does not fail).
Load Diff This file was deleted.
Original file line number Diff line number Diff line change 3
3
4
4
void foo (char * arr , size_t size , char * cur )
5
5
// clang-format off
6
- __CPROVER_requires (
7
- (0 < size && size < __CPROVER_max_malloc_size ) &&
8
- __CPROVER_is_fresh (arr , size ) &&
6
+ __CPROVER_requires (0 < size && __CPROVER_is_fresh (arr , size ) &&
9
7
__CPROVER_pointer_in_range_dfcc (arr , cur , arr + size ))
10
8
__CPROVER_ensures (__CPROVER_pointer_in_range_dfcc (arr , cur , arr + size ))
11
9
// clang-format on
Original file line number Diff line number Diff line change 1
1
CORE
2
2
main.c
3
- --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check
3
+ --malloc-may-fail --malloc-fail-null -- dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check
4
4
^EXIT=0$
5
5
^SIGNAL=0$
6
6
^VERIFICATION SUCCESSFUL$
Original file line number Diff line number Diff line change 3
3
4
4
void foo (char * arr , size_t size , char * cur )
5
5
// clang-format off
6
- __CPROVER_requires (
7
- (0 < size && size < __CPROVER_max_malloc_size ) &&
8
- __CPROVER_is_fresh (arr , size ) &&
6
+ __CPROVER_requires (0 < size && __CPROVER_is_fresh (arr , size ) &&
9
7
__CPROVER_pointer_in_range_dfcc (arr , cur , arr + size ))
10
8
__CPROVER_ensures (__CPROVER_pointer_in_range_dfcc (
11
9
arr , cur /*, arr + size missing arg */ ))
Original file line number Diff line number Diff line change 1
1
CORE
2
2
main.c
3
- --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check
3
+ --malloc-may-fail --malloc-fail-null -- dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check
4
4
^.*error: __CPROVER_pointer_in_range_dfcc expects three arguments$
5
5
^EXIT=(1|64)$
6
6
^SIGNAL=0$
Original file line number Diff line number Diff line change 3
3
4
4
void foo (char * arr , size_t size , char * cur )
5
5
// clang-format off
6
- __CPROVER_requires (
7
- (0 < size && size < __CPROVER_max_malloc_size ) &&
8
- __CPROVER_is_fresh (arr , size ) &&
9
- __CPROVER_pointer_in_range_dfcc (arr , cur , arr + size ))
6
+ __CPROVER_requires (0 < size && __CPROVER_is_fresh (arr , size ) &&
7
+ __CPROVER_pointer_in_range_dfcc (arr , cur , arr + size ))
10
8
__CPROVER_ensures (__CPROVER_pointer_in_range_dfcc (
11
9
arr , cur , 2 /* wrong type arg */ ))
12
10
// clang-format on
Original file line number Diff line number Diff line change 1
1
CORE
2
2
main.c
3
- --dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check
3
+ --malloc-may-fail --malloc-fail-null -- dfcc main --enforce-contract foo _ --pointer-check --pointer-primitive-check
4
4
^.*error: __CPROVER_pointer_in_range_dfcc expects pointer-typed arguments$
5
5
^EXIT=(1|64)$
6
6
^SIGNAL=0$
You can’t perform that action at this time.
0 commit comments