|
| 1 | +#include <assert.h> |
| 2 | +#include <stdbool.h> |
| 3 | +#include <stdlib.h> |
| 4 | +typedef struct list_t |
| 5 | +{ |
| 6 | + int value; |
| 7 | + struct list_t *next; |
| 8 | +} list_t; |
| 9 | + |
| 10 | +// true iff list of len max_len with values in [-10,10] |
| 11 | +bool is_list(list_t *l, size_t len) |
| 12 | +{ |
| 13 | + if(len == 0) |
| 14 | + return l == NULL; |
| 15 | + else |
| 16 | + return __CPROVER_is_fresh(l, sizeof(*l)) && |
| 17 | + (-10 <= l->value && l->value <= 10) && is_list(l->next, len - 1); |
| 18 | +} |
| 19 | + |
| 20 | +typedef struct buffer_t |
| 21 | +{ |
| 22 | + size_t size; |
| 23 | + char *arr; |
| 24 | + char *cursor; |
| 25 | +} buffer_t; |
| 26 | + |
| 27 | +typedef struct double_buffer_t |
| 28 | +{ |
| 29 | + buffer_t *first; |
| 30 | + buffer_t *second; |
| 31 | +} double_buffer_t; |
| 32 | + |
| 33 | +bool is_sized_array(char *arr, size_t size) |
| 34 | +{ |
| 35 | + return __CPROVER_is_fresh(arr, size); |
| 36 | +} |
| 37 | + |
| 38 | +bool is_ranged_cursor(char *cursor, char *arr, size_t size) |
| 39 | +{ |
| 40 | + void *lb = arr; |
| 41 | + void *ub = arr + size; |
| 42 | + return __CPROVER_pointer_in_range_dfcc(lb, cursor, ub); |
| 43 | +} |
| 44 | + |
| 45 | +bool is_buffer(buffer_t *b) |
| 46 | +{ |
| 47 | + return __CPROVER_is_fresh(b, sizeof(*b)) && (0 < b->size && b->size <= 10) && |
| 48 | + is_sized_array(b->arr, b->size) && |
| 49 | + is_ranged_cursor(b->cursor, b->arr, b->size); |
| 50 | +} |
| 51 | + |
| 52 | +bool is_double_buffer(double_buffer_t *b) |
| 53 | +{ |
| 54 | + return __CPROVER_is_fresh(b, sizeof(*b)) && is_buffer(b->first) && |
| 55 | + is_buffer(b->second); |
| 56 | +} |
| 57 | + |
| 58 | +int bar(list_t *l) |
| 59 | + // clang-format off |
| 60 | + __CPROVER_requires(is_list(l, 3)) |
| 61 | + __CPROVER_ensures(-30 <= __CPROVER_return_value && |
| 62 | + __CPROVER_return_value <= 30) |
| 63 | +// clang-format on |
| 64 | +{ |
| 65 | + return l->value + l->next->value + l->next->next->value; |
| 66 | +} |
| 67 | + |
| 68 | +int baz(double_buffer_t *b) |
| 69 | + // clang-format off |
| 70 | + __CPROVER_requires(is_double_buffer(b)) |
| 71 | + __CPROVER_ensures(2 <= __CPROVER_return_value && |
| 72 | + __CPROVER_return_value <= 20) |
| 73 | +// clang-format on |
| 74 | +{ |
| 75 | + return b->first->size + b->second->size; |
| 76 | +} |
| 77 | + |
| 78 | +int foo(list_t *l, double_buffer_t *b) |
| 79 | + // clang-format off |
| 80 | + __CPROVER_requires(is_list(l, 3)) |
| 81 | + __CPROVER_requires(is_double_buffer(b)) |
| 82 | + __CPROVER_ensures(-28 <= __CPROVER_return_value && |
| 83 | + __CPROVER_return_value <= 50) |
| 84 | +// clang-format on |
| 85 | +{ |
| 86 | + return bar(l) + baz(b); |
| 87 | +} |
| 88 | + |
| 89 | +int main() |
| 90 | +{ |
| 91 | + list_t *l; |
| 92 | + double_buffer_t *b; |
| 93 | + int return_value = foo(l, b); |
| 94 | +} |
0 commit comments