Skip to content

Commit d9e945b

Browse files
author
owen-jones-diffblue
authored
Merge pull request diffblue#317 from diffblue/owen-jones-diffblue/fix-evs-bugs-and-add-subtype-and-array-tests
SEC-182: Owen jones diffblue/fix evs bugs and add subtype and array tests
2 parents aea7a32 + 601e3c5 commit d9e945b

File tree

9 files changed

+263
-66
lines changed

9 files changed

+263
-66
lines changed

regression/LVSA/TestEVS/Test$A.class

499 Bytes
Binary file not shown.

regression/LVSA/TestEVS/Test$B.class

467 Bytes
Binary file not shown.

regression/LVSA/TestEVS/Test$C.class

459 Bytes
Binary file not shown.

regression/LVSA/TestEVS/Test$D.class

494 Bytes
Binary file not shown.

regression/LVSA/TestEVS/Test.class

1.72 KB
Binary file not shown.

regression/LVSA/TestEVS/Test.java

+62
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,66 @@ public void is_initializer_flag(Node parameter_node) {
3030
parameter_node.right = new Object();
3131
static_object = parameter_node.left;
3232
}
33+
34+
public class A {
35+
Node node;
36+
}
37+
38+
public class B extends A {
39+
Object extra_field;
40+
}
41+
42+
public void read_from_field_from_supertype(B b) {
43+
static_object = b.node.left;
44+
}
45+
46+
public void write_to_field_from_supertype(B b) {
47+
b.node.left = new Object();
48+
Node n = b.node;
49+
static_object = n.left;
50+
}
51+
52+
public void write_to_field_of_A(A a, Node node_parameter) {
53+
a.node = node_parameter;
54+
}
55+
56+
public void write_to_field_of_B_through_A(B b, Node node_parameter) {
57+
write_to_field_of_A(b, node_parameter);
58+
static_node = b.node;
59+
}
60+
61+
public void read_from_array(Object object_array[]) {
62+
static_object = object_array[0];
63+
}
64+
65+
public void write_to_array(Object object_array[]) {
66+
object_array[0] = new Object();
67+
static_object = object_array[0];
68+
}
69+
70+
public void read_from_field_of_object_in_array(Node node_array[]) {
71+
static_object = node_array[0].left;
72+
}
73+
74+
public void write_to_field_of_object_in_array(Node node_array[]) {
75+
node_array[0].left = new Object();
76+
static_object = node_array[0].left;
77+
}
78+
79+
public class C {
80+
Object object_array[];
81+
}
82+
83+
public class D {
84+
A a_array[];
85+
}
86+
87+
public void read_from_array_field(C c) {
88+
static_object = c.object_array[0];
89+
}
90+
91+
public void write_to_array_field(C c) {
92+
c.object_array[0] = new Object();
93+
static_object = c.object_array[0];
94+
}
3395
}

regression/LVSA/TestEVS/test_evs.py

+104
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,107 @@ def test_is_initializer_flag(tmpdir):
6060
value_set_expectation_2.check_number_of_values(2)
6161
value_set_expectation_2.check_contains_dynamic_object(is_most_recent_allocation=True)
6262
value_set_expectation_2.check_contains_per_field_evs(access_path=['.left'])
63+
64+
65+
def test_read_from_field_from_supertype(tmpdir):
66+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('read_from_field_from_supertype')
67+
lvsa_expectation = lvsa_driver.run()
68+
69+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
70+
71+
value_set_expectation.check_number_of_values(2)
72+
value_set_expectation.check_contains_per_field_evs(access_path=['.left'])
73+
value_set_expectation.check_contains_precise_evs(access_path=['[email protected]$A.node', '.left'])
74+
75+
76+
def test_write_to_field_from_supertype(tmpdir):
77+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('write_to_field_from_supertype')
78+
lvsa_expectation = lvsa_driver.run()
79+
80+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
81+
82+
value_set_expectation.check_number_of_values(3)
83+
value_set_expectation.check_contains_dynamic_object()
84+
value_set_expectation.check_contains_per_field_evs(access_path=['.left'])
85+
value_set_expectation.check_contains_precise_evs(access_path=['[email protected]$A.node', '.left'])
86+
87+
88+
def test_write_to_field_of_B_through_A(tmpdir):
89+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('write_to_field_of_B_through_A')
90+
lvsa_expectation = lvsa_driver.run()
91+
92+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_node')
93+
94+
value_set_expectation.check_number_of_values(2)
95+
value_set_expectation.check_contains_root_object_evs(label_suffix='node_parameter')
96+
value_set_expectation.check_contains_per_field_evs(access_path=['.node'])
97+
98+
99+
def test_read_from_array(tmpdir):
100+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('read_from_array')
101+
lvsa_expectation = lvsa_driver.run()
102+
103+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
104+
105+
value_set_expectation.check_number_of_values(2)
106+
value_set_expectation.check_contains_per_field_evs(access_path=['[]'])
107+
value_set_expectation.check_contains_precise_evs(access_path=['.data', '[]'])
108+
109+
110+
def test_write_to_array(tmpdir):
111+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('write_to_array')
112+
lvsa_expectation = lvsa_driver.run()
113+
114+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
115+
116+
value_set_expectation.check_number_of_values(3)
117+
value_set_expectation.check_contains_dynamic_object()
118+
value_set_expectation.check_contains_per_field_evs(access_path=['[]'])
119+
value_set_expectation.check_contains_precise_evs(access_path=['.data', '[]'])
120+
121+
122+
def test_read_from_field_of_object_in_array(tmpdir):
123+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('read_from_field_of_object_in_array')
124+
lvsa_expectation = lvsa_driver.run()
125+
126+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
127+
128+
value_set_expectation.check_number_of_values(2)
129+
value_set_expectation.check_contains_per_field_evs(access_path=['.left'])
130+
value_set_expectation.check_contains_precise_evs(access_path=['.data', '[]', '.left'])
131+
132+
133+
def test_write_to_field_of_object_in_array(tmpdir):
134+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('write_to_field_of_object_in_array')
135+
lvsa_expectation = lvsa_driver.run()
136+
137+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
138+
139+
value_set_expectation.check_number_of_values(3)
140+
value_set_expectation.check_contains_dynamic_object()
141+
value_set_expectation.check_contains_per_field_evs(access_path=['.left'])
142+
value_set_expectation.check_contains_precise_evs(access_path=['.data', '[]', '.left'])
143+
144+
145+
def test_read_from_array_field(tmpdir):
146+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('read_from_array_field')
147+
lvsa_expectation = lvsa_driver.run()
148+
149+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
150+
151+
value_set_expectation.check_number_of_values(2)
152+
value_set_expectation.check_contains_per_field_evs(access_path=['[]'])
153+
value_set_expectation.check_contains_precise_evs(access_path=['.object_array','.data', '[]'])
154+
155+
156+
def test_write_to_array_field(tmpdir):
157+
lvsa_driver = LvsaDriver(tmpdir, folder_name).with_test_function('write_to_array_field')
158+
lvsa_expectation = lvsa_driver.run()
159+
160+
value_set_expectation = lvsa_expectation.get_value_set_for_public_static('static_object')
161+
162+
value_set_expectation.check_number_of_values(3)
163+
value_set_expectation.check_contains_dynamic_object()
164+
value_set_expectation.check_contains_per_field_evs(access_path=['[]'])
165+
value_set_expectation.check_contains_precise_evs(access_path=['.object_array','.data', '[]'])
166+

src/pointer-analysis/local_value_set.cpp

+32-36
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ static const typet &type_from_suffix(
168168
return static_cast<const typet&>(get_nil_irep());
169169
// Otherwise this is the base class.
170170
// Can't use the method below because it might contain periods.
171-
const auto &subclass_comp=to_struct_union_type(*ret).components()[0];
172-
std::string subclass_name=id2string(subclass_comp.get_name());
173-
assert(has_infix(suffix, subclass_name, next_member));
174-
ret=&subclass_comp.type();
175-
next_member+=(subclass_name.size()+1);
171+
const auto &superclass_comp = to_struct_union_type(*ret).components()[0];
172+
std::string superclass_name = id2string(superclass_comp.get_name());
173+
assert(has_infix(suffix, superclass_name, next_member));
174+
ret = &superclass_comp.type();
175+
next_member += (superclass_name.size() + 1);
176176
suffix_without_supertypes=suffix.substr(next_member-1);
177177
}
178178
else
@@ -252,37 +252,30 @@ void local_value_sett::get_value_set_rec(
252252
// if it hasn't been initialised yet, do so now.
253253

254254
typet declared_on_type;
255-
std::string suffix_without_subtype;
256-
const typet &field_type=
257-
type_from_suffix(
258-
expr.type(),
259-
suffix,
260-
ns,
261-
declared_on_type,
262-
suffix_without_subtype);
255+
std::string suffix_without_supertypes;
256+
const typet &field_type = type_from_suffix(
257+
expr.type(), suffix, ns, declared_on_type, suffix_without_supertypes);
263258
if(field_type.id()==ID_pointer)
264259
{
265260
// Temporary: keep track of whether we read from an EVS, so we can
266261
// ignore precise access path EVSs when applying function summaries if
267262
// there are any reads from EVSs.
268263
++num_reads_of_field_of_external_object;
269264

270-
std::string access_path_suffix=
271-
suffix_without_subtype == "" ?
272-
"[]" :
273-
suffix_without_subtype;
274265
const auto &extinit=to_external_value_set(expr);
275266

276-
access_path_entry_exprt new_entry(
277-
access_path_suffix,
278-
function,
279-
std::to_string(location_number),
280-
declared_on_type);
281267
// If we're reading from `EVS(A.b)` then initialize an entry for that
282268
// EVS containing an initializer (e.g.
283269
// `external_objects.A.b <- { EVS(A.b) }`.
284270
if(extinit.can_extend_to_imprecise())
285271
{
272+
std::string access_path_suffix =
273+
suffix_without_supertypes.empty() ? "[]" : suffix_without_supertypes;
274+
access_path_entry_exprt new_entry(
275+
access_path_suffix,
276+
function,
277+
std::to_string(location_number),
278+
declared_on_type);
286279
/// Create external value set for the type and suffix
287280
external_value_set_exprt new_ext_set=extinit;
288281
new_ext_set.extend_access_path(
@@ -300,6 +293,12 @@ void local_value_sett::get_value_set_rec(
300293

301294
if(extinit.can_extend_to_precise())
302295
{
296+
std::string access_path_suffix = suffix.empty() ? "[]" : suffix;
297+
access_path_entry_exprt new_entry(
298+
access_path_suffix,
299+
function,
300+
std::to_string(location_number),
301+
declared_on_type);
303302
/// Create external value set for the precise access path
304303
external_value_set_exprt new_ext_set=extinit;
305304
bool loop_found=new_ext_set.extend_access_path(
@@ -489,13 +488,13 @@ void local_value_sett::assign_rec(
489488
const irep_idt &identifier=to_symbol_expr(lhs).get_identifier();
490489

491490
typet declared_on_type;
492-
std::string suffix_without_subtype_ignored;
491+
std::string suffix_without_supertypes_ignored;
493492
type_from_suffix(
494493
lhs.type(),
495494
suffix,
496495
ns,
497496
declared_on_type,
498-
suffix_without_subtype_ignored);
497+
suffix_without_supertypes_ignored);
499498
entryt &e = get_entry(
500499
entryt(identifier, suffix, declared_on_type, lhs), lhs.type(), ns);
501500

@@ -512,13 +511,13 @@ void local_value_sett::assign_rec(
512511
std::string name=get_dynamic_object_name(dynamic_object);
513512

514513
typet declared_on_type;
515-
std::string suffix_without_subtype_ignored;
514+
std::string suffix_without_supertypes_ignored;
516515
type_from_suffix(
517516
lhs.type(),
518517
suffix,
519518
ns,
520519
declared_on_type,
521-
suffix_without_subtype_ignored);
520+
suffix_without_supertypes_ignored);
522521

523522
entryt &entry =
524523
get_entry(entryt(name, suffix, declared_on_type, lhs), lhs.type(), ns);
@@ -544,15 +543,9 @@ void local_value_sett::assign_rec(
544543
// Write through an opaque external value set.
545544
const auto &evsi=to_external_value_set(lhs);
546545
typet declared_on_type;
547-
std::string suffix_without_subtype;
548-
const typet &field_type=type_from_suffix(
549-
lhs.type(),
550-
suffix,
551-
ns,
552-
declared_on_type,
553-
suffix_without_subtype);
554-
std::string access_path_suffix=
555-
suffix_without_subtype.empty() ? "[]" : suffix_without_subtype;
546+
std::string suffix_without_supertypes;
547+
const typet &field_type = type_from_suffix(
548+
lhs.type(), suffix, ns, declared_on_type, suffix_without_supertypes);
556549

557550
if(field_type.id()==ID_pointer)
558551
{
@@ -564,6 +557,8 @@ void local_value_sett::assign_rec(
564557

565558
if(evsi.can_extend_to_imprecise())
566559
{
560+
std::string access_path_suffix =
561+
suffix_without_supertypes.empty() ? "[]" : suffix_without_supertypes;
567562
access_path_entry_exprt new_entry(
568563
access_path_suffix,
569564
function,
@@ -595,8 +590,9 @@ void local_value_sett::assign_rec(
595590

596591
if(evsi.can_extend_to_precise())
597592
{
593+
std::string access_path_suffix = suffix.empty() ? "[]" : suffix;
598594
access_path_entry_exprt new_entry(
599-
suffix,
595+
access_path_suffix,
600596
function,
601597
std::to_string(location_number),
602598
declared_on_type);

0 commit comments

Comments
 (0)