Skip to content

Commit

Permalink
Value set dereferencing: do not treat struct prefixes as equal
Browse files Browse the repository at this point in the history
Two distinct struct types cannot be cast between, even when one is a
prefix of the other. Value set dereferencing taking this approach just
resulted in propositional encoding producing a warning about invalid
type casts.
  • Loading branch information
tautschnig committed May 25, 2022
1 parent c688efd commit 5496378
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 56 deletions.

This file was deleted.

2 changes: 1 addition & 1 deletion regression/cbmc/Pointer21/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE broken-smt-backend
CORE
main.c
--pointer-check
^EXIT=0$
Expand Down
24 changes: 24 additions & 0 deletions regression/cbmc/struct2/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
struct T
{
// intentionally empty to trigger is_prefix_of code (empty structs, however,
// are a GCC-only feature)
};

struct S
{
struct T t;
int other;
};

void foo(struct S s2)
{
struct T *p = &s2.t;
struct T t2 = *p;
__CPROVER_assert(0, "");
}

int main()
{
struct S s;
foo(s);
}
11 changes: 11 additions & 0 deletions regression/cbmc/struct2/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CORE gcc-only broken-smt-backend
main.c

^VERIFICATION FAILED$
^EXIT=10$
^SIGNAL=0$
--
^warning: ignoring
--
This test must not generate a warning about typecasts (between different struct
types) being ignored.
28 changes: 28 additions & 0 deletions regression/cbmc/struct5/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <assert.h>

struct a
{
int x;
};
struct b
{
struct a p;
int y;
};

int f00(struct a *ptr)
{
return ptr->x;
}

int main()
{
struct b z = {{1}, 2};

assert(&z == &(z.p));
assert(&z == &(z.p.x));

assert(f00(&z) == z.p.x);

return 0;
}
8 changes: 8 additions & 0 deletions regression/cbmc/struct5/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CORE
main.c

^VERIFICATION SUCCESSFUL$
^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring
13 changes: 0 additions & 13 deletions src/pointer-analysis/value_set_dereference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,19 +358,6 @@ bool value_set_dereferencet::dereference_type_compare(
if(object_type == dereference_type)
return true; // ok, they just match

// check for struct prefixes

const typet ot_base=ns.follow(object_type),
dt_base=ns.follow(dereference_type);

if(ot_base.id()==ID_struct &&
dt_base.id()==ID_struct)
{
if(to_struct_type(dt_base).is_prefix_of(
to_struct_type(ot_base)))
return true; // ok, dt is a prefix of ot
}

// we are generous about code pointers
if(dereference_type.id()==ID_code &&
object_type.id()==ID_code)
Expand Down
29 changes: 0 additions & 29 deletions src/util/std_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,35 +104,6 @@ optionalt<struct_typet::baset> struct_typet::get_base(const irep_idt &id) const
return {};
}

/// Returns true if the struct is a prefix of \a other, i.e., if this struct
/// has n components then the component types and names of this struct must
/// match the first n components of \a other struct.
/// \param other: Struct type to compare with.
bool struct_typet::is_prefix_of(const struct_typet &other) const
{
const componentst &ot_components=other.components();
const componentst &tt_components=components();

if(ot_components.size()<
tt_components.size())
return false;

componentst::const_iterator
ot_it=ot_components.begin();

for(const auto &tt_c : tt_components)
{
if(ot_it->type() != tt_c.type() || ot_it->get_name() != tt_c.get_name())
{
return false; // they just don't match
}

ot_it++;
}

return true; // ok, *this is a prefix of ot
}

/// Returns true if the type is a reference.
bool is_reference(const typet &type)
{
Expand Down
2 changes: 0 additions & 2 deletions src/util/std_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,6 @@ class struct_typet:public struct_union_typet
{
}

bool is_prefix_of(const struct_typet &other) const;

/// A struct may be a class, where members may have access restrictions.
bool is_class() const
{
Expand Down

0 comments on commit 5496378

Please sign in to comment.