Skip to content

Commit 91121ac

Browse files
author
owen-jones-diffblue
authored
Merge pull request diffblue#388 from diffblue/owen-jones-diffblue/bugfix/add-precise-evs-initializers
SEC-366: LVSA: fix bug in add_precise_evs_initializers()
2 parents 1366fa8 + ecb629c commit 91121ac

File tree

6 files changed

+84
-32
lines changed

6 files changed

+84
-32
lines changed

cbmc/src/analyses/static_analysis.cpp

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,28 @@ bool static_analysis_baset::fixedpoint(
221221
return new_data;
222222
}
223223

224+
bool static_analysis_baset::fixedpoint(
225+
const goto_programt &goto_program,
226+
const goto_functionst &goto_functions,
227+
working_sett &working_set)
228+
{
229+
if(goto_program.instructions.empty())
230+
return false;
231+
232+
bool new_data = false;
233+
234+
while(!working_set.empty())
235+
{
236+
++nsteps;
237+
locationt l = get_next(working_set);
238+
239+
if(visit(l, working_set, goto_program, goto_functions))
240+
new_data = true;
241+
}
242+
243+
return new_data;
244+
}
245+
224246
bool static_analysis_baset::visit(
225247
locationt l,
226248
working_sett &working_set,
@@ -243,21 +265,7 @@ bool static_analysis_baset::visit(
243265

244266
statet &new_values=*tmp_state;
245267

246-
if(l->is_function_call())
247-
{
248-
// this is a big special case
249-
const code_function_callt &code=
250-
to_code_function_call(l->code);
251-
252-
do_function_call_rec(
253-
l, to_l,
254-
code.function(),
255-
code.arguments(),
256-
new_values,
257-
goto_functions);
258-
}
259-
else
260-
new_values.transform(ns, l, to_l);
268+
transform_or_apply_function_call(l, to_l, goto_functions, new_values);
261269

262270
statet &other=get_state(to_l);
263271

@@ -547,3 +555,21 @@ void static_analysis_baset::concurrent_fixedpoint(
547555
}
548556
}
549557
}
558+
559+
void static_analysis_baset::transform_or_apply_function_call(
560+
locationt l,
561+
locationt to_l,
562+
const goto_functionst &goto_functions,
563+
statet &new_values)
564+
{
565+
if(l->is_function_call())
566+
{
567+
// this is a big special case
568+
const code_function_callt &code = to_code_function_call(l->code);
569+
570+
do_function_call_rec(
571+
l, to_l, code.function(), code.arguments(), new_values, goto_functions);
572+
}
573+
else
574+
new_values.transform(ns, l, to_l);
575+
}

cbmc/src/analyses/static_analysis.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ class static_analysis_baset
217217
bool fixedpoint(
218218
const goto_programt &goto_program,
219219
const goto_functionst &goto_functions);
220+
bool fixedpoint(
221+
const goto_programt &goto_program,
222+
const goto_functionst &goto_functions,
223+
working_sett &working_set);
220224

221225
virtual void fixedpoint(
222226
const goto_functionst &goto_functions)=0;
@@ -226,6 +230,12 @@ class static_analysis_baset
226230
void concurrent_fixedpoint(
227231
const goto_functionst &goto_functions);
228232

233+
void transform_or_apply_function_call(
234+
locationt l,
235+
locationt to_l,
236+
const goto_functionst &goto_functions,
237+
statet &new_values);
238+
229239
// true = found something new
230240
bool visit(
231241
locationt l,

regression/LVSA/TestPreciseAccessPaths/test_precise_access_paths.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ def test_apply_set_field_of_external_object(tmpdir):
7373
is_initializer=True)
7474

7575

76-
@pytest.mark.xfail(strict=True) # SEC-202
7776
def test_conditionally_set_field_of_external_object(tmpdir):
7877
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('conditionally_set_field_of_external_object')
7978
lvsa_expectation = lvsa_driver.run()
@@ -94,7 +93,12 @@ def test_apply_conditionally_set_field_of_external_object(tmpdir):
9493
value_set_expectation = lvsa_expectation.get_value_set_for_precise_evs(
9594
parameter_name='parameter_a', suffix='.object')
9695

97-
value_set_expectation.check_number_of_values(2)
96+
value_set_expectation.check_number_of_values(4)
97+
# Two values that existed before the function call
98+
value_set_expectation.check_contains_per_field_evs(access_path=['.object'])
99+
value_set_expectation.check_contains_precise_evs(label_suffix='parameter_a', access_path=['.object'],
100+
is_initializer=False)
101+
# Two values that came from the function call
98102
value_set_expectation.check_contains_root_object_evs(label_suffix='parameter_object')
99103
value_set_expectation.check_contains_precise_evs(label_suffix='parameter_a', access_path=['.object'],
100104
is_initializer=True)

src/pointer-analysis/local_value_set.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ void local_value_sett::assign_rec(
717717

718718
external_value_set_exprt new_ext_set = evsi;
719719
new_ext_set.set_per_field_access_path(new_entry);
720+
new_ext_set.type() = field_type.subtype();
720721

721722
const std::string basename =
722723
new_ext_set.get_access_path_basename(declared_on_type);
@@ -730,10 +731,7 @@ void local_value_sett::assign_rec(
730731
auto &lhs_entry = insert_result.first->second;
731732

732733
if(insert_result.second && field_type.id() == ID_pointer)
733-
{
734-
new_ext_set.type() = field_type.subtype();
735734
insert(lhs_entry.object_map, new_ext_set.as_initializer());
736-
}
737735

738736
make_union(lhs_entry.object_map, values_rhs);
739737
}
@@ -747,6 +745,7 @@ void local_value_sett::assign_rec(
747745
declared_on_type);
748746
external_value_set_exprt new_ext_set = evsi;
749747
bool loop_found = new_ext_set.extend_precise_access_path(new_entry);
748+
new_ext_set.type() = field_type.subtype();
750749

751750
if(loop_found)
752751
precise_evs_curtailed_because_of_loop = true;

src/pointer-analysis/local_value_set_analysis.cpp

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <algorithm>
1818

1919
#include <pointer-analysis/dynamic_object_name.h>
20+
#include <analyses/static_analysis.h>
2021
#include <util/infix.h>
2122
#include <java_bytecode/java_types.h>
2223

@@ -604,28 +605,31 @@ void local_value_set_analysist::operator()(const goto_programt &goto_program)
604605
/// This is a dummy variable that will always be empty because we handle
605606
/// function calls specially
606607
goto_functionst goto_functions;
608+
working_sett working_set;
609+
put_in_working_set(working_set, goto_program.instructions.begin());
607610

608611
while(true)
609612
{
610-
bool fixedpoint_changed_valuesets =
611-
static_analysis_baset::fixedpoint(goto_program, goto_functions);
613+
bool fixedpoint_changed_valuesets = static_analysis_baset::fixedpoint(
614+
goto_program, goto_functions, working_set);
612615

613616
if(!fixedpoint_changed_valuesets)
614617
break;
615618

616-
bool initializer_precise_evs_added =
617-
add_precise_evs_initializers(goto_program);
619+
working_set = add_precise_evs_initializers(goto_program, goto_functions);
618620

619-
if(!initializer_precise_evs_added)
621+
if(working_set.empty())
620622
break;
621623
}
622624
}
623625

624-
bool local_value_set_analysist::add_precise_evs_initializers(
625-
const goto_programt &goto_program)
626+
static_analysis_baset::working_sett
627+
local_value_set_analysist::add_precise_evs_initializers(
628+
const goto_programt &goto_program,
629+
const goto_functionst &goto_functions)
626630
{
627631
const std::string precise_evs_prefix = PRECISE_EVS_PREFIX;
628-
bool any_changes = false;
632+
static_analysis_baset::working_sett working_set;
629633

630634
for(locationt loc = goto_program.instructions.begin();
631635
loc != goto_program.instructions.end();
@@ -642,7 +646,14 @@ bool local_value_set_analysist::add_precise_evs_initializers(
642646
for(goto_programt::instructionst::const_iterator predecessor :
643647
loc->incoming_edges)
644648
{
645-
for(const auto &value : (*this)[predecessor].value_set.values)
649+
std::unique_ptr<local_value_set_domaint> tmp_state =
650+
util_make_unique<local_value_set_domaint>((*this)[predecessor]);
651+
local_value_set_domaint &incoming_state = *tmp_state;
652+
653+
transform_or_apply_function_call(
654+
predecessor, loc, goto_functions, incoming_state);
655+
656+
for(const auto &value : incoming_state.value_set.values)
646657
{
647658
const exprt &lhs = value.second.structured_lhs;
648659

@@ -673,11 +684,11 @@ bool local_value_set_analysist::add_precise_evs_initializers(
673684
bool object_map_changed = value_set.insert(entry.object_map, init_evs);
674685

675686
if(object_map_changed)
676-
any_changes = true;
687+
put_in_working_set(working_set, loc);
677688
}
678689
}
679690
}
680-
return any_changes;
691+
return working_set;
681692
}
682693

683694
void local_value_set_analysist::generate_state(locationt l)

src/pointer-analysis/local_value_set_analysis.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,9 @@ class local_value_set_analysist
242242
/// for precise external value sets to their value-sets if needed.
243243
/// \param goto_program: the program under analysis
244244
/// \return true if any value-sets were changed
245-
bool add_precise_evs_initializers(const goto_programt &goto_program);
245+
static_analysis_baset::working_sett add_precise_evs_initializers(
246+
const goto_programt &goto_program,
247+
const goto_functionst &goto_functions);
246248
virtual void generate_state(locationt l) override;
247249
};
248250

0 commit comments

Comments
 (0)