Skip to content

Commit ea0fb4e

Browse files
committed
Add nondet assignment to non-zero'd allocations in symex
This change means that if a generation zero symex variable is seen it can be assumed to not have been allocated at any point and still have its default values. We use this knowledge to then not add a guard on a phi merge that has a gen zero on its lhs or rhs, instead just simply assigning the other side directly.
1 parent 41d7a45 commit ea0fb4e

File tree

14 files changed

+244
-2
lines changed

14 files changed

+244
-2
lines changed
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
public class PhiMergeUninitialized {
2+
3+
public int dynamicAllocationUninitialized(Boolean trigger) {
4+
5+
Ephemeral obj;
6+
if (trigger) {
7+
obj = new Ephemeral(42);
8+
} else {
9+
obj = new Aetherial(20);
10+
}
11+
12+
assert obj.val == 20;
13+
return obj.val;
14+
}
15+
16+
private Ephemeral local;
17+
18+
public int localUninitialized(Boolean trigger) {
19+
if (trigger) {
20+
local = new Ephemeral(42);
21+
} else {
22+
local = new Aetherial(50);
23+
}
24+
25+
assert local.val == 42;
26+
return local.val;
27+
}
28+
29+
private static Ephemeral staticLocal;
30+
31+
public int staticLocalUninitialized(Boolean trigger) {
32+
if (trigger) {
33+
staticLocal = new Ephemeral(42);
34+
} else {
35+
staticLocal = new Aetherial(76);
36+
}
37+
38+
assert staticLocal.val == 76;
39+
return staticLocal.val;
40+
}
41+
42+
class Ephemeral {
43+
Ephemeral(int value) {
44+
val = value;
45+
}
46+
47+
int val;
48+
}
49+
50+
class Aetherial extends Ephemeral {
51+
Aetherial(int value) {
52+
super(value);
53+
}
54+
}
55+
}
56+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
PhiMergeUninitialized.class
3+
--function PhiMergeUninitialized.localUninitialized --show-vcc
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^.*:\s+(dynamic_object|new_tmp)[0-9]+(@[0-9]+)?#0\)
9+
^.*\?\s+(dynamic_object|new_tmp)[0-9]+(@[0-9]+)?#0\s+:
10+
--
11+
These regexes are making sure that a variable of generation 0 dosen't appear in a phi merge:
12+
13+
(guard ? dynamic_object2@3#1 : dynamic_object3@3#0)
14+
15+
First regex deals with the form : variable#0), second deals with ? variable#0 :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
PhiMergeUninitialized.class
3+
--function PhiMergeUninitialized.dynamicAllocationUninitialized --show-vcc
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^.*:\s+(dynamic_object|new_tmp)[0-9]+(@[0-9]+)?#0\)
9+
^.*\?\s+(dynamic_object|new_tmp)[0-9]+(@[0-9]+)?#0\s+:
10+
--
11+
These regexes are making sure that a variable of generation 0 dosen't appear in a phi merge:
12+
13+
(guard ? dynamic_object2@3#1 : dynamic_object3@3#0)
14+
15+
First regex deals with the form : variable#0), second deals with ? variable#0 :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
PhiMergeUninitialized.class
3+
--function PhiMergeUninitialized.staticLocalUninitialized --show-vcc
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^.*:\s+(dynamic_object|new_tmp)[0-9]+(@[0-9]+)?#0\)
9+
^.*\?\s+(dynamic_object|new_tmp)[0-9]+(@[0-9]+)?#0\s+:
10+
--
11+
These regexes are making sure that a variable of generation 0 dosen't appear in a phi merge:
12+
13+
(guard ? dynamic_object2@3#1 : dynamic_object3@3#0)
14+
15+
First regex deals with the form : variable#0), second deals with ? variable#0 :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
test.c
3+
--function dynamicAllocationUninitialized --show-vcc
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^.*:\s+dynamic_object[0-9]+(@[0-9]+)?#0\)
9+
^.*\?\s+dynamic_object[0-9]+(@[0-9]+)?#0\s+:
10+
--
11+
These regexes are making sure that a variable of generation 0 dosen't appear in a phi merge:
12+
13+
(guard ? dynamic_object2@3#1 : dynamic_object3@3#0)
14+
15+
First regex deals with the form : variable#0), second deals with ? variable#0 :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
test.c
3+
--function globalUninitialized --show-vcc
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^.*:\s+global(@[0-9]+)?#0\)
9+
^.*\?\s+global(@[0-9]+)?#0\s+:
10+
--
11+
These regexes are making sure that a variable of generation 0 dosen't appear in a phi merge:
12+
13+
(guard ? dynamic_object2@3#1 : dynamic_object3@3#0)
14+
15+
First regex deals with the form : variable#0), second deals with ? variable#0 :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
test.c
3+
--function localUninitialized --show-vcc
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^.*:\s+local(@[0-9]+)?#0\)
9+
^.*\?\s+local(@[0-9]+)?#0\s+:
10+
--
11+
These regexes are making sure that a variable of generation 0 dosen't appear in a phi merge:
12+
13+
(guard ? dynamic_object2@3#1 : dynamic_object3@3#0)
14+
15+
First regex deals with the form : variable#0), second deals with ? variable#0 :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
test.c
3+
--function staticLocalUninitialized --show-vcc
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^.*:\s+staticLocal(@[0-9]+)?#0\)
9+
^.*\?\s+staticLocal(@[0-9]+)?#0\s+:
10+
--
11+
These regexes are making sure that a variable of generation 0 dosen't appear in a phi merge:
12+
13+
(guard ? dynamic_object2@3#1 : dynamic_object3@3#0)
14+
15+
First regex deals with the form : variable#0), second deals with ? variable#0 :
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
void dynamicAllocationUninitialized(int trigger)
5+
{
6+
int *obj;
7+
obj = (int*)malloc(sizeof(int));
8+
if(trigger)
9+
{
10+
*obj = 42;
11+
}
12+
else
13+
{
14+
*obj = 76;
15+
}
16+
17+
assert(*obj == 42);
18+
}
19+
20+
int global;
21+
void globalUninitialized(int trigger)
22+
{
23+
if(trigger)
24+
{
25+
global = 44;
26+
}
27+
else
28+
{
29+
global = 20;
30+
}
31+
32+
assert(global == 44);
33+
}
34+
35+
void staticLocalUninitialized(int trigger)
36+
{
37+
static int staticLocal;
38+
if(trigger)
39+
{
40+
staticLocal = 43;
41+
}
42+
43+
assert(staticLocal == 43);
44+
}
45+
46+
void localUninitialized(int trigger)
47+
{
48+
int local;
49+
if(trigger)
50+
{
51+
local = 24;
52+
}
53+
54+
assert(local == 24);
55+
}

src/goto-symex/goto_symex.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,19 @@ void goto_symext::do_simplify(exprt &expr)
2222
simplify(expr, ns);
2323
}
2424

25+
nondet_symbol_exprt goto_symext::build_symex_nondet(typet &type)
26+
{
27+
irep_idt identifier = "symex::nondet" + std::to_string(nondet_count++);
28+
nondet_symbol_exprt new_expr(identifier, type);
29+
return new_expr;
30+
}
31+
2532
void goto_symext::replace_nondet(exprt &expr)
2633
{
2734
if(expr.id()==ID_side_effect &&
2835
expr.get(ID_statement)==ID_nondet)
2936
{
30-
irep_idt identifier="symex::nondet"+std::to_string(nondet_count++);
31-
nondet_symbol_exprt new_expr(identifier, expr.type());
37+
nondet_symbol_exprt new_expr = build_symex_nondet(expr.type());
3238
new_expr.add_source_location()=expr.source_location();
3339
expr.swap(new_expr);
3440
}

src/goto-symex/goto_symex.h

+2
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,8 @@ class goto_symext
376376
exprt &code,
377377
const irep_idt &identifier);
378378

379+
nondet_symbol_exprt build_symex_nondet(typet &type);
380+
379381
// exceptions
380382
void symex_throw(statet &);
381383
void symex_catch(statet &);

src/goto-symex/symex_builtin_functions.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ void goto_symext::symex_allocate(
184184
else
185185
throw "failed to zero initialize dynamic object";
186186
}
187+
else
188+
{
189+
exprt nondet = build_symex_nondet(object_type);
190+
code_assignt assignment(value_symbol.symbol_expr(), nondet);
191+
symex_assign(state, assignment);
192+
}
187193

188194
exprt rhs;
189195

src/goto-symex/symex_goto.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,22 @@ void goto_symext::phi_function(
425425

426426
exprt rhs;
427427

428+
// Don't add a conditional to the assignment when:
429+
// 1. Either guard is false, so we can't follow that branch.
430+
// 2. Either identifier is of generation zero, and so hasn't been initialized and therefor
431+
// an invalid target.
428432
if(dest_state.guard.is_false())
429433
rhs=goto_state_rhs;
430434
else if(goto_state.guard.is_false())
431435
rhs=dest_state_rhs;
436+
else if(goto_state.level2_current_count(l1_identifier) == 0)
437+
{
438+
rhs = dest_state_rhs;
439+
}
440+
else if(dest_state.level2.current_count(l1_identifier) == 0)
441+
{
442+
rhs = goto_state_rhs;
443+
}
432444
else
433445
{
434446
rhs=if_exprt(diff_guard.as_expr(), goto_state_rhs, dest_state_rhs);

0 commit comments

Comments
 (0)