Skip to content

Commit 1ef1e08

Browse files
author
owen-jones-diffblue
authored
Merge pull request diffblue#331 from diffblue/bugfix/non_replaced_occurrences_of_NONDET
SEC-224: Added replacement of missed NONDET calls.
2 parents 6f6c099 + 7b02c81 commit 1ef1e08

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

src/taint-analysis/taint_program.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,66 @@ static void build_NONDET_retvals_replacements(
3232
next_instr_it!=instructions.end();
3333
instr_it = next_instr_it, ++next_instr_it)
3434
{
35-
if(instr_it->type!=FUNCTION_CALL || next_instr_it->type!=ASSIGN)
35+
if(instr_it->type != FUNCTION_CALL || next_instr_it->type != ASSIGN)
36+
{
37+
if(instr_it->type == ASSIGN)
38+
{
39+
const code_assignt &assign = to_code_assign(instr_it->code);
40+
if(assign.rhs().id() == ID_side_effect)
41+
{
42+
const side_effect_exprt side_effect =
43+
to_side_effect_expr(assign.rhs());
44+
if(side_effect.get_statement() == ID_nondet)
45+
{
46+
// See if we can see that this instruction is definitely
47+
// dead. Iterate backwards through the program from the current
48+
// instruction, looking for an unconditional GOTO or a target.
49+
// If we find an unconditional GOTO first then the instruction
50+
// is dead. If we find a target first then we must assume that
51+
// it can be reached. If we reach the beginning before finding
52+
// either then the instruction is reachable.
53+
bool is_dead = true;
54+
for(auto sit = instr_it;
55+
sit != instructions.begin();
56+
sit=std::prev(sit))
57+
{
58+
if(sit->is_target())
59+
{
60+
is_dead = false;
61+
break;
62+
}
63+
if(sit->type == GOTO && sit->guard.is_true())
64+
break;
65+
}
66+
if(is_dead || side_effect.type().id() == ID_pointer)
67+
{
68+
// Create a new static variable to put on the rhs of this
69+
// assignment. When the instruction is dead then this is
70+
// sound. Otherwise this is not sound, but it is
71+
// preferable to having a pointer that could point to
72+
// anything. A better solution would be to use the
73+
// replace_java_nondet pass or similar.
74+
static unsigned long counter = 0UL;
75+
std::stringstream sstr;
76+
sstr << "@__CPROVER_NONDET_dead_replace_" << ++counter;
77+
symbolt symbol;
78+
symbol.type =
79+
side_effect.type().id() == ID_pointer ?
80+
to_pointer_type(side_effect.type()).subtype() :
81+
side_effect.type();
82+
symbol.name = sstr.str();
83+
symbol.base_name = symbol.name;
84+
symbol.mode = ID_java;
85+
symbol.pretty_name = symbol.name;
86+
symbol.is_static_lifetime = true;
87+
const_cast<symbol_tablet&>(model.symbol_table).insert(symbol);
88+
replacements.insert({instr_it, symbol.symbol_expr()});
89+
}
90+
}
91+
}
92+
}
3693
continue;
94+
}
3795
const code_function_callt &fn_call=to_code_function_call(instr_it->code);
3896
if(fn_call.function().id()!=ID_symbol)
3997
continue;

0 commit comments

Comments
 (0)