Skip to content

Commit a4c9364

Browse files
committed
Address comments from reviews
1 parent 6a29bf5 commit a4c9364

File tree

1 file changed

+60
-47
lines changed

1 file changed

+60
-47
lines changed
Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,52 @@
11
# Shadow Memory
22

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).
66

77
## Introduction
88

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.
1414

1515
By doing so, one can organise his own tracking of metadata related to the code,
1616
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
1919
implemented with the use of the SSM component described here.
2020

2121
## Usage
2222

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:
2626

2727
* `__CPROVER_field_decl_local`
2828
* `__CPROVER_field_decl_global`
2929
* `__CPROVER_get_field`
3030
* `__CPROVER_set_field`
3131

3232
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:
3535

3636
### `void __CPROVER_field_decl_local(type1 field_name, SSM_value_type init_value)`
3737

3838
Type constraints:
3939

4040
* `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).
4242

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).
4750

4851
```c
4952
void func() {
@@ -60,10 +63,11 @@ void func() {
6063
Type constraints:
6164

6265
* `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).
6467

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).
6771

6872
```c
6973
// Sample global object
@@ -79,18 +83,19 @@ void func() {
7983

8084
Type constraints:
8185

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,
8488
* `type1 *`: a non-`void` pointer to an object of type `type1`, whose address we
8589
are going to use for indexing the shadow memory component for the field
8690
declared,
8791
* `type2`: a string literal-typed value, denoting the name of the field whose
8892
value we want to retrieve, such as `"field"`.
8993

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.
9499

95100
```c
96101
// Sample global object
@@ -106,6 +111,10 @@ void func() {
106111
}
107112
```
108113

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+
109118
### `void __CPROVER_set_field(type1 *p, type2 field_name, type3 set_value)`
110119

111120
Type constraints:
@@ -115,34 +124,38 @@ Type constraints:
115124
declared,
116125
* `type2`: a string literal-typed value, denoting the name of the field whose
117126
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.
122131

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.
128135

129136
```c
130-
// Sample global object
137+
// Sample global object, used for addressing within the SSM component.
131138
int a = 10;
132139

133140
void func() {
134141
// 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);
141144

142145
// Retrieve the value of the field named "shadow" associated with the address
143146
// of the object `a`.
144147
_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");
147157
}
148158
```
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

Comments
 (0)