Skip to content

Commit 94e279c

Browse files
author
owen-jones-diffblue
authored
Merge pull request diffblue#321 from diffblue/owen-jones-diffblue/fix-evs-initializer-status
SEC-193: Various fix-ups for EVSs in LVSA (version 2)
2 parents d9e945b + 4a75f54 commit 94e279c

File tree

5 files changed

+72
-50
lines changed

5 files changed

+72
-50
lines changed

regression/LVSA/lvsa_driver.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,11 @@ def check_contains_per_field_evs(self, expected_number=1, is_initializer=False,
101101
matches = [x for x in matches if x.label.endswith(label)]
102102
assert expected_number == len(matches)
103103

104-
def check_contains_precise_evs(self, expected_number=1, access_path=None, label_suffix=None):
104+
def check_contains_precise_evs(self, expected_number=1, is_initializer=False, access_path=None, label_suffix=None):
105105
matches = [x for x in self.external_value_sets if x.evs_type == EvsType.precise]
106+
if is_initializer is not None:
107+
# Expect True or False
108+
matches = [x for x in matches if x.is_initializer == is_initializer]
106109
if access_path is not None:
107110
# Expect an array of strings, e.g. ['.a', '.b']
108111
matches = [x for x in matches if x.access_path_entries == access_path]

src/pointer-analysis/external_value_set_expr.h

+26-4
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ class external_value_set_exprt:public exprt
128128
return get_bool(ID_is_initializer);
129129
}
130130

131+
void set_initializer()
132+
{
133+
set(ID_is_initializer, ID_1);
134+
}
135+
131136
void set_non_initializer()
132137
{
133138
set(ID_is_initializer, ID_0);
@@ -212,7 +217,7 @@ class external_value_set_exprt:public exprt
212217
}
213218
}
214219

215-
/// Add a new entry to the access path
220+
/// Add a new entry to the access path, and set as not an initializer
216221
/// \param newentry: the entry to add to the access path
217222
/// \param evs_type: which external_value_set_type we want *this to become.
218223
/// A root object can become per field or precise. The other two must
@@ -226,6 +231,8 @@ class external_value_set_exprt:public exprt
226231
{
227232
PRECONDITION(evs_type!=external_value_set_typet::ROOT_OBJECT);
228233
set_external_value_set_type(evs_type);
234+
set_non_initializer();
235+
229236
switch(evs_type)
230237
{
231238
case external_value_set_typet::PER_FIELD:
@@ -250,9 +257,6 @@ class external_value_set_exprt:public exprt
250257
if(entry==newentry)
251258
return true;
252259

253-
/// Precise EVSs always have is_initializer=false
254-
set_non_initializer();
255-
256260
if(access_path_entries().empty())
257261
label()=constant_exprt(
258262
PRECISE_EVS_PREFIX+id2string(label().get_value()), string_typet());
@@ -267,6 +271,18 @@ class external_value_set_exprt:public exprt
267271
return false;
268272
}
269273

274+
external_value_set_exprt as_initializer() const
275+
{
276+
if(is_initializer())
277+
return *this;
278+
else
279+
{
280+
external_value_set_exprt copy = *this;
281+
copy.set_initializer();
282+
return copy;
283+
}
284+
}
285+
270286
external_value_set_exprt as_non_initializer() const
271287
{
272288
if(!is_initializer())
@@ -278,6 +294,12 @@ class external_value_set_exprt:public exprt
278294
return copy;
279295
}
280296
}
297+
298+
static const typet &get_precise_evs_irep_id()
299+
{
300+
static typet precise_evs("precise_evs");
301+
return precise_evs;
302+
}
281303
};
282304

283305
inline external_value_set_exprt &to_external_value_set(exprt &e)

src/pointer-analysis/local_value_set.cpp

+41-33
Original file line numberDiff line numberDiff line change
@@ -40,25 +40,6 @@ void local_value_sett::make_union_adjusting_evs_types(
4040
}
4141
}
4242

43-
std::pair<value_sett::valuest::iterator, bool>
44-
local_value_sett::init_external_value_set(const external_value_set_exprt &evse)
45-
{
46-
PRECONDITION(!evse.access_path_entries().empty());
47-
const auto &apback=evse.access_path_entries().back();
48-
std::string basename=evse.get_access_path_basename(apback.declared_on_type());
49-
std::string access_path_suffix=evse.get_access_path_suffix();
50-
std::string entryname=basename+access_path_suffix;
51-
52-
entryt entry(basename, access_path_suffix, apback.declared_on_type(), evse);
53-
54-
auto insert_result=values.insert(std::make_pair(irep_idt(entryname), entry));
55-
56-
if(insert_result.second)
57-
insert(insert_result.first->second.object_map, evse);
58-
59-
return insert_result;
60-
}
61-
6243
/// Builds a version of expr suitable for alias-comparison
6344
/// \param expr: The expression to be converted to the alias-uniform structure
6445
/// \return expr without information which is irrelevant to alias-comparison
@@ -282,11 +263,27 @@ void local_value_sett::get_value_set_rec(
282263
new_entry, external_value_set_typet::PER_FIELD);
283264
new_ext_set.type()=field_type.subtype();
284265

285-
// TODO: figure out how to do this sort of on-demand-insert
286-
// without such ugly const hacking:
287-
auto insert_result=
288-
(const_cast<local_value_sett *>(this))->
289-
init_external_value_set(new_ext_set);
266+
std::string basename =
267+
new_ext_set.get_access_path_basename(declared_on_type);
268+
std::string entryname = basename + access_path_suffix;
269+
270+
entryt entry(
271+
basename, access_path_suffix, declared_on_type, new_ext_set);
272+
273+
/// If there is already an entry for this EVS then find it, otherwise
274+
/// create a new entry for it
275+
/// TODO: figure out how to do this sort of on-demand-insert
276+
/// without such ugly const hacking:
277+
auto insert_result =
278+
(const_cast<local_value_sett *>(this))
279+
->values.insert(std::make_pair(irep_idt(entryname), entry));
280+
281+
/// If we've just created a new entry then populate the object map
282+
/// with an initializer EVS
283+
if(insert_result.second)
284+
insert(
285+
insert_result.first->second.object_map,
286+
new_ext_set.as_initializer());
290287

291288
make_union(dest, insert_result.first->second.object_map);
292289
}
@@ -309,13 +306,21 @@ void local_value_sett::get_value_set_rec(
309306
{
310307
new_ext_set.type()=field_type.subtype();
311308

312-
// TODO: figure out how to do this sort of on-demand-insert
313-
// without such ugly const hacking:
314-
auto insert_result=
315-
(const_cast<local_value_sett *>(this))->
316-
init_external_value_set(new_ext_set);
317-
318-
make_union(dest, insert_result.first->second.object_map);
309+
declared_on_type =
310+
external_value_set_exprt::get_precise_evs_irep_id();
311+
std::string basename =
312+
new_ext_set.get_access_path_basename(declared_on_type);
313+
access_path_suffix = new_ext_set.get_access_path_suffix();
314+
std::string entryname = basename + access_path_suffix;
315+
316+
const auto it = values.find(entryname);
317+
318+
/// If an entry already exists then use the values in the object
319+
/// map, otherwise do not create an entry and use the EVS
320+
if(it != values.end())
321+
make_union(dest, it->second.object_map);
322+
else
323+
insert(dest, new_ext_set);
319324
}
320325
}
321326
}
@@ -582,7 +587,7 @@ void local_value_sett::assign_rec(
582587
if(insert_result.second && field_type.id()==ID_pointer)
583588
{
584589
new_ext_set.type()=field_type.subtype();
585-
insert(lhs_entry.object_map, new_ext_set);
590+
insert(lhs_entry.object_map, new_ext_set.as_initializer());
586591
}
587592

588593
make_union(lhs_entry.object_map, values_rhs);
@@ -608,7 +613,10 @@ void local_value_sett::assign_rec(
608613
std::string entryname=basename+access_path_suffix;
609614

610615
entryt entry(
611-
basename, access_path_suffix, declared_on_type, new_ext_set);
616+
basename,
617+
access_path_suffix,
618+
external_value_set_exprt::get_precise_evs_irep_id(),
619+
new_ext_set);
612620

613621
auto insert_result=const_cast<valuest &>(values).
614622
insert(std::make_pair(irep_idt(entryname), entry));

src/pointer-analysis/local_value_set.h

-11
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,6 @@ class local_value_sett:public value_sett
5050
const object_mapt &src,
5151
const typet&) const;
5252

53-
/// Gets or creates a value-set entry corresponding to an external value set
54-
/// expression, which initially contains the EVS itself. For example, given
55-
/// EVS(A.x), representing all `x` fields of objects of type `A`, this would
56-
/// create an entry `external_objects.A.x <- EVS(A.x)` if it didn't already
57-
/// exist and return an iterator pointing to it.
58-
/// \param evse: external value set whose entry to create
59-
/// \return a la `std::map::insert`, a pair of an iterator pointing to the
60-
/// relevant entry and a boolean indicating if it is new.
61-
std::pair<valuest::iterator, bool> init_external_value_set(
62-
const external_value_set_exprt& evse);
63-
6453
// For all the overrides below, see the base type for parameter-level docs
6554
// as their meanings are unchanged.
6655

src/pointer-analysis/local_value_set_analysis.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void local_value_set_analysist::initialize(const goto_programt &fun)
8888
extsym.type().subtype(),
8989
constant_exprt(extsym_name, string_typet()),
9090
default_mode_for_new_evs,
91-
true);
91+
false);
9292
local_value_sett::entryt extsym_entry_blank(
9393
id2string(extsym_name), "", typet(), extsym_var);
9494
auto &extsym_entry = initial_state.get_entry(

0 commit comments

Comments
 (0)