Skip to content

Commit 79186c4

Browse files
authored
Merge pull request #7846 from esteffin/esteffin/shadow-memory-set-field-op
Add shadow memory set_field operation
2 parents 8a8ecc8 + a3964fe commit 79186c4

File tree

34 files changed

+487
-31
lines changed

34 files changed

+487
-31
lines changed

regression/cbmc-shadow-memory/char1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/constchar-param1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33
--unwind 11
44
^EXIT=0$

regression/cbmc-shadow-memory/constchar-pointers1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33
--unwind 11
44
^EXIT=0$

regression/cbmc-shadow-memory/errno1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/float1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/getenv1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/global1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/linked-list1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/linked-list2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/local1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/malloc1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/maybe-null1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/memcpy1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/nondet-pointer-into-struct1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/nondet-size-arrays1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/param1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/static1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/strdup1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33
--unwind 4
44
^EXIT=0$

regression/cbmc-shadow-memory/struct-get-max1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/struct-get-or1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/struct-set1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include <assert.h>
2+
3+
struct S
4+
{
5+
short x[3];
6+
char c;
7+
};
8+
9+
int main(void)
10+
{
11+
__CPROVER_field_decl_local("f", (char)0);
12+
13+
struct S s;
14+
15+
// Setting the struct recursively set all its fields
16+
__CPROVER_set_field(&s, "f", 1);
17+
18+
assert(__CPROVER_get_field(&s.x[0], "f") == 1);
19+
assert(__CPROVER_get_field(&s.x[1], "f") == 1);
20+
assert(__CPROVER_get_field(&s.x[2], "f") == 1);
21+
assert(__CPROVER_get_field(&s.c, "f") == 1);
22+
assert(__CPROVER_get_field(&s, "f") == 1);
23+
24+
// Setting the struct recursively set all its fields
25+
__CPROVER_set_field(&s, "f", 0);
26+
27+
assert(__CPROVER_get_field(&s.x[0], "f") == 0);
28+
assert(__CPROVER_get_field(&s.x[1], "f") == 0);
29+
assert(__CPROVER_get_field(&s.x[2], "f") == 0);
30+
assert(__CPROVER_get_field(&s.c, "f") == 0);
31+
assert(__CPROVER_get_field(&s, "f") == 0);
32+
33+
// Setting a field of the struct changes its values ad after aggregation the whole struct value
34+
__CPROVER_set_field(&s.x[1], "f", 2);
35+
36+
assert(__CPROVER_get_field(&s.x[0], "f") == 0);
37+
assert(__CPROVER_get_field(&s.x[1], "f") == 2);
38+
assert(__CPROVER_get_field(&s.x[2], "f") == 0);
39+
assert(__CPROVER_get_field(&s.c, "f") == 0);
40+
assert(__CPROVER_get_field(&s, "f") == 2);
41+
42+
// Rest shadow memory
43+
__CPROVER_set_field(&s, "f", 0);
44+
45+
// Changing ONLY first cell of S array at field x by using offset with pointer arithmetics
46+
short *p = ((short *)&s) + 1;
47+
__CPROVER_set_field(p, "f", 3);
48+
49+
assert(__CPROVER_get_field(&s.x[0], "f") == 0);
50+
assert(__CPROVER_get_field(&s.x[1], "f") == 3);
51+
assert(__CPROVER_get_field(&s.x[2], "f") == 0);
52+
assert(__CPROVER_get_field(&s.c, "f") == 0);
53+
assert(__CPROVER_get_field(&s, "f") == 3);
54+
55+
return 0;
56+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc-shadow-memory/taint-example1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33
--unwind 15
44
^EXIT=0$

regression/cbmc-shadow-memory/trace1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33
--stop-on-fail --unwind 5
44
^EXIT=10$

regression/cbmc-shadow-memory/union-get-max1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/union-get-or1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/union-set1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/var-assign1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
KNOWNBUG
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/void-ptr-param-set1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=6$

regression/cbmc-shadow-memory/void-ptr-param2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FUTURE
1+
CORE
22
main.c
33

44
^EXIT=0$

src/goto-symex/shadow_memory.cpp

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,98 @@ void shadow_memoryt::symex_set_field(
9090
goto_symex_statet &state,
9191
const exprt::operandst &arguments)
9292
{
93-
// To be implemented
93+
// parse set_field call
94+
INVARIANT(
95+
arguments.size() == 3, CPROVER_PREFIX "set_field requires 3 arguments");
96+
irep_idt field_name = extract_field_name(arguments[1]);
97+
98+
exprt expr = arguments[0];
99+
typet expr_type = expr.type();
100+
DATA_INVARIANT_WITH_DIAGNOSTICS(
101+
expr_type.id() == ID_pointer,
102+
"shadow memory requires a pointer expression",
103+
irep_pretty_diagnosticst{expr_type});
104+
105+
exprt value = arguments[2];
106+
log_set_field(ns, log, field_name, expr, value);
107+
INVARIANT(
108+
state.shadow_memory.address_fields.count(field_name) == 1,
109+
id2string(field_name) + " should exist");
110+
const auto &addresses = state.shadow_memory.address_fields.at(field_name);
111+
112+
// get value set
113+
replace_invalid_object_by_null(expr);
114+
#ifdef DEBUG_SM
115+
log_set_field(ns, log, field_name, expr, value);
116+
#endif
117+
std::vector<exprt> value_set = state.value_set.get_value_set(expr, ns);
118+
log_value_set(ns, log, value_set);
119+
if(set_field_check_null(ns, log, value_set, expr))
120+
{
121+
log.warning() << "Shadow memory: cannot set shadow memory of NULL"
122+
<< messaget::eom;
123+
return;
124+
}
125+
126+
// build lhs
127+
const exprt &rhs = value;
128+
size_t mux_size = 0;
129+
optionalt<exprt> maybe_lhs =
130+
get_shadow_memory(expr, value_set, addresses, ns, log, mux_size);
131+
132+
// add to equation
133+
if(maybe_lhs.has_value())
134+
{
135+
if(mux_size >= 10)
136+
{
137+
log.warning() << "Shadow memory: mux size set_field: " << mux_size
138+
<< messaget::eom;
139+
}
140+
else
141+
{
142+
log.debug() << "Shadow memory: mux size set_field: " << mux_size
143+
<< messaget::eom;
144+
}
145+
const exprt lhs = deref_expr(*maybe_lhs);
146+
#ifdef DEBUG_SM
147+
log.debug() << "Shadow memory: LHS: " << format(lhs) << messaget::eom;
148+
#endif
149+
if(lhs.type().id() == ID_empty)
150+
{
151+
std::stringstream s;
152+
s << "Shadow memory: cannot set shadow memory via type void* for "
153+
<< format(expr)
154+
<< ". Insert a cast to the type that you want to access.";
155+
throw invalid_input_exceptiont(s.str());
156+
}
157+
158+
// Get the type of the shadow memory for this field
159+
const typet &sm_field_type = get_field_init_type(field_name, state);
160+
// Add a conditional cast to the shadow memory field type if `rhs` is not of
161+
// the expected type
162+
const exprt casted_rhs =
163+
typecast_exprt::conditional_cast(rhs, sm_field_type);
164+
// We replicate the rhs value on each byte of the value that we set.
165+
// This allows the get_field or/max semantics to operate correctly
166+
// on unions.
167+
const auto per_byte_rhs =
168+
expr_initializer(lhs.type(), expr.source_location(), ns, casted_rhs);
169+
CHECK_RETURN(per_byte_rhs.has_value());
170+
171+
#ifdef DEBUG_SM
172+
log.debug() << "Shadow memory: RHS: " << format(per_byte_rhs.value())
173+
<< messaget::eom;
174+
#endif
175+
symex_assign(
176+
state,
177+
lhs,
178+
typecast_exprt::conditional_cast(per_byte_rhs.value(), lhs.type()));
179+
}
180+
else
181+
{
182+
log.warning() << "Shadow memory: cannot set_field for " << format(expr)
183+
<< messaget::eom;
184+
}
94185
}
95186

96187
// Function synopsis

0 commit comments

Comments
 (0)