Skip to content

Commit 0cfa0c9

Browse files
committed
goto-symex: expand unknown points-to values to all objects
Non-deterministic pointers should consider all possible objects. goto-symex is aware of all current objects, and can thus expand points-to values of "unknown" to all current objects (leaving the pointer offset unconstrained).
1 parent 2611c6d commit 0cfa0c9

File tree

3 files changed

+68
-15
lines changed

3 files changed

+68
-15
lines changed

src/goto-symex/symex_dereference_state.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "symex_dereference_state.h"
1313

14+
#include <util/pointer_expr.h>
1415
#include <util/symbol_table.h>
1516

1617
/// Get or create a failed symbol for the given pointer-typed expression. These
@@ -80,5 +81,39 @@ symex_dereference_statet::get_or_create_failed_symbol(const exprt &expr)
8081
std::vector<exprt>
8182
symex_dereference_statet::get_value_set(const exprt &expr) const
8283
{
83-
return state.value_set.get_value_set(expr, ns);
84+
auto result = state.value_set.get_value_set(expr, ns);
85+
86+
bool has_unknown = result.empty();
87+
for(const auto &v : result)
88+
{
89+
if(v.id() == ID_unknown)
90+
{
91+
has_unknown = true;
92+
break;
93+
}
94+
}
95+
96+
if(has_unknown)
97+
{
98+
#if 0
99+
// The value set only knows about objects the address of which has been
100+
// taken, and may therefore still present an underapproximation for
101+
// non-deterministic pointers.
102+
result = state.value_set.get_any_object(expr, ns);
103+
#else
104+
state.get_level2().current_names.iterate(
105+
[this, &result](
106+
const irep_idt &key, const std::pair<ssa_exprt, std::size_t> &entry) {
107+
const irep_idt &obj_identifier = entry.first.get_object_name();
108+
if(obj_identifier != state.guard_identifier())
109+
result.emplace_back(
110+
object_descriptor_exprt{ns.lookup(obj_identifier).symbol_expr()});
111+
});
112+
113+
result.emplace_back(object_descriptor_exprt{
114+
exprt(ID_null_object, to_pointer_type(expr.type()).subtype())});
115+
#endif
116+
}
117+
118+
return result;
84119
}

src/pointer-analysis/value_set.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,30 @@ value_sett::object_mapt value_sett::get_value_set(
371371
return dest;
372372
}
373373

374+
std::vector<exprt>
375+
value_sett::get_any_object(exprt expr, const namespacet &ns) const
376+
{
377+
if(expr.type().id() != ID_pointer)
378+
return {};
379+
380+
object_mapt object_map;
381+
382+
// we'll take the union of all objects we see, with unspecified offsets
383+
values.iterate([this, &object_map](const irep_idt &key, const entryt &value) {
384+
for(const auto &object : value.object_map.read())
385+
insert(object_map, object.first, offsett());
386+
});
387+
388+
// we'll add null, in case it's not there yet
389+
insert(
390+
object_map,
391+
exprt(ID_null_object, to_pointer_type(expr.type()).subtype()),
392+
offsett());
393+
394+
return make_range(object_map.read())
395+
.map([&](const object_map_dt::value_type &pair) { return to_expr(pair); });
396+
}
397+
374398
/// Check if 'suffix' starts with 'field'.
375399
/// Suffix is delimited by periods and '[]' (array access) tokens, so we're
376400
/// looking for ".field($|[]|.)"
@@ -507,20 +531,7 @@ void value_sett::get_value_set_rec(
507531
}
508532
else if(expr.id() == ID_nondet_symbol)
509533
{
510-
if(expr.type().id() == ID_pointer)
511-
{
512-
// we'll take the union of all objects we see, with unspecified offsets
513-
values.iterate([this, &dest](const irep_idt &key, const entryt &value) {
514-
for(const auto &object : value.object_map.read())
515-
insert(dest, object.first, offsett());
516-
});
517-
518-
// we'll add null, in case it's not there yet
519-
insert(
520-
dest,
521-
exprt(ID_null_object, to_pointer_type(expr_type).subtype()),
522-
offsett());
523-
}
534+
insert(dest, exprt(ID_unknown, original_type));
524535
}
525536
else if(expr.id()==ID_if)
526537
{

src/pointer-analysis/value_set.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,13 @@ class value_sett
251251
/// are object_descriptor_exprt or have id ID_invalid or ID_unknown.
252252
std::vector<exprt> get_value_set(exprt expr, const namespacet &ns) const;
253253

254+
/// Collects all objects known to the value set.
255+
/// \param expr: query expression
256+
/// \param ns: global namespace
257+
/// \return list of objects that any pointer could point to. These expressions
258+
/// are object_descriptor_exprt or have id ID_invalid or ID_unknown.
259+
std::vector<exprt> get_any_object(exprt expr, const namespacet &ns) const;
260+
254261
void clear()
255262
{
256263
values.clear();

0 commit comments

Comments
 (0)