Skip to content

Commit 87e992b

Browse files
authored
Merge pull request #7472 from tautschnig/bugfixes/fs-recursive
Field sensitivity: fully expand nested objects
2 parents 3b908f8 + ad8086f commit 87e992b

File tree

6 files changed

+173
-23
lines changed

6 files changed

+173
-23
lines changed

Diff for: regression/cbmc/field-sensitivity15/main.c

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <assert.h>
2+
3+
struct _12817932758143517076
4+
{
5+
unsigned char _0;
6+
};
7+
8+
struct _14237415465709481864_union__Err
9+
{
10+
unsigned char cap;
11+
};
12+
13+
union _14237415465709481864_union
14+
{
15+
struct _12817932758143517076 value;
16+
struct _14237415465709481864_union__Err Err;
17+
};
18+
19+
void main(void)
20+
{
21+
unsigned int x; // nondet
22+
23+
// the following is crucial (else pn trivially simplifies to 0)
24+
unsigned int var_7 = x;
25+
unsigned int pn = x - var_7;
26+
27+
unsigned char raw;
28+
unsigned char mask;
29+
if(pn == 0)
30+
{
31+
raw = 1;
32+
mask = 0;
33+
}
34+
else
35+
assert(0);
36+
37+
union _14237415465709481864_union var_11;
38+
if(mask != 0)
39+
{
40+
var_11.Err.cap = 0;
41+
}
42+
else
43+
{
44+
var_11.value._0 = 1;
45+
goto bb5;
46+
}
47+
48+
// required to make this test fail (before the fix)
49+
int tmp = 1;
50+
51+
bb5:;
52+
struct _12817932758143517076 truncated_packet_number = var_11.value;
53+
unsigned char r = truncated_packet_number._0;
54+
assert(raw == r);
55+
}

Diff for: regression/cbmc/field-sensitivity15/test.desc

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
--
9+
The test is a minimized version of code generated from s2n-quic using Kani.

Diff for: regression/cbmc/field-sensitivity16/main.c

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include <assert.h>
2+
3+
struct _17626587426415757163
4+
{
5+
unsigned long int cap;
6+
};
7+
8+
struct _14237415465709481864_union__Err
9+
{
10+
struct _17626587426415757163 _0;
11+
};
12+
13+
struct _12817932758143517076_union__U8
14+
{
15+
unsigned char _0;
16+
};
17+
18+
union _12817932758143517076_union_
19+
{
20+
struct _12817932758143517076_union__U8 U8;
21+
};
22+
23+
struct _2123760316064833246_
24+
{
25+
union _12817932758143517076_union_ cases;
26+
};
27+
28+
union _14237415465709481864_union
29+
{
30+
struct _2123760316064833246_ Ok;
31+
struct _14237415465709481864_union__Err Err;
32+
};
33+
34+
void main(void)
35+
{
36+
unsigned int x; // nondet
37+
38+
// the following is crucial (else pn trivially simplifies to 0)
39+
unsigned int var_7 = x;
40+
unsigned int pn = x - var_7;
41+
42+
unsigned char mask;
43+
if(pn == 0)
44+
mask = 0;
45+
else
46+
assert(0);
47+
48+
union _14237415465709481864_union var_11;
49+
if(mask != 0)
50+
{
51+
assert(0);
52+
var_11.Err._0.cap = 0;
53+
}
54+
else
55+
{
56+
var_11.Ok.cases.U8._0 = 1;
57+
goto bb5;
58+
}
59+
60+
// keep this
61+
int tmp = 1;
62+
bb5:;
63+
64+
struct _2123760316064833246_ truncated_packet_number = var_11.Ok;
65+
assert(1 == var_11.Ok.cases.U8._0);
66+
assert(1 == truncated_packet_number.cases.U8._0);
67+
}

Diff for: regression/cbmc/field-sensitivity16/test.desc

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE broken-z3-smt-backend
2+
main.c
3+
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
--
9+
The test is a minimized version of code generated from s2n-quic using Kani.

Diff for: src/goto-symex/field_sensitivity.cpp

+33-15
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ exprt field_sensitivityt::apply(
8484
member.struct_op() = tmp.get_original_expr();
8585
tmp.set_expression(member);
8686
if(was_l2)
87-
return state.rename(std::move(tmp), ns).get();
87+
return apply(ns, state, state.rename(std::move(tmp), ns).get(), write);
8888
else
89-
return std::move(tmp);
89+
return apply(ns, state, std::move(tmp), write);
9090
}
9191
}
9292
else if(
@@ -116,9 +116,12 @@ exprt field_sensitivityt::apply(
116116
tmp.type() = be.type();
117117
tmp.set_expression(*recursive_member);
118118
if(was_l2)
119-
return state.rename(std::move(tmp), ns).get();
119+
{
120+
return apply(
121+
ns, state, state.rename(std::move(tmp), ns).get(), write);
122+
}
120123
else
121-
return std::move(tmp);
124+
return apply(ns, state, std::move(tmp), write);
122125
}
123126
}
124127
}
@@ -171,9 +174,12 @@ exprt field_sensitivityt::apply(
171174
index.index() = l2_index.get();
172175
tmp.set_expression(index);
173176
if(was_l2)
174-
return state.rename(std::move(tmp), ns).get();
177+
{
178+
return apply(
179+
ns, state, state.rename(std::move(tmp), ns).get(), write);
180+
}
175181
else
176-
return std::move(tmp);
182+
return apply(ns, state, std::move(tmp), write);
177183
}
178184
else if(!write)
179185
{
@@ -293,6 +299,14 @@ void field_sensitivityt::field_assignments(
293299
{
294300
field_assignments_rec(
295301
ns, state, lhs_fs, rhs, target, allow_pointer_unsoundness);
302+
// Erase the composite symbol from our working state. Note that we need to
303+
// have it in the propagation table and the value set while doing the field
304+
// assignments, thus we cannot skip putting it in there above.
305+
if(is_divisible(lhs, true))
306+
{
307+
state.propagation.erase_if_exists(lhs.get_identifier());
308+
state.value_set.erase_symbol(lhs, ns);
309+
}
296310
}
297311
}
298312

@@ -316,15 +330,11 @@ void field_sensitivityt::field_assignments_rec(
316330
{
317331
if(is_ssa_expr(lhs_fs))
318332
{
319-
const ssa_exprt ssa_lhs = state
320-
.assignment(
321-
to_ssa_expr(lhs_fs),
322-
ssa_rhs,
323-
ns,
324-
true,
325-
true,
326-
allow_pointer_unsoundness)
327-
.get();
333+
const ssa_exprt &l1_lhs = to_ssa_expr(lhs_fs);
334+
const ssa_exprt ssa_lhs =
335+
state
336+
.assignment(l1_lhs, ssa_rhs, ns, true, true, allow_pointer_unsoundness)
337+
.get();
328338

329339
// do the assignment
330340
target.assignment(
@@ -335,6 +345,14 @@ void field_sensitivityt::field_assignments_rec(
335345
ssa_rhs,
336346
state.source,
337347
symex_targett::assignment_typet::STATE);
348+
// Erase the composite symbol from our working state. Note that we need to
349+
// have it in the propagation table and the value set while doing the field
350+
// assignments, thus we cannot skip putting it in there above.
351+
if(is_divisible(l1_lhs, true))
352+
{
353+
state.propagation.erase_if_exists(l1_lhs.get_identifier());
354+
state.value_set.erase_symbol(l1_lhs, ns);
355+
}
338356
}
339357
else if(
340358
ssa_rhs.type().id() == ID_struct || ssa_rhs.type().id() == ID_struct_tag)

Diff for: src/goto-symex/symex_assign.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,6 @@ void symex_assignt::assign_non_struct_symbol(
215215
assignment.rhs,
216216
target,
217217
symex_config.allow_pointer_unsoundness);
218-
// Erase the composite symbol from our working state. Note that we need to
219-
// have it in the propagation table and the value set while doing the field
220-
// assignments, thus we cannot skip putting it in there above.
221-
if(state.field_sensitivity.is_divisible(l1_lhs, true))
222-
{
223-
state.propagation.erase_if_exists(l1_lhs.get_identifier());
224-
state.value_set.erase_symbol(l1_lhs, ns);
225-
}
226218
}
227219
}
228220

0 commit comments

Comments
 (0)