File tree 24 files changed +667
-16
lines changed
assigns-replace-ignored-return-value
assigns_replace_havoc_dependent_targets_fail
assigns_replace_havoc_dependent_targets_pass 24 files changed +667
-16
lines changed Original file line number Diff line number Diff line change
1
+ #include <stdlib.h>
2
+ #include <stdbool.h>
3
+
4
+ int bar (int l , int r )
5
+ __CPROVER_requires (0 <= l && l <= 10 )
6
+ __CPROVER_requires (0 <= r && r <= 10 )
7
+ __CPROVER_assigns ()
8
+ __CPROVER_ensures (__CPROVER_return_value == __CPROVER_old (l ) + __CPROVER_old (r ))
9
+ {
10
+ return l + r ;
11
+ }
12
+
13
+ int * baz (int l , int r )
14
+ __CPROVER_requires (0 <= l && l <= 10 )
15
+ __CPROVER_requires (0 <= r && r <= 10 )
16
+ __CPROVER_assigns ()
17
+ __CPROVER_ensures (* __CPROVER_return_value == __CPROVER_old (l ) + __CPROVER_old (r ))
18
+ {
19
+ int * res = malloc (sizeof (int ));
20
+ * res = l + r ;
21
+ return res ;
22
+ }
23
+
24
+ int foo (int l , int r )
25
+ __CPROVER_requires (0 <= l && l <= 10 )
26
+ __CPROVER_requires (0 <= r && r <= 10 )
27
+ __CPROVER_assigns ()
28
+ __CPROVER_ensures (__CPROVER_return_value == __CPROVER_old (l ) + __CPROVER_old (r ))
29
+ {
30
+ bar (l , r );
31
+ bar (l , r );
32
+ baz (l , r );
33
+ baz (l , r );
34
+ return l + r ;
35
+ }
36
+
37
+ int main ()
38
+ {
39
+ int l ;
40
+ int r ;
41
+ foo (l ,r );
42
+ return 0 ;
43
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --replace-call-with-contract bar --replace-call-with-contract baz --enforce-contract foo
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ ^[.*] Check that .*ignored_return_value.* is assignable: FAILURE
9
+ --
10
+ This test checks that when replacing a call by a contract for a call that
11
+ ignores the return value of the function, the temporary introduced to
12
+ receive the call result does not trigger errors with assigns clause Checking
13
+ in the function under verification.
Original file line number Diff line number Diff line change 4
4
^EXIT=10$
5
5
^SIGNAL=0$
6
6
main.c function bar
7
- ^\[bar.\d+\] line \d+ Check that \*y is assignable: SUCCESS$
8
- ^\[bar.\d+\] line \d+ Check that x is assignable: FAILURE$
7
+ ^\[bar\ .\d+\] line \d+ Check that \*y is assignable: SUCCESS$
8
+ ^\[bar\ .\d+\] line \d+ Check that x \(assigned by the contract of quz\) is assignable: FAILURE
9
9
^VERIFICATION FAILED$
10
10
--
11
11
--
Original file line number Diff line number Diff line change 3
3
--enforce-contract foo --replace-call-with-contract bar _ --pointer-primitive-check
4
4
^EXIT=10$
5
5
^SIGNAL=0$
6
- \[foo.\d+\] line \d+ Check that \*z is assignable: FAILURE$
6
+ \[foo.\d+\] line \d+ Check that \*z \(assigned by the contract of bar\) is assignable: FAILURE$
7
7
^.* 1 of \d+ failed \(\d+ iteration.*\)$
8
8
^VERIFICATION FAILED$
9
9
--
Original file line number Diff line number Diff line change 3
3
--replace-call-with-contract bar --enforce-contract foo
4
4
^EXIT=0$
5
5
^SIGNAL=0$
6
- \[foo.\d+\] line \d+ Check that \*z is assignable: SUCCESS$
6
+ \[foo.\d+\] line \d+ Check that \*z \(assigned by the contract of bar\) is assignable: SUCCESS$
7
7
^VERIFICATION SUCCESSFUL$
8
8
--
9
9
^Condition: \!not\_found$
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main_enforce.c
3
+ --enforce-contract resize_vec _ --signed-overflow-check --unsigned-overflow-check --pointer-overflow-check
4
+ ^VERIFICATION SUCCESSFUL$
5
+ ^EXIT=0$
6
+ ^SIGNAL=0$
7
+ --
8
+ --
9
+ Verifies the contract being replaced in `replace.desc`.
Original file line number Diff line number Diff line change
1
+ #include "vect.h"
2
+
3
+ int main ()
4
+ {
5
+ vect * v ;
6
+ size_t incr ;
7
+ resize_vec (v , incr );
8
+ return 0 ;
9
+ }
Original file line number Diff line number Diff line change
1
+ #include "vect.h"
2
+
3
+ int main ()
4
+ {
5
+ vect * v ;
6
+ resize_vec_incr10 (v );
7
+ return 0 ;
8
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main_replace.c
3
+ --replace-call-with-contract resize_vec --enforce-contract resize_vec_incr10 _ --signed-overflow-check --unsigned-overflow-check --pointer-overflow-check
4
+ ^\[.*\] .* Check that v->size \(assigned by the contract of resize_vec\) is assignable: SUCCESS
5
+ ^\[.*\] .* Check that v->arr \(assigned by the contract of resize_vec\) is assignable: FAILURE
6
+ ^\[.*\] .* Check that POINTER_OBJECT\(\(const void \*\)v->arr\) \(assigned by the contract of resize_vec\) is assignable: FAILURE
7
+ ^VERIFICATION FAILED$
8
+ ^EXIT=10$
9
+ ^SIGNAL=0$
10
+ --
11
+ --
12
+ Shows that when an assigns clause contains targets that are dependent,
13
+ in this case, a pointer variable `v->arr` and
14
+ the object it points to `__CPROVER_POINTER_OBJECT(v->arr)`, we can correctly
15
+ havoc them when replacing the call by the contract.
16
+ In this version of the test the inclusion check must fail.
Original file line number Diff line number Diff line change
1
+ #include <assert.h>
2
+ #include <stdlib.h>
3
+
4
+ typedef struct vect
5
+ {
6
+ char * arr ;
7
+ size_t size ;
8
+ } vect ;
9
+
10
+ void resize_vec (vect * v , size_t incr )
11
+ // clang-format off
12
+ __CPROVER_requires (
13
+ __CPROVER_is_fresh (v , sizeof (vect )) &&
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
+ )
18
+ __CPROVER_assigns (v - > size , v - > arr , __CPROVER_POINTER_OBJECT (v - > arr ))
19
+ __CPROVER_ensures (
20
+ v - > size == __CPROVER_old (v - > size ) + __CPROVER_old (incr ) &&
21
+ __CPROVER_is_fresh (v - > arr , v - > size )
22
+ )
23
+ // clang-format on
24
+ {
25
+ free (v -> arr );
26
+ v -> size += incr ;
27
+ v -> arr = malloc (v -> size );
28
+ return ;
29
+ }
30
+
31
+ void resize_vec_incr10 (vect * v )
32
+ // clang-format off
33
+ __CPROVER_requires (
34
+ __CPROVER_is_fresh (v , sizeof (vect )) &&
35
+ 0 < v - > size && v - > size <= __CPROVER_max_malloc_size &&
36
+ v - > size + 10 < __CPROVER_max_malloc_size &&
37
+ __CPROVER_is_fresh (v - > arr , v - > size )
38
+ )
39
+ __CPROVER_assigns (v - > size )
40
+ __CPROVER_ensures (
41
+ v - > size == __CPROVER_old (v - > size ) + 10 &&
42
+ __CPROVER_is_fresh (v - > arr , v - > size )
43
+ )
44
+ // clang-format on
45
+ {
46
+ resize_vec (v , 10 );
47
+ return ;
48
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main_enforce.c
3
+ --enforce-contract resize_vec _ --signed-overflow-check --unsigned-overflow-check --pointer-overflow-check
4
+ ^VERIFICATION SUCCESSFUL$
5
+ ^EXIT=0$
6
+ ^SIGNAL=0$
7
+ --
8
+ --
9
+ Verifies the contract being replaced in `replace.desc`.
Original file line number Diff line number Diff line change
1
+ #include "vect.h"
2
+
3
+ int main ()
4
+ {
5
+ vect * v ;
6
+ size_t incr ;
7
+ resize_vec (v , incr );
8
+ return 0 ;
9
+ }
Original file line number Diff line number Diff line change
1
+ #include "vect.h"
2
+
3
+ int main ()
4
+ {
5
+ vect * v ;
6
+ resize_vec_incr10 (v );
7
+ return 0 ;
8
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main_replace.c
3
+ --replace-call-with-contract resize_vec --enforce-contract resize_vec_incr10 _ --signed-overflow-check --unsigned-overflow-check --pointer-overflow-check
4
+ ^VERIFICATION SUCCESSFUL$
5
+ ^\[.*\] .* Check that v->size \(assigned by the contract of resize_vec\) is assignable: SUCCESS
6
+ ^\[.*\] .* Check that v->arr \(assigned by the contract of resize_vec\) is assignable: SUCCESS
7
+ ^\[.*\] .* Check that POINTER_OBJECT\(\(const void \*\)v->arr\) \(assigned by the contract of resize_vec\) is assignable: SUCCESS
8
+ ^EXIT=0$
9
+ ^SIGNAL=0$
10
+ --
11
+ --
12
+ Shows that when an assigns clause contains targets that are dependent,
13
+ in this case, a pointer variable `v->arr` and
14
+ the object it points to `__CPROVER_POINTER_OBJECT(v->arr)`, we can correctly
15
+ havoc them when replacing the call by the contract.
16
+ In this version of the test the inclusion check must pass.
Original file line number Diff line number Diff line change
1
+ #include <assert.h>
2
+ #include <stdlib.h>
3
+
4
+ typedef struct vect
5
+ {
6
+ char * arr ;
7
+ size_t size ;
8
+ } vect ;
9
+
10
+ void resize_vec (vect * v , size_t incr )
11
+ // clang-format off
12
+ __CPROVER_requires (
13
+ __CPROVER_is_fresh (v , sizeof (vect )) &&
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
+ )
18
+ __CPROVER_assigns (v - > size , v - > arr , __CPROVER_POINTER_OBJECT (v - > arr ))
19
+ __CPROVER_ensures (
20
+ v - > size == __CPROVER_old (v - > size ) + __CPROVER_old (incr ) &&
21
+ __CPROVER_is_fresh (v - > arr , v - > size )
22
+ )
23
+ // clang-format on
24
+ {
25
+ free (v -> arr );
26
+ v -> size += incr ;
27
+ v -> arr = malloc (v -> size );
28
+ return ;
29
+ }
30
+
31
+ void resize_vec_incr10 (vect * v )
32
+ // clang-format off
33
+ __CPROVER_requires (
34
+ __CPROVER_is_fresh (v , sizeof (vect )) &&
35
+ 0 < v - > size && v - > size <= __CPROVER_max_malloc_size &&
36
+ v - > size + 10 < __CPROVER_max_malloc_size &&
37
+ __CPROVER_is_fresh (v - > arr , v - > size )
38
+ )
39
+ __CPROVER_assigns (* v , __CPROVER_POINTER_OBJECT (v - > arr ))
40
+ __CPROVER_ensures (
41
+ v - > size == __CPROVER_old (v - > size ) + 10 &&
42
+ __CPROVER_is_fresh (v - > arr , v - > size )
43
+ )
44
+ // clang-format on
45
+ {
46
+ resize_vec (v , 10 );
47
+ return ;
48
+ }
Original file line number Diff line number Diff line change
1
+ #include <stdio.h>
2
+
3
+ int foo (int l )
4
+ __CPROVER_requires (-10 <= l && l <= 10 )
5
+ __CPROVER_ensures (__CPROVER_return_value == __CPROVER_old (l ) + __CPROVER_old (10 ))
6
+ {
7
+ return l + 10 ;
8
+ }
9
+
10
+ int main ()
11
+ {
12
+ int l ;
13
+ __CPROVER_assume (-10 <= l && l <= 10 );
14
+ foo (l );
15
+ return 0 ;
16
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --enforce-contract foo
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ ^Tracking history of constant expressions is not supported yet
9
+ --
10
+ This test checks that history variables are supported for constant expressions.
Original file line number Diff line number Diff line change
1
+ #include <stdio.h>
2
+
3
+ long bar (long l , long r )
4
+ __CPROVER_requires (-10 <= l && l <= 10 )
5
+ __CPROVER_requires (-10 <= r && r <= 10 )
6
+ __CPROVER_ensures (__CPROVER_return_value == __CPROVER_old (l ) + __CPROVER_old (r ))
7
+ {
8
+ return l + r ;
9
+ }
10
+
11
+ int foo (int l , int r )
12
+ __CPROVER_requires (-10 <= l && l <= 10 )
13
+ __CPROVER_requires (-10 <= r && r <= 10 )
14
+ __CPROVER_ensures (__CPROVER_return_value == __CPROVER_old (l ) + __CPROVER_old (r ))
15
+ {
16
+ return bar ((long )l , (long )r );
17
+ }
18
+
19
+ int main ()
20
+ {
21
+ int n ;
22
+ __CPROVER_assume (-10 <= n && n <= 10 );
23
+ foo (n ,n );
24
+ return 0 ;
25
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --replace-call-with-contract bar --enforce-contract foo
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ ^Tracking history of typecast expressions is not supported yet
9
+ --
10
+ This test checks that history variables are supported for typecast expressions.
Original file line number Diff line number Diff line change @@ -18,6 +18,7 @@ SRC = accelerate/accelerate.cpp \
18
18
call_sequences.cpp \
19
19
contracts/assigns.cpp \
20
20
contracts/contracts.cpp \
21
+ contracts/havoc_assigns_clause_targets.cpp \
21
22
contracts/memory_predicates.cpp \
22
23
contracts/utils.cpp \
23
24
concurrency.cpp \
You can’t perform that action at this time.
0 commit comments