Skip to content

Commit 8e88c89

Browse files
authored
Merge pull request diffblue#274 from diffblue/owen-jones-diffblue/refactor-lvsa
Minor improvements to LVSA code
2 parents 8706385 + 00badf2 commit 8e88c89

File tree

6 files changed

+96
-58
lines changed

6 files changed

+96
-58
lines changed

cbmc/src/pointer-analysis/value_set_analysis.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ Author: Daniel Kroening, [email protected]
2424

2525
class xmlt;
2626

27-
template<class Value_Sett>
27+
template<class Value_Set_Domaint>
2828
class value_set_analysis_baset:
2929
public value_setst,
30-
public static_analysist<value_set_domaint<Value_Sett> >
30+
public static_analysist<Value_Set_Domaint>
3131
{
3232
public:
33-
typedef value_set_domaint<Value_Sett> domaint;
33+
typedef Value_Set_Domaint domaint;
3434
typedef static_analysist<domaint> baset;
3535
typedef typename baset::locationt locationt;
3636

@@ -39,11 +39,11 @@ class value_set_analysis_baset:
3939
}
4040

4141
// overloading
42-
void initialize(const goto_programt &goto_program)
42+
void initialize(const goto_programt &goto_program) override
4343
{
4444
baset::initialize(goto_program);
4545
}
46-
void initialize(const goto_functionst &goto_functions)
46+
void initialize(const goto_functionst &goto_functions) override
4747
{
4848
baset::initialize(goto_functions);
4949
}
@@ -105,7 +105,7 @@ class value_set_analysis_baset:
105105
virtual void get_values(
106106
locationt l,
107107
const exprt &expr,
108-
value_setst::valuest &dest)
108+
value_setst::valuest &dest) override
109109
{
110110
((const value_sett&)(*this)[l].value_set).get_value_set(
111111
expr,
@@ -134,7 +134,8 @@ class value_set_analysis_baset:
134134
}
135135
};
136136

137-
typedef value_set_analysis_baset<value_sett> value_set_analysist;
137+
typedef value_set_analysis_baset<value_set_domaint<value_sett> >
138+
value_set_analysist;
138139

139140
void convert(
140141
const goto_functionst &goto_functions,

src/pointer-analysis/local_value_set.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,9 @@ void local_value_sett::apply_code(
528528
baset::apply_code(code, ns);
529529
}
530530
}
531+
532+
void local_value_sett::make_union_bookkeeping_data_structures(
533+
const local_value_sett &other)
534+
{
535+
use_precise_evs = use_precise_evs && other.use_precise_evs;
536+
}

src/pointer-analysis/local_value_set.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class local_value_sett:public value_sett
2222
#endif
2323

2424
declared_on_type_mapt declared_on_types;
25+
mutable bool use_precise_evs=true;
2526

2627
void make_union_adjusting_evs_types(
2728
object_mapt &dest,
@@ -48,6 +49,8 @@ class local_value_sett:public value_sett
4849
const codet &,
4950
const namespacet &) override;
5051

52+
void make_union_bookkeeping_data_structures(const local_value_sett &other);
53+
5154
protected:
5255
void get_value_set_rec(
5356
const exprt &expr,

src/pointer-analysis/local_value_set_analysis.cpp

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ void local_value_set_analysist::initialize(const goto_programt &fun)
6666
external_symbols.end());
6767

6868
auto &initial_state=(*this)[fun.instructions.begin()].value_set;
69+
const external_value_set_typet
70+
default_mode_for_new_evs=external_value_set_typet::ROOT_OBJECT;
6971

7072
// Now insert fresh symbols for each external symbol,
7173
// indicating an unknown external points-to set.
@@ -83,7 +85,7 @@ void local_value_set_analysist::initialize(const goto_programt &fun)
8385
external_value_set_exprt extsym_var(
8486
extsym.type().subtype(),
8587
constant_exprt(extsym_name, string_typet()),
86-
external_value_set_typet::ROOT_OBJECT,
88+
default_mode_for_new_evs,
8789
true);
8890
initial_state.insert(extsym_entry.object_map, extsym_var);
8991
}
@@ -129,44 +131,41 @@ void local_value_set_analysist::transform_function_stub(
129131
const symbolt &function_symbol=ns.lookup(fname);
130132
const code_function_callt &fcall=to_code_function_call(l_call->code);
131133

132-
std::shared_ptr<lvsaa_single_external_set_summaryt> call_summary =
133-
summarydb.at(fname);
134+
const auto &assignments=summarydb.at(fname)->field_assignments;
134135

135136
// The summary gives a list of inclusions, in the form symbol1 <- symbol2,
136137
// indicating that values reachable before the call from symbol2
137-
// may now be reachable from symbol1. The assignments are simeltaneous.
138+
// may now be reachable from symbol1. The assignments are simultaneous.
138139
// Thus start by reading all RHS values, before any changes are made:
139140

140141
auto &valuesets=static_cast<domaint&>(state).value_set;
141142
std::map<exprt, local_value_sett::object_mapt> pre_call_rhs_value_sets;
142-
const std::string external_objects_basename_prefix="external_objects";
143+
const std::string per_field_evs_prefix="external_objects";
143144

144145
std::set<std::pair<std::string, std::string> > lhs_written;
145146

146-
for(const auto &assignment : call_summary->field_assignments)
147+
for(const auto &assignment : assignments)
147148
{
148149
++nstub_assignments;
150+
const auto &lhs_fieldname=assignment.first;
149151
const auto &rhs_expr=assignment.second;
150152
if(pre_call_rhs_value_sets.count(rhs_expr))
151153
continue;
152154
auto &rhs_map=pre_call_rhs_value_sets[rhs_expr];
153-
if(assignment.second.id()==ID_external_value_set)
155+
if(rhs_expr.id()==ID_external_value_set)
154156
{
155-
auto &evse=to_external_value_set(assignment.second);
157+
const auto &evse=to_external_value_set(rhs_expr);
158+
const std::string &evse_label=
159+
id2string(to_constant_expr(evse.label()).get_value());
160+
156161
// Differentiate external-set entries that only contain
157162
// their initialiser from ones that have been written:
158163
if(!evse.is_initializer())
159-
{
160-
lhs_written.insert({
161-
assignment.first.base_name,
162-
assignment.first.field_name});
163-
}
164-
if(has_prefix(
165-
id2string(to_constant_expr(evse.label()).get_value()),
166-
"external_objects"))
164+
lhs_written.insert({lhs_fieldname.base_name, lhs_fieldname.field_name});
165+
166+
if(has_prefix(evse_label, per_field_evs_prefix))
167167
{
168168
std::vector<local_value_sett::entryt*> rhs_entries;
169-
const auto &evse=to_external_value_set(assignment.second);
170169
PRECONDITION(!evse.access_path_entries().empty());
171170
const auto &apback=evse.access_path_entries().back();
172171
if(!evse.is_initializer())
@@ -179,20 +178,21 @@ void local_value_set_analysist::transform_function_stub(
179178
}
180179

181180
for(const auto &rhs_entry : rhs_entries)
181+
{
182182
valuesets.make_union_adjusting_evs_types(
183183
rhs_map,
184184
rhs_entry->object_map,
185185
evse.type());
186+
}
186187
// Also add the external set itself,
187188
// representing the possibility that the read
188189
// comes from outside *this* function as well:
189190
valuesets.insert(rhs_map, evse);
190191
}
191192
else
192193
{
193-
// This should be an external value set assigned
194-
// to initialise some global or parameter.
195-
assert(evse.access_path_entries().empty());
194+
// This should be an external value set of type ROOT_OBJECT.
195+
PRECONDITION(evse.access_path_entries().empty());
196196
const symbolt &inflow_symbol=
197197
ns.lookup(to_constant_expr(evse.label()).get_value());
198198
exprt inflow_expr;
@@ -222,7 +222,7 @@ void local_value_set_analysist::transform_function_stub(
222222
<< to_constant_expr(evse.label()).get_value()
223223
<< eom;
224224
}
225-
assert(paramidx!=(size_t)-1 && "Unknown parameter symbol?");
225+
INVARIANT(paramidx!=(size_t)-1, "Unknown parameter symbol?");
226226
inflow_expr=fcall.arguments()[paramidx];
227227
}
228228
pointer_typet expect_type=pointer_type(evse.type());
@@ -234,49 +234,48 @@ void local_value_set_analysist::transform_function_stub(
234234
else
235235
{
236236
// Ordinary value set member; just add to the RHS map.
237-
valuesets.insert(rhs_map, assignment.second);
238-
lhs_written.insert({
239-
assignment.first.base_name,
240-
assignment.first.field_name});
237+
valuesets.insert(rhs_map, rhs_expr);
238+
lhs_written.insert({lhs_fieldname.base_name, lhs_fieldname.field_name});
241239
}
242240
}
243241

244242
// OK, read all the RHS sets, now assign to the LHS symbols:
245243

246-
for(const auto &assignment : call_summary->field_assignments)
244+
for(const auto &assignment : assignments)
247245
{
246+
const auto &lhs_fieldname=assignment.first;
248247
const auto &rhs_values=pre_call_rhs_value_sets.at(assignment.second);
249248

250-
if(has_prefix(assignment.first.base_name, external_objects_basename_prefix))
249+
if(has_prefix(lhs_fieldname.base_name, per_field_evs_prefix))
251250
{
252251
std::vector<local_value_sett::entryt*> lhs_entries;
253252
const auto find_pair=std::make_pair(
254-
assignment.first.base_name,
255-
assignment.first.field_name);
253+
lhs_fieldname.base_name,
254+
lhs_fieldname.field_name);
256255
if(lhs_written.count(find_pair))
257256
get_all_field_value_sets(
258-
assignment.first.field_name,
259-
assignment.first.declared_on_type,
257+
lhs_fieldname.field_name,
258+
lhs_fieldname.declared_on_type,
260259
valuesets,
261260
lhs_entries);
262261
// Also write to the external value set itself:
263262
local_value_sett::entryt evse_entry(
264-
assignment.first.base_name,
265-
assignment.first.field_name,
266-
assignment.first.declared_on_type);
267-
std::string objkey=assignment.first.base_name+assignment.first.field_name;
263+
lhs_fieldname.base_name,
264+
lhs_fieldname.field_name,
265+
lhs_fieldname.declared_on_type);
266+
std::string objkey=lhs_fieldname.base_name+lhs_fieldname.field_name;
268267
auto insertit=valuesets.values.insert(std::make_pair(objkey, evse_entry));
269268
lhs_entries.push_back(&insertit.first->second);
270269
for(auto lhs_entry : lhs_entries)
271270
valuesets.make_union(lhs_entry->object_map, rhs_values);
272271
}
273-
else if(has_prefix(assignment.first.base_name, prefix_dynamic_object))
272+
else if(has_prefix(lhs_fieldname.base_name, prefix_dynamic_object))
274273
{
275-
std::string objkey=assignment.first.base_name+assignment.first.field_name;
274+
std::string objkey=lhs_fieldname.base_name+lhs_fieldname.field_name;
276275
local_value_sett::entryt dynobj_entry_name(
277-
assignment.first.base_name,
278-
assignment.first.field_name,
279-
assignment.first.declared_on_type);
276+
lhs_fieldname.base_name,
277+
lhs_fieldname.field_name,
278+
lhs_fieldname.declared_on_type);
280279
auto insertit=
281280
valuesets.values.insert(std::make_pair(objkey, dynobj_entry_name));
282281
valuesets.make_union(insertit.first->second.object_map, rhs_values);
@@ -285,12 +284,14 @@ void local_value_set_analysist::transform_function_stub(
285284
{
286285
// The only other kind of symbols mentioned
287286
// in summary LHS are global variables.
288-
assert(assignment.first.field_name=="");
289-
const auto &global_sym=ns.lookup(assignment.first.base_name);
287+
INVARIANT(
288+
lhs_fieldname.field_name=="",
289+
"unexpected lhs entry in call summary assignments");
290+
const auto &global_sym=ns.lookup(lhs_fieldname.base_name);
290291
local_value_sett::entryt global_entry_name(
291-
assignment.first.base_name,
292+
lhs_fieldname.base_name,
292293
"",
293-
assignment.first.declared_on_type);
294+
lhs_fieldname.declared_on_type);
294295
auto &global_entry=
295296
valuesets.get_entry(global_entry_name, global_sym.type, ns);
296297
valuesets.make_union(global_entry.object_map, rhs_values);
@@ -409,17 +410,20 @@ void lvsaa_single_external_set_summaryt::from_final_state(
409410
// by this function, and the values they may be assigned.
410411

411412
std::vector<local_value_sett::valuest::const_iterator> to_export;
413+
const std::string per_field_evs_prefix="external_objects";
412414

413-
for(auto it=final_state.values.begin(), itend=final_state.values.end();
414-
it!=itend;
415+
for(auto it=final_state.values.begin();
416+
it!=final_state.values.end();
415417
++it)
416418
{
417419
const auto &entry=*it;
418-
const std::string prefix="external_objects";
420+
419421
const std::string entryname=id2string(entry.first);
420422
bool export_this_entry=false;
421-
if(has_prefix(entryname, prefix))
423+
if(has_prefix(entryname, per_field_evs_prefix))
424+
{
422425
export_this_entry=true;
426+
}
423427
if((!export_this_entry) &&
424428
has_prefix(entryname, prefix_dynamic_object))
425429
{
@@ -482,7 +486,7 @@ void lvsaa_single_external_set_summaryt::from_final_state(
482486
id2string(entry.second.identifier),
483487
entry.second.suffix,
484488
entry.second.declared_on_type);
485-
field_assignments.push_back(std::make_pair(thisname, *toexport));
489+
field_assignments.emplace_back(thisname, *toexport);
486490
}
487491
}
488492
}

src/pointer-analysis/local_value_set_analysis.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <pointer-analysis/value_set_analysis.h>
1010
#include "local_value_set.h"
11+
#include "local_value_set_domain.h"
1112
#include <pointer-analysis/external_value_set_expr.h>
1213
#include <summaries/summary.h>
1314
#include <util/message.h>
@@ -59,10 +60,10 @@ class lvsaa_single_external_set_summaryt:public summaryt
5960
// to talk about external entities, rather than simply declare them unknown.
6061

6162
class local_value_set_analysist
62-
: public value_set_analysis_baset<local_value_sett>, public messaget
63+
: public value_set_analysis_baset<local_value_set_domaint>, public messaget
6364
{
6465
public:
65-
typedef value_set_analysis_baset<local_value_sett> baset;
66+
typedef value_set_analysis_baset<local_value_set_domaint> baset;
6667
typedef cached_mapt<irep_idt, lvsaa_single_external_set_summaryt> dbt;
6768

6869
local_value_set_analysist(
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016-2017 Diffblue Limited. All Rights Reserved.
2+
3+
/// \file
4+
/// Local value-set analysis
5+
6+
#ifndef SECURITY_SCANNER_POINTER_ANALYSIS_LOCAL_VALUE_SET_DOMAIN_H
7+
#define SECURITY_SCANNER_POINTER_ANALYSIS_LOCAL_VALUE_SET_DOMAIN_H
8+
9+
#include <pointer-analysis/value_set.h>
10+
#include <pointer-analysis/value_set_domain.h>
11+
12+
class local_value_set_domaint:public value_set_domaint<local_value_sett>
13+
{
14+
public:
15+
16+
bool merge(const local_value_set_domaint &other, locationt to)
17+
{
18+
value_set.make_union_bookkeeping_data_structures(other.value_set);
19+
return value_set.make_union(other.value_set);
20+
}
21+
};
22+
23+
#endif

0 commit comments

Comments
 (0)