|
1 | 1 | #include <assert.h>
|
2 | 2 | #include <stdbool.h>
|
3 |
| -#include <stddef.h> |
4 |
| -#include <stdint.h> |
5 | 3 | #include <stdlib.h>
|
6 | 4 |
|
7 |
| -bool dummy_for_definitions(int *n) |
8 |
| -{ |
9 |
| - assert(__CPROVER_is_fresh(&n, sizeof(int))); |
10 |
| - int *x = malloc(sizeof(int)); |
11 |
| -} |
12 |
| - |
13 | 5 | bool ptr_ok(int *x)
|
14 | 6 | {
|
15 |
| - return *x < 5; |
16 |
| -} |
17 |
| - |
18 |
| -/* |
19 |
| - Here are the meanings of the predicates: |
20 |
| -
|
21 |
| -static _Bool __foo_memory_map[__CPROVER_constant_infinity_uint]; |
22 |
| -
|
23 |
| -bool __foo_requires_is_fresh(void **elem, size_t size) { |
24 |
| - *elem = malloc(size); |
25 |
| - if (!*elem || (__foo_memory_map[__CPROVER_POINTER_OBJECT(*elem)] != 0)) return false; |
26 |
| -
|
27 |
| - __foo_memory_map[__CPROVER_POINTER_OBJECT(*elem)] = 1; |
28 |
| - return true; |
| 7 | + return 0 < *x && *x < 5; |
29 | 8 | }
|
30 | 9 |
|
31 |
| -bool __foo_ensures_is_fresh(void *elem, size_t size) { |
32 |
| - bool ok = (__foo_memory_map[__CPROVER_POINTER_OBJECT(elem)] == 0 && |
33 |
| - __CPROVER_r_ok(elem, size)); |
34 |
| - __foo_memory_map[__CPROVER_POINTER_OBJECT(elem)] = 1; |
35 |
| - return ok; |
36 |
| -} |
37 |
| -
|
38 |
| -
|
39 |
| -_Bool __call_foo_requires_is_fresh(void *elem, size_t size) { |
40 |
| - _Bool r_ok = __CPROVER_r_ok(elem, size); |
41 |
| - if (!__CPROVER_r_ok(elem, size) || |
42 |
| - __foo_memory_map[__CPROVER_POINTER_OBJECT(elem)]) return 0; |
43 |
| - __foo_memory_map[__CPROVER_POINTER_OBJECT(elem)] = 1; |
44 |
| - return 1; |
45 |
| -} |
46 |
| -
|
47 |
| -// In the calling context, we assume freshness means new |
48 |
| -// allocation from within the function. |
49 |
| -bool __call_foo_ensures_is_fresh(void **elem, size_t size) { |
50 |
| - *elem = malloc(size); |
51 |
| - return (*elem != NULL); |
52 |
| -} |
53 |
| -*/ |
54 |
| - |
55 | 10 | bool return_ok(int ret_value, int *x)
|
56 | 11 | {
|
57 |
| - int a; |
58 |
| - a = *x; |
59 |
| - return ret_value == *x + 5; |
| 12 | + return ret_value == (*x + 5); |
60 | 13 | }
|
61 | 14 |
|
62 |
| -// The 'ensures' __CPROVER_is_fresh test is unnecessary, but left in just to test the function is working correctly. |
63 |
| -// If you remove the negation, the program will fail, because 'x' is not fresh. |
64 |
| - |
65 |
| -int foo(int *x, int y) __CPROVER_assigns(*x) |
66 |
| - __CPROVER_requires(__CPROVER_is_fresh(x, sizeof(int)) && *x > 0 && ptr_ok(x)) |
67 |
| - __CPROVER_ensures( |
68 |
| - !ptr_ok(x) && !__CPROVER_is_fresh(x, sizeof(int)) && |
69 |
| - return_ok(__CPROVER_return_value, x)) |
| 15 | +int foo(int *x) |
| 16 | + // clang-format off |
| 17 | +__CPROVER_requires(__CPROVER_is_fresh(x, sizeof(int))) |
| 18 | +__CPROVER_requires(ptr_ok(x)) |
| 19 | +__CPROVER_assigns(*x) |
| 20 | +__CPROVER_ensures(!ptr_ok(x)) |
| 21 | +__CPROVER_ensures(return_ok(__CPROVER_return_value, x)) |
| 22 | +// clang-format on |
70 | 23 | {
|
71 | 24 | *x = *x + 4;
|
72 |
| - int y = *x + 5; |
73 | 25 | return *x + 5;
|
74 | 26 | }
|
75 | 27 |
|
76 |
| -int main() |
| 28 | +void main() |
77 | 29 | {
|
78 |
| - int *n = malloc(sizeof(int)); |
79 |
| - assert(__CPROVER_r_ok(n, sizeof(int))); |
80 |
| - *n = 3; |
81 |
| - int o = foo(n, 10); |
82 |
| - assert(o >= 10 && o == *n + 5); |
83 |
| - return 0; |
| 30 | + int x; |
| 31 | + int *_x = &x; |
| 32 | + if(ptr_ok(_x)) |
| 33 | + { |
| 34 | + int ret_val = foo(_x); |
| 35 | + assert(!ptr_ok(_x)); |
| 36 | + assert(return_ok(ret_val, _x)); |
| 37 | + } |
84 | 38 | }
|
0 commit comments