Skip to content

Commit cced7fd

Browse files
committed
Add a small paragraph explaining operation on compound type objects and aggregation
1 parent a4c9364 commit cced7fd

File tree

1 file changed

+84
-1
lines changed

1 file changed

+84
-1
lines changed

doc/cprover-manual/modeling-shadow-memory.md

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,94 @@ void func() {
151151
// to a value of `1`.
152152
__CPROVER_set_field(&a, "shadow", 1);
153153
// Retrieve the value of the field named "shadow" associated with the address
154-
// of the object `a`.
154+
// of the object `a`.
155155
shadow_x = __CPROVER_get_field(&a, "shadow");
156156
__CPROVER_assert(shadow_x == 1, "expected success: field set to a value of 1");
157157
}
158158
```
159159

160160
Note that setting the value of a local variable from a global SSM field or the
161161
opposite will produce no effect (and it **will not** fail).
162+
163+
### Working with Compound Type Objects
164+
165+
When using SSM on compound type pointers (e.g. `struct`) the value used for the
166+
`__CPROVER_set_field` will be replicated in each of the fields of the type, and
167+
aggregated again when retrieving them with `__CPROVER_get_field`. The
168+
aggregation function is `or` for an SSM field of `_Bool` type, and `max` for
169+
other types.
170+
171+
This is helpful, for example, in the case of taint analysis (as presented in the
172+
paper and shown below). In this case, when retrieving the taint value of a
173+
struct containing a tainted field the result value will indicate taint (without
174+
the need for changing non-tainted field values), and when setting the taint
175+
value of a struct then all its fields will be set to the given value.
176+
177+
```c
178+
struct S {
179+
unsigned long f1;
180+
char f2;
181+
};
182+
183+
void func() {
184+
// Shadow memory field (called "field") associated with local objects.
185+
// Originally assigned a value of `0`, of type `_Bool`.
186+
__CPROVER_field_decl_local("shadow", (_Bool)0);
187+
188+
// Struct typed variable
189+
struct S s;
190+
191+
// Retrieve the value of the field named "shadow" associated with the address
192+
// of the object `s`. Here we expect a `0` as default.
193+
__CPROVER_assert(__CPROVER_get_field(&s, "shadow") == 0,
194+
"expected success: field defaulted to a value of 0");
195+
// Retrieve the value of the field named "shadow" associated with the address
196+
// of the field `f1` of the object `s`. Here we expect a `0` as default.
197+
__CPROVER_assert(__CPROVER_get_field(&s.f1, "shadow") == 0,
198+
"expected success: field defaulted to a value of 0");
199+
// Retrieve the value of the field named "shadow" associated with the address
200+
// of the field `f1` of the object `s`. Here we expect a `0` as default.
201+
__CPROVER_assert(__CPROVER_get_field(&s.f2, "shadow") == 0,
202+
"expected success: field defaulted to a value of 0");
203+
204+
205+
// Set the shadow memory of the field `f1` (ONLY) of the object `s`.
206+
__CPROVER_set_field(&s.f1, "shadow", 1);
207+
208+
// Retrieve the value of the field named "shadow" associated with the address
209+
// of the object `s`. Here we expect a `1` as the value of field `f1` (after
210+
// aggregating all its field values using `max`).
211+
__CPROVER_assert(__CPROVER_get_field(&s, "shadow") == 1,
212+
"expected success: field previously set to a value of 1");
213+
// Retrieve the value of the field named "shadow" associated with the address
214+
// of the field `f1` of the object `s`. Here we expect a `1` as set above.
215+
__CPROVER_assert(__CPROVER_get_field(&s.f1, "shadow") == 1,
216+
"expected success: field previously set to a value of 1");
217+
// Retrieve the value of the field named "shadow" associated with the address
218+
// of the field `f2` of the object `s`. Here we expect a `0` as default.
219+
__CPROVER_assert(__CPROVER_get_field(&s.f2, "shadow") == 0,
220+
"expected success: field defaulted to a value of 0");
221+
222+
223+
// Set the shadow memory of the object `s`. This in turns sets also the
224+
// values of each (shadow) field of `s`.
225+
__CPROVER_set_field(&s, "shadow", 0);
226+
227+
// Retrieve the value of the field named "shadow" associated with the address
228+
// of the object `s`. Here we expect a `0` as set above.
229+
__CPROVER_assert(__CPROVER_get_field(&s, "shadow") == 0,
230+
"expected success: field previously set to a value of 0");
231+
// Retrieve the value of the field named "shadow" associated with the address
232+
// of the field `f1` of the object `s`. Here we expect a `0` as the set
233+
// above was replicated on all the fields of `s`.
234+
__CPROVER_assert(__CPROVER_get_field(&s.f1, "shadow") == 0,
235+
"expected success: field previously set to a value of 0");
236+
// Retrieve the value of the field named "shadow" associated with the address
237+
// of the field `f2` of the object `s`. Here we expect a `0` as the set
238+
// above was replicated on all the fields of `s`.
239+
__CPROVER_assert(__CPROVER_get_field(&s.f2, "shadow") == 0,
240+
"expected success: field previously set to a value of 0");
241+
}
242+
```
243+
244+

0 commit comments

Comments
 (0)