1
1
# Shadow Memory
2
2
3
- ( The original artefact's implementation is outlined in the paper [ CBMC-SSM:
4
- Bounded Model Checking of C Programs with Symbolic Shadow
5
- Memory] ( https://dl.acm.org/doi/abs/10.1145/3551349.3559523 ) .)
3
+ The Symbolic Shadow Memory module described below is an implementation of
4
+ what is outlined in the paper [ CBMC-SSM: Bounded Model Checking of C Programs
5
+ with Symbolic Shadow Memory] ( https://dl.acm.org/doi/abs/10.1145/3551349.3559523 ) .
6
6
7
7
## Introduction
8
8
9
- CBMC contains a component that supports * Symbolic Shadow Memory* . Shadow memory
10
- allows one to create a parallel memory structure that is maintained by the
11
- analysis program and that shadows the standard memory of the program. In that
12
- memory structure, a user can create fields, for which he can later set and
13
- retrieve values.
9
+ CBMC implements * Symbolic Shadow Memory* . Symbolic Shadow Memory (from now on,
10
+ SSM) allows one to create a parallel memory structure that is maintained by the
11
+ analysis program and that shadows the standard memory of the program. In the
12
+ Shadow Memory structure, a user can create fields, for which he can set and get
13
+ ( retrieve) values.
14
14
15
15
By doing so, one can organise his own tracking of metadata related to the code,
16
16
in a way that is then considered by the backend of CBMC during analysis. This
17
- can be used to implement novel analyses that the CBMC framework itself doesn't
18
- support - for example, the paper above presents as an example a taint analysis
17
+ can be used to implement novel analyses that the CBMC framework itself does not
18
+ support. For example, the paper above presents as an example a taint analysis
19
19
implemented with the use of the SSM component described here.
20
20
21
21
## Usage
22
22
23
- A user can interact with the Symbolic Shadow Memory component (from now on
24
- onwards, SSM) through four CBMC primitives, which allow one to declare shadow
25
- memory fields, and retrieve/set their corresponding values:
23
+ A user can interact with the Symbolic Shadow Memory component through four CBMC
24
+ primitives, which allow one to declare shadow memory fields, and set/get their
25
+ corresponding values:
26
26
27
27
* ` __CPROVER_field_decl_local `
28
28
* ` __CPROVER_field_decl_global `
29
29
* ` __CPROVER_get_field `
30
30
* ` __CPROVER_set_field `
31
31
32
32
More precisely, their signatures (in pseudo-C, because of some constraints that
33
- we can't express using the type system), along with some small examples of their
34
- usage, look like this :
33
+ we cannot express using the type system), along with some small examples of their
34
+ usage, are described below :
35
35
36
36
### ` void __CPROVER_field_decl_local(type1 field_name, SSM_value_type init_value) `
37
37
38
38
Type constraints:
39
39
40
40
* ` type1 ` : string literal, such as ` "field" ` ,
41
- * ` SSM_value_type ` : value of maximum 8 bits, signed or unsigned or ` _Bool ` .
41
+ * ` SSM_value_type ` : any value up to 8 bits in size (signed or unsigned) .
42
42
43
- Declares a local (working for variable declared in the current function scope)
44
- shadow memory field called ` field_name ` , and initialises it with the value
45
- ` init_value ` . The field is going to be associated with local-scope objects (i.e.
46
- a variable on the stack).
43
+ Declares a local shadow memory field called ` field_name ` , and initialises it
44
+ with the value ` init_value ` . The field is going to be associated with
45
+ local-scope objects (i.e. a variable on the stack).
46
+
47
+ Note that each scope will have a separate * local* shadow memory, so value stored
48
+ in the * local* shadow memory is not propagated to subcalls (even when the call
49
+ is recursive).
47
50
48
51
``` c
49
52
void func () {
@@ -60,10 +63,11 @@ void func() {
60
63
Type constraints:
61
64
62
65
* ` type1 ` : string literal, such as ` "field" ` ,
63
- * ` SSM_value_type ` : value of maximum 8 bits, signed or unsigned or ` _Bool ` .
66
+ * ` SSM_value_type ` : any value up to 8 bits in size (signed or unsigned) .
64
67
65
- Ditto as above, but the field declared is associated with global objects (i.e.
66
- global variables or heap allocated objects).
68
+ As for ` __CPROVER_field_decl_local ` , but the field declared is associated with
69
+ objects whose lifetime exceeds the current function scope (i.e. global variables
70
+ or heap allocated objects).
67
71
68
72
``` c
69
73
// Sample global object
@@ -79,18 +83,19 @@ void func() {
79
83
80
84
Type constraints:
81
85
82
- * ` SSM_VALUE_TYPE ` : the type of the value that was used to intialise the field
83
- with during declaration,
86
+ * ` SSM_VALUE_TYPE ` : the type of the returned value is the same of the SSM field,
87
+ i.e. the type that was used to intialise the SSM field during declaration,
84
88
* ` type1 * ` : a non-` void ` pointer to an object of type ` type1 ` , whose address we
85
89
are going to use for indexing the shadow memory component for the field
86
90
declared,
87
91
* ` type2 ` : a string literal-typed value, denoting the name of the field whose
88
92
value we want to retrieve, such as ` "field" ` .
89
93
90
- Retrieves the value (currently) associated with a SSM field of the given
91
- pointer. This would be either the value the field was declared to be initialised
92
- with, or, if there had been subsequent changes to it through a ` __CPROVER_set_field ` ,
93
- the value that it was last ` set ` with.
94
+ Retrieves the latest value associated with a SSM field to the given pointer.
95
+ This would be either the value the field was declared to be initialised with,
96
+ or, if there had been subsequent changes to it through a ` __CPROVER_set_field `
97
+ (see ` __CPROVER_set_field ` section below), the value that it was last ` set `
98
+ with.
94
99
95
100
``` c
96
101
// Sample global object
@@ -106,6 +111,10 @@ void func() {
106
111
}
107
112
```
108
113
114
+ Note that getting the value of a local variable from a global SSM field or the
115
+ opposite will return the default value for that SSM field (and it ** will not**
116
+ fail).
117
+
109
118
### ` void __CPROVER_set_field(type1 *p, type2 field_name, type3 set_value) `
110
119
111
120
Type constraints:
@@ -115,34 +124,38 @@ Type constraints:
115
124
declared,
116
125
* ` type2 ` : a string literal-typed value, denoting the name of the field whose
117
126
value we want to retrieve, such as ` "field" ` ,
118
- * ` type3 ` : type of the value to be set. This can be ` _Bool ` or of any integer
119
- type signed or unsigned . Notice that if this type differs from the type the
120
- field was declared with (` SSM_VALUE_TYPE ` above) it will be implicitly casted
121
- to it.
127
+ * ` type3 ` : type of the value to be set. This can be any integer type signed or
128
+ unsigned (including ` _Bool ` ) . Notice that if this type differs from the type
129
+ the SSM field was declared with (` SSM_VALUE_TYPE ` above) it will be
130
+ implicitly casted to it.
122
131
123
- Sets the value of an SSM field, using the name supplied by the ` field name ` as an
124
- identifier for the field and using the pointer in ` p ` as the address for the location
125
- of the value to be changed, to the given value, supplied by the third argument
126
- ` set_value ` . This value needs to be of the same type as the type of the value the
127
- field was originally initialised with.
132
+ Sets the value associated with a SSM field to the given pointer ` p ` with the
133
+ given value ` set_value ` . If the ` set_value ` type is not the ` SSM_VALUE_TYPE ` , it
134
+ will be implicitly casted to it.
128
135
129
136
``` c
130
- // Sample global object
137
+ // Sample global object, used for addressing within the SSM component.
131
138
int a = 10 ;
132
139
133
140
void func () {
134
141
// Shadow memory field (called "field") associated with global objects.
135
- // Originally assigned a value of `1`, of type `_Bool`.
136
- __CPROVER_field_decl_global ("shadow", (_ Bool)1);
137
-
138
- // Set field "shadow" for the memory location denoted by the address of `a`
139
- // to a value of 0.
140
- __CPROVER_set_field (&a, "shadow", 0);
142
+ // Originally assigned a value of `0`, of type `_Bool`.
143
+ __CPROVER_field_decl_global ("shadow", (_ Bool)0);
141
144
142
145
// Retrieve the value of the field named "shadow" associated with the address
143
146
// of the object `a`.
144
147
_Bool shadow_x = __CPROVER_get_field(&a, "shadow");
145
- __CPROVER_assert (shadow_x == 0, "expected success: field set to a value of 0");
146
- __ CPROVER_assert(shadow_x == 1, "expected fail: field set to a value of 0");
148
+ __CPROVER_assert (shadow_x == 0, "expected success: field defaulted to a value of 0");
149
+
150
+ // Set field "shadow" for the memory location denoted by the address of `a`
151
+ // to a value of `1`.
152
+ __CPROVER_set_field (&a, "shadow", 1);
153
+ // Retrieve the value of the field named "shadow" associated with the address
154
+ // of the object ` a ` .
155
+ shadow_x = __ CPROVER_get_field(&a, "shadow");
156
+ __ CPROVER_assert(shadow_x == 1, "expected success: field set to a value of 1");
147
157
}
148
158
```
159
+
160
+ Note that setting the value of a local variable from a global SSM field or the
161
+ opposite will produce no effect (and it ** will not** fail).
0 commit comments