Skip to content

Commit b2950c4

Browse files
author
klaas
committed
Fixes bugs making goto_rw too conservative
When handling the case of pointers, goto_rw would mark both the object pointed to and the pointer itself as written. For example, if x = &i, the line `*x = 1' would yield a write set containing both x and i, instead of just i. This resolves that issue by ensuring that value_set_dereference always gives at least one object that the dereference can refer to. This also resolves a bug wherein &a is marked as reading from a by removing the ID_symbol special case from get_objects_address_of.A
1 parent 9d8cef4 commit b2950c4

File tree

3 files changed

+26
-19
lines changed

3 files changed

+26
-19
lines changed

src/analyses/goto_rw.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@ void rw_range_sett::get_objects_dereference(
128128
{
129129
const exprt &pointer=deref.pointer();
130130
get_objects_rec(get_modet::READ, pointer);
131-
if(mode!=get_modet::READ)
132-
get_objects_rec(mode, pointer);
133131
}
134132

135133
void rw_range_sett::get_objects_byte_extract(
@@ -414,16 +412,19 @@ void rw_range_sett::get_objects_typecast(
414412

415413
void rw_range_sett::get_objects_address_of(const exprt &object)
416414
{
417-
if(object.id() == ID_string_constant ||
415+
if(object.id() == ID_symbol ||
416+
object.id() == ID_string_constant ||
418417
object.id() == ID_label ||
419418
object.id() == ID_array ||
420419
object.id() == ID_null_object)
421420
// constant, nothing to do
421+
{
422422
return;
423-
else if(object.id()==ID_symbol)
424-
get_objects_rec(get_modet::READ, object);
423+
}
425424
else if(object.id()==ID_dereference)
425+
{
426426
get_objects_rec(get_modet::READ, object);
427+
}
427428
else if(object.id()==ID_index)
428429
{
429430
const index_exprt &index=to_index_expr(object);
@@ -524,6 +525,11 @@ void rw_range_sett::get_objects_rec(
524525
get_objects_array(mode, to_array_expr(expr), range_start, size);
525526
else if(expr.id()==ID_struct)
526527
get_objects_struct(mode, to_struct_expr(expr), range_start, size);
528+
else if(expr.id()==ID_dynamic_object)
529+
{
530+
const auto obj_instance = to_dynamic_object_expr(expr).get_instance();
531+
add(mode, "goto_rw::dynamic_object-" + std::to_string(obj_instance), 0, -1);
532+
}
527533
else if(expr.id()==ID_symbol)
528534
{
529535
const symbol_exprt &symbol=to_symbol_expr(expr);
@@ -564,11 +570,6 @@ void rw_range_sett::get_objects_rec(
564570
{
565571
// dereferencing may yield some weird ones, ignore these
566572
}
567-
else if(mode==get_modet::LHS_W)
568-
{
569-
forall_operands(it, expr)
570-
get_objects_rec(mode, *it);
571-
}
572573
else
573574
throw "rw_range_sett: assignment to `"+expr.id_string()+"' not handled";
574575
}
@@ -605,6 +606,8 @@ void rw_range_set_value_sett::get_objects_dereference(
605606
exprt object=deref;
606607
dereference(target, object, ns, value_sets);
607608

609+
PRECONDITION(object.is_not_nil());
610+
608611
range_spect new_size=
609612
to_range_spect(pointer_offset_bits(object.type(), ns));
610613

src/analyses/reaching_definitions.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,19 +307,19 @@ void rd_range_domaint::transform_assign(
307307
{
308308
const irep_idt &identifier=it->first;
309309
// ignore symex::invalid_object
310-
const symbolt *symbol_ptr;
311-
if(ns.lookup(identifier, symbol_ptr))
310+
const symbolt *symbol_ptr = nullptr;
311+
bool not_found = ns.lookup(identifier, symbol_ptr);
312+
if(not_found && has_prefix(id2string(identifier), "symex::invalid_object"))
313+
{
312314
continue;
313-
INVARIANT_STRUCTURED(
314-
symbol_ptr!=nullptr,
315-
nullptr_exceptiont,
316-
"Symbol is in symbol table");
315+
}
317316

318317
const range_domaint &ranges=rw_set.get_ranges(it);
319318

320319
if(is_must_alias &&
321320
(!rd.get_is_threaded()(from) ||
322-
(!symbol_ptr->is_shared() &&
321+
(symbol_ptr != nullptr &&
322+
symbol_ptr->is_shared() &&
323323
!rd.get_is_dirty()(identifier))))
324324
for(const auto &range : ranges)
325325
kill(identifier, range.first, range.second);

src/pointer-analysis/value_set_dereference.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,12 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
358358
// this is also our guard
359359
result.pointer_guard = dynamic_object(pointer_expr);
360360

361-
// can't remove here, turn into *p
362-
result.value=dereference_exprt(pointer_expr, dereference_type);
361+
// TODO should this be object or root_object?
362+
// TODO It's unclear whether this is a good approach to take --- it
363+
// successfully ensures that every (non-null) dereference points to
364+
// something, making the write set computation work correctly, but dynamic
365+
// objects do not seem to be intended to be used in this way.
366+
result.value = object;
363367

364368
if(options.get_bool_option("pointer-check"))
365369
{

0 commit comments

Comments
 (0)