@@ -151,11 +151,94 @@ void func() {
151
151
// to a value of `1`.
152
152
__CPROVER_set_field (&a, "shadow", 1);
153
153
// Retrieve the value of the field named "shadow" associated with the address
154
- // of the object ` a ` .
154
+ // of the object ` a ` .
155
155
shadow_x = __ CPROVER_get_field(&a, "shadow");
156
156
__ CPROVER_assert(shadow_x == 1, "expected success: field set to a value of 1");
157
157
}
158
158
```
159
159
160
160
Note that setting the value of a local variable from a global SSM field or the
161
161
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