Skip to content

Commit 324bfc7

Browse files
committed
---
yaml --- r: 83303 b: refs/heads/variant-submodule c: 2c32f86 h: refs/heads/develop i: 83301: f384b98 83299: 5ada16b 83295: 6b5139e
1 parent 2bddfcd commit 324bfc7

File tree

6 files changed

+145
-147
lines changed

6 files changed

+145
-147
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ refs/heads/unwind-counters4: 57aedaa3fe3995b30ba69c96c9f04df79f8e8ff8
131131
refs/heads/value-set-make-member: 0f8404cb460f55d43bc253e12f1bde7fd7ed4d37
132132
refs/heads/value-set-member-fix: 2c87bd4c0d9e1954e2de6af0118fa1ef296ae548
133133
"refs/heads/value_set_fi_hacks": 3d243543adb4ff450596e7994e2fa1d590ec1e1b
134-
refs/heads/variant-submodule: a0646ecf24dfe0686ad5b2eedde0144d839185b2
134+
refs/heads/variant-submodule: 2c32f86edeb62a6fbb39268e605f2299bcbedd87
135135
refs/heads/windows-console-streambuf: b984ac7bd772da956bb5656f0072d85b3fdbbf34
136136
refs/tags/cbmc-5.10: 097cf712f57d59cff9c53a9fb7b9b81be1245f93
137137
refs/tags/cbmc-5.11: 90d0de91b0918c9e5d5ed250cae62241ae38392a

branches/variant-submodule/doc/cprover-manual/contracts-assigns.md

Lines changed: 56 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
__CPROVER_assigns(*identifier*, ...)
77
```
88
9-
An _assigns_ clause allows the user to specify that a memory location may be written by a function. The set of locations writable by a function is the union of the locations specified by the assigns clauses, or the empty set of no _assigns_ clause is specified. While, in general, an _assigns_ clause could be interpreted with wither _writes_ or _modifies_ semantics, this
9+
An _assigns_ clause allows the user to specify that a memory location may be written by a function. The set of locations writable by a function is the union of the locations specified by the assigns clauses, or the empty set of no _assigns_ clause is specified. While, in general, an _assigns_ clause could be interpreted with either _writes_ or _modifies_ semantics, this
1010
design is based on the former. This means that memory not captured by an
1111
_assigns_ clause must not be written within the given function, even if the
1212
value(s) therein are not modified.
@@ -15,10 +15,11 @@ value(s) therein are not modified.
1515
1616
An _assigns_ clause currently supports simple variable types and their pointers,
1717
structs, and arrays. Recursive pointer structures are left to future work, as
18-
their support would require changes to CBMC's memory model. For example,
18+
their support would require changes to CBMC's memory model.
1919
2020
```c
21-
int *err_signal; // Global variable
21+
/* Examples */
22+
int err_signal; // Global variable
2223
2324
int sum(const uint32_t a, const uint32_t b, uint32_t* out)
2425
__CPROVER_assigns(*out)
@@ -49,10 +50,10 @@ int sum(const uint32_t a, const uint32_t b, uint32_t* out)
4950
/* Writable Set */
5051
__CPROVER_assigns(*out)
5152
{
52-
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
53-
if (result > UINT32_MAX) return FAILURE;
54-
*out = (uint32_t) result;
55-
return SUCCESS;
53+
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
54+
if (result > UINT32_MAX) return FAILURE;
55+
*out = (uint32_t) result;
56+
return SUCCESS;
5657
}
5758
```
5859
@@ -65,28 +66,28 @@ is one of those options.
6566
```c
6667
int __CPROVER_contracts_original_sum(const uint32_t a, const uint32_t b, uint32_t* out)
6768
{
68-
const uint64_t result;
69-
__CPROVER_assert((__CPROVER_POINTER_OBJECT(&result) == __CPROVER_POINTER_OBJECT(out) &&
70-
__CPROVER_POINTER_OFFSET(&result) == __CPROVER_POINTER_OFFSET(out)) ||
71-
(__CPROVER_POINTER_OBJECT(&result) == __CPROVER_POINTER_OBJECT(&result) &&
72-
__CPROVER_POINTER_OFFSET(&result) == __CPROVER_POINTER_OFFSET(&result))
73-
, "Check that result is assignable");
74-
result = ((uint64_t) *a) + ((uint64_t) *b);
75-
if (result > UINT32_MAX) return FAILURE;
76-
__CPROVER_assert((__CPROVER_POINTER_OBJECT(out) == __CPROVER_POINTER_OBJECT(out) &&
77-
__CPROVER_POINTER_OFFSET(out) == __CPROVER_POINTER_OFFSET(out)) ||
78-
(__CPROVER_POINTER_OBJECT(out) == __CPROVER_POINTER_OBJECT(&result) &&
79-
__CPROVER_POINTER_OFFSET(out) == __CPROVER_POINTER_OFFSET(&result))
80-
, "Check that result is assignable");
81-
*out = (uint32_t) result;
82-
return SUCCESS;
69+
const uint64_t result;
70+
__CPROVER_assert((__CPROVER_POINTER_OBJECT(&result) == __CPROVER_POINTER_OBJECT(out) &&
71+
__CPROVER_POINTER_OFFSET(&result) == __CPROVER_POINTER_OFFSET(out)) ||
72+
(__CPROVER_POINTER_OBJECT(&result) == __CPROVER_POINTER_OBJECT(&result) &&
73+
__CPROVER_POINTER_OFFSET(&result) == __CPROVER_POINTER_OFFSET(&result))
74+
, "Check that result is assignable");
75+
result = ((uint64_t) a) + ((uint64_t) b);
76+
if (result > UINT32_MAX) return FAILURE;
77+
__CPROVER_assert((__CPROVER_POINTER_OBJECT(out) == __CPROVER_POINTER_OBJECT(out) &&
78+
__CPROVER_POINTER_OFFSET(out) == __CPROVER_POINTER_OFFSET(out)) ||
79+
(__CPROVER_POINTER_OBJECT(out) == __CPROVER_POINTER_OBJECT(&result) &&
80+
__CPROVER_POINTER_OFFSET(out) == __CPROVER_POINTER_OFFSET(&result))
81+
, "Check that result is assignable");
82+
*out = (uint32_t) result;
83+
return SUCCESS;
8384
}
8485
8586
/* Function Contract Enforcement */
8687
int sum(const uint32_t a, const uint32_t b, uint32_t* out)
8788
{
88-
int return_value_sum = __CPROVER_contracts_original_sum(a, b, out);
89-
return return_value_sum;
89+
int return_value_sum = __CPROVER_contracts_original_sum(a, b, out);
90+
return return_value_sum;
9091
}
9192
```
9293

@@ -101,7 +102,8 @@ considered assignable as well.
101102
Finally, a set of freely-assignable symbols *free* is tracked during the
102103
traversal of the function body. These are locally-defined variables and formal
103104
parameters without dereferences. For example, in a variable declaration `<type>
104-
x = <initial_value>`, `x` would be added to *free*. Assignment statements where the left-hand-side is in *free* are not instrumented with the above assertions.
105+
x = <initial_value>`, `x` would be added to the *free* set. Assignment statements
106+
where the left-hand-side is in the *free* set are not instrumented with the above assertions.
105107

106108
#### Replacement
107109

@@ -112,7 +114,7 @@ Clauses](contracts-requires-and-ensures.md) - Replacement section, and it will a
112114
non-deterministic assignments for each object listed in the `__CPROVER_assigns`
113115
clause. Since these objects might be modified by the function, CBMC uses
114116
non-deterministic assignments to havoc them and restrict their values only by
115-
assuming the postconditions.
117+
assuming the postconditions (i.e., requires clauses).
116118

117119
In our example, consider that a function `foo` may call `sum`.
118120

@@ -126,21 +128,21 @@ __CPROVER_ensures((__CPROVER_return_value == SUCCESS) ==> (*out == (a + b)))
126128
/* Writable Set */
127129
__CPROVER_assigns(*out)
128130
{
129-
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
130-
if (result > UINT32_MAX) return FAILURE;
131-
*out = (uint32_t) result;
132-
return SUCCESS;
131+
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
132+
if (result > UINT32_MAX) return FAILURE;
133+
*out = (uint32_t) result;
134+
return SUCCESS;
133135
}
134136

135137
int foo()
136138
{
137-
uint32_t a;
138-
uint32_t b;
139-
uint32_t out;
140-
int rval = sum(a, b, &out);
141-
if (rval == SUCCESS)
142-
return out;
143-
return rval;
139+
uint32_t a;
140+
uint32_t b;
141+
uint32_t out;
142+
int rval = sum(a, b, &out);
143+
if (rval == SUCCESS)
144+
return out;
145+
return rval;
144146
}
145147
```
146148
@@ -150,26 +152,25 @@ wherever the function is called.
150152
```c
151153
int foo()
152154
{
153-
uint32_t a;
154-
uint32_t b;
155-
uint32_t out;
155+
uint32_t a;
156+
uint32_t b;
157+
uint32_t out;
156158
159+
/* Function Contract Replacement */
160+
/* Precondition */
161+
__CPROVER_assert(__CPROVER_is_fresh(out, sizeof(*out)), "Check requires clause");
157162
158-
/* Function Contract Replacement */
159-
/* Precondition */
160-
__CPROVER_assert(__CPROVER_is_fresh(out, sizeof(*out)), "Check requires clause");
163+
/* Writable Set */
164+
*(&out) = nondet_uint32_t();
161165
162-
/* Writable Set */
163-
*(&out) = nondet_uint32_t();
164-
165-
/* Postconditions */
166-
int return_value_sum = nondet_int();
167-
__CPROVER_assume(return_value_sum == SUCCESS || return_value_sum == FAILURE);
168-
__CPROVER_assume((return_value_sum == SUCCESS) ==> (*out == (*a + *b)));
169-
170-
int rval = return_value_sum;
171-
if (rval == SUCCESS)
172-
return out;
173-
return rval;
166+
/* Postconditions */
167+
int return_value_sum = nondet_int();
168+
__CPROVER_assume(return_value_sum == SUCCESS || return_value_sum == FAILURE);
169+
__CPROVER_assume((return_value_sum == SUCCESS) ==> (*out == (a + b)));
170+
171+
int rval = return_value_sum;
172+
if (rval == SUCCESS)
173+
return out;
174+
return rval;
174175
}
175176
```

branches/variant-submodule/doc/cprover-manual/contracts-history-variables.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ _ensures_ clause.
1414
### Parameters
1515
1616
`__CPROVER_old` takes a single argument, which is the identifier corresponding to
17-
a parameter of the function. For now, only scalar, structs, or pointer types are supported.
18-
17+
a parameter of the function. For now, only scalar or pointer types are supported.
1918
2019
### Semantics
2120
@@ -24,13 +23,12 @@ bellow. If the function returns a failure code, the value of `*out` should not
2423
have been modified.
2524
2625
```c
27-
int sum(uint32_t* a, uint32_t* b, uint32_t* out)
28-
26+
int sum(const uint32_t a, const uint32_t b, uint32_t* out)
2927
/* Postconditions */
3028
__CPROVER_ensures((__CPROVER_return_value == FAILURE) ==> (*out == __CPROVER_old(*out)))
3129
/* Writable Set */
3230
__CPROVER_assigns(*out)
3331
{
34-
/* ... */
32+
/* ... */
3533
}
3634
```
Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# Memory Predicates
22

3-
43
### Syntax
54

65
```c
76
bool __CPROVER_is_fresh(void *p, size_t size);
87
```
98
109
To specify memory footprint we use a special function called `__CPROVER_is_fresh `. The meaning of `__CPROVER_is_fresh` is that we are borrowing a pointer from the
11-
external environment (in a precondition), or returning it to the calling context (in a postcondition).
10+
external environment (in a precondition), or returning it to the calling context (in a postcondition).
1211
1312
### Parameters
1413
@@ -33,12 +32,12 @@ __CPROVER_requires(__CPROVER_is_fresh(out, sizeof(*out)))
3332
__CPROVER_ensures(__CPROVER_is_fresh(err_signal, sizeof(*err_signal)))
3433
__CPROVER_assigns(*out, err_signal)
3534
{
36-
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
37-
err_signal = malloc(sizeof(*err_signal));
38-
if (!err_signal) return;
39-
if (result > UINT32_MAX) *err_signal = FAILURE;
40-
*out = (uint32_t) result;
41-
*err_signal = SUCCESS;
35+
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
36+
err_signal = malloc(sizeof(*err_signal));
37+
if (!err_signal) return;
38+
if (result > UINT32_MAX) *err_signal = FAILURE;
39+
*out = (uint32_t) result;
40+
*err_signal = SUCCESS;
4241
}
4342
```
4443

@@ -53,21 +52,21 @@ int *err_signal; // Global variable
5352

5453
int __CPROVER_contracts_original_sum(const uint32_t a, const uint32_t b, uint32_t* out)
5554
{
56-
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
57-
err_signal = malloc(sizeof(*err_signal));
58-
if (!err_signal) return;
59-
if (result > UINT32_MAX) *err_signal = FAILURE;
60-
*out = (uint32_t) result;
61-
*err_signal = SUCCESS;
55+
const uint64_t result = ((uint64_t) a) + ((uint64_t) b);
56+
err_signal = malloc(sizeof(*err_signal));
57+
if (!err_signal) return;
58+
if (result > UINT32_MAX) *err_signal = FAILURE;
59+
*out = (uint32_t) result;
60+
*err_signal = SUCCESS;
6261
}
6362

6463
/* Function Contract Enforcement */
6564
int sum(const uint32_t a, const uint32_t b, uint32_t* out)
6665
{
67-
__CPROVER_assume(__CPROVER_is_fresh(out, sizeof(*out))); // Assumes out is freshly allocated
68-
int return_value_sum = __CPROVER_contracts_original_sum(a, b, out);
69-
__CPROVER_assert(__CPROVER_is_fresh(err_signal, sizeof(*err_signal)), "Check ensures clause");
70-
return return_value_sum;
66+
__CPROVER_assume(__CPROVER_is_fresh(out, sizeof(*out))); // Assumes out is freshly allocated
67+
int return_value_sum = __CPROVER_contracts_original_sum(a, b, out);
68+
__CPROVER_assert(__CPROVER_is_fresh(err_signal, sizeof(*err_signal)), "Check ensures clause");
69+
return return_value_sum;
7170
}
7271
```
7372
@@ -80,11 +79,11 @@ int *err_signal; // Global variable
8079
8180
int foo()
8281
{
83-
uint32_t a;
84-
uint32_t b;
85-
uint32_t out;
86-
sum(a, b, &out);
87-
return *err_signal;
82+
uint32_t a;
83+
uint32_t b;
84+
uint32_t out;
85+
sum(a, b, &out);
86+
return *err_signal;
8887
}
8988
```
9089

@@ -98,21 +97,21 @@ int *err_signal; // Global variable
9897

9998
int foo()
10099
{
101-
uint32_t a;
102-
uint32_t b;
103-
uint32_t out;
100+
uint32_t a;
101+
uint32_t b;
102+
uint32_t out;
104103

105-
/* Function Contract Replacement */
106-
/* Precondition */
107-
__CPROVER_assert(__CPROVER_is_fresh(out, sizeof(*out)), "Check requires clause");
104+
/* Function Contract Replacement */
105+
/* Precondition */
106+
__CPROVER_assert(__CPROVER_is_fresh(out, sizeof(*out)), "Check requires clause");
108107

109-
/* Writable Set */
110-
*(&out) = nondet_uint32_t();
111-
err_signal = nondet_int_pointer();
108+
/* Writable Set */
109+
*(&out) = nondet_uint32_t();
110+
err_signal = nondet_int_pointer();
112111

113-
/* Postconditions */
114-
__CPROVER_assume(__CPROVER_is_fresh(err_signal, sizeof(*err_signal))); // Assumes out is allocated
112+
/* Postconditions */
113+
__CPROVER_assume(__CPROVER_is_fresh(err_signal, sizeof(*err_signal))); // Assumes out is allocated
115114

116-
return *err_signal;
115+
return *err_signal;
117116
}
118-
```
117+
```

0 commit comments

Comments
 (0)