Skip to content

Commit 4176f59

Browse files
committed
Create heap allocation abstract object on pointer typecast
We can't ensure the modified pointer object will be properly assigned back to its symbol if we wait until first write. If we defer then modified pointer may, or may not, be assigned depending on how the write is expressed *p = 1; // good :) p[0] = 1; // bad :(
1 parent 0fbd46a commit 4176f59

File tree

10 files changed

+87
-11
lines changed

10 files changed

+87
-11
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
int main() {
3+
int* i_was_malloced = malloc(sizeof(int) * 10);
4+
int* alias = i_was_malloced;
5+
6+
*i_was_malloced = 99;
7+
assert(*alias == 99);
8+
9+
i_was_malloced[0] = 100;
10+
assert(*alias == 100);
11+
12+
*alias += 1;
13+
assert(i_was_malloced[0] == 101);
14+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--variable-sensitivity --vsd-pointers constants --vsd-arrays every-element --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
\[main.assertion.1\] .*alias == 99: SUCCESS
7+
\[main.assertion.2\] .*alias == 100: SUCCESS
8+
\[main.assertion.3\] .*i_was_malloced.* == 101: SUCCESS
9+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--variable-sensitivity --vsd-pointers top-bottom --vsd-arrays every-element --verify
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
\[main.assertion.1\] .*alias == 99: UNKNOWN
7+
\[main.assertion.2\] .*alias == 100: UNKNOWN
8+
\[main.assertion.3\] .*i_was_malloced.* == 101: UNKNOWN
9+
--

regression/goto-analyzer/heap-allocation/test-constant-pointers.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ main.c
33
--variable-sensitivity --vsd-pointers constants --show
44
^EXIT=0$
55
^SIGNAL=0$
6-
main::1::i_was_malloced \(\) -> ptr ->\(heap allocation\)
6+
main::1::i_was_malloced \(\) -> ptr ->\(heap-object\[0\]\)
77
--

src/analyses/variable-sensitivity/abstract_pointer_object.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ abstract_object_pointert abstract_pointer_objectt::expression_transform(
5555
auto pointer = std::dynamic_pointer_cast<const abstract_pointer_objectt>(
5656
obj->unwrap_context());
5757
if(pointer)
58-
return pointer->typecast(tce.type());
58+
return pointer->typecast(tce.type(), environment, ns);
5959
}
6060
}
6161

@@ -101,7 +101,11 @@ abstract_object_pointert abstract_pointer_objectt::write_dereference(
101101
}
102102

103103
abstract_object_pointert
104-
abstract_pointer_objectt::typecast(const typet &new_type) const
104+
abstract_pointer_objectt::typecast(
105+
const typet &new_type,
106+
const abstract_environmentt &environment,
107+
const namespacet &ns
108+
) const
105109
{
106110
INVARIANT(is_void_pointer(type()), "Only allow pointer casting from void*");
107111
return std::make_shared<abstract_pointer_objectt>(

src/analyses/variable-sensitivity/abstract_pointer_object.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ class abstract_pointer_objectt : public abstract_objectt,
9696
const abstract_object_pointert &value,
9797
bool merging_write) const;
9898

99-
virtual abstract_object_pointert typecast(const typet &new_type) const;
99+
virtual abstract_object_pointert typecast(
100+
const typet &new_type,
101+
const abstract_environmentt &environment,
102+
const namespacet &ns
103+
) const;
100104
};
101105

102106
#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_POINTER_OBJECT_H

src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "constant_pointer_abstract_object.h"
1010

1111
#include <analyses/variable-sensitivity/abstract_environment.h>
12+
#include <util/arith_tools.h>
13+
#include <util/c_types.h>
1214
#include <util/pointer_expr.h>
1315
#include <util/std_expr.h>
1416

@@ -207,18 +209,40 @@ abstract_object_pointert constant_pointer_abstract_objectt::write_dereference(
207209
abstract_object_pointert modified_value =
208210
environment.write(pointed_value, new_value, stack, ns, merging_write);
209211
environment.assign(value, modified_value, ns);
210-
211212
// but the pointer itself does not change!
212213
}
213-
return std::dynamic_pointer_cast<const constant_pointer_abstract_objectt>(
214-
shared_from_this());
214+
215+
return shared_from_this();
215216
}
216217
}
217218

218219
abstract_object_pointert
219-
constant_pointer_abstract_objectt::typecast(const typet &new_type) const
220+
constant_pointer_abstract_objectt::typecast(
221+
const typet &new_type,
222+
const abstract_environmentt &environment,
223+
const namespacet &ns
224+
) const
220225
{
221226
INVARIANT(is_void_pointer(type()), "Only allow pointer casting from void*");
227+
228+
// Get an expression that we can assign to
229+
exprt value = to_address_of_expr(value_stack.to_expression()).object();
230+
if (value.id() == ID_dynamic_object) {
231+
auto& env = const_cast<abstract_environmentt&>(environment);
232+
233+
auto heap_array_type = array_typet(new_type.subtype(), nil_exprt());
234+
auto array_object = environment.abstract_object_factory(heap_array_type, ns, true, false);
235+
auto heap_symbol = symbol_exprt("heap-object", heap_array_type);
236+
env.assign(heap_symbol, array_object, ns);
237+
auto heap_address = address_of_exprt(
238+
index_exprt(heap_symbol, from_integer(0, size_type())));
239+
auto new_pointer = std::make_shared<constant_pointer_abstract_objectt>(
240+
heap_address,
241+
env,
242+
ns);
243+
return new_pointer;
244+
}
245+
222246
return std::make_shared<constant_pointer_abstract_objectt>(new_type, *this);
223247
}
224248

src/analyses/variable-sensitivity/constant_pointer_abstract_object.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ class constant_pointer_abstract_objectt : public abstract_pointer_objectt
106106
const abstract_object_pointert &value,
107107
bool merging_write) const override;
108108

109-
abstract_object_pointert typecast(const typet &new_type) const override;
109+
abstract_object_pointert typecast(
110+
const typet &new_type,
111+
const abstract_environmentt &environment,
112+
const namespacet &ns
113+
) const override;
110114

111115
void get_statistics(
112116
abstract_object_statisticst &statistics,

src/analyses/variable-sensitivity/value_set_pointer_abstract_object.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,11 @@ abstract_object_pointert value_set_pointer_abstract_objectt::write_dereference(
143143
}
144144

145145
abstract_object_pointert
146-
value_set_pointer_abstract_objectt::typecast(const typet &new_type) const
146+
value_set_pointer_abstract_objectt::typecast(
147+
const typet &new_type,
148+
const abstract_environmentt &environment,
149+
const namespacet &ns
150+
) const
147151
{
148152
INVARIANT(is_void_pointer(type()), "Only allow pointer casting from void*");
149153
return std::make_shared<value_set_pointer_abstract_objectt>(new_type, *this);

src/analyses/variable-sensitivity/value_set_pointer_abstract_object.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ class value_set_pointer_abstract_objectt : public abstract_pointer_objectt,
6868
const abstract_object_pointert &new_value,
6969
bool merging_write) const override;
7070

71-
abstract_object_pointert typecast(const typet &new_type) const override;
71+
abstract_object_pointert typecast(
72+
const typet &new_type,
73+
const abstract_environmentt &environment,
74+
const namespacet &ns
75+
) const override;
7276

7377
void output(std::ostream &out, const ai_baset &ai, const namespacet &ns)
7478
const override;

0 commit comments

Comments
 (0)