Skip to content

Commit 84df81e

Browse files
committed
Remove well-alignedness assumption from pointer dereferencing
With void* pointers, pointer dereferencing would permit any type for the dereferenced object. For arrays, alignment at the root level was implicitly assumed, not taking into account that there may be a well-aligned pointer to a nested element. For the regression test we got `arr[11 / 7]` when dereferencing `(void *)ptr`, where `ptr` was `(char *)&arr[0] + 11` (and the size of `arr`'s elements is 7 bytes). Fixes: #7036
1 parent 52b1b40 commit 84df81e

File tree

3 files changed

+66
-8
lines changed

3 files changed

+66
-8
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include <assert.h>
2+
3+
typedef struct my_struct
4+
{
5+
char a;
6+
char b;
7+
char c[5];
8+
} my_struct;
9+
10+
int main()
11+
{
12+
my_struct arr[3] = {0};
13+
char *ptr = &(arr[1].c[2]);
14+
int offset;
15+
__CPROVER_assume(offset < 1 && offset > -1);
16+
void *ptr_plus = ptr + offset;
17+
char nondet[3];
18+
19+
__CPROVER_array_replace(ptr_plus, &nondet[0]);
20+
21+
// expected valid and proved
22+
assert(arr[0].a == 0);
23+
assert(arr[0].b == 0);
24+
assert(arr[0].c[0] == 0);
25+
assert(arr[0].c[1] == 0);
26+
assert(arr[0].c[2] == 0);
27+
assert(arr[0].c[3] == 0);
28+
assert(arr[0].c[4] == 0);
29+
30+
assert(arr[1].a == 0); // expected valid, falsified
31+
assert(arr[1].b == 0); // expected valid, falsified
32+
assert(arr[1].c[0] == 0); // expected valid, falsified
33+
assert(arr[1].c[1] == 0); // expected valid, proved
34+
assert(arr[1].c[2] == 0); // expected falsifiable, proved
35+
assert(arr[1].c[3] == 0); // expected falsifiable, proved
36+
assert(arr[1].c[4] == 0); // expected falsifiable, proved
37+
38+
// expected valid and proved
39+
assert(arr[2].a == 0);
40+
assert(arr[2].b == 0);
41+
assert(arr[2].c[0] == 0);
42+
assert(arr[2].c[1] == 0);
43+
assert(arr[2].c[2] == 0);
44+
assert(arr[2].c[3] == 0);
45+
assert(arr[2].c[4] == 0);
46+
47+
return 0;
48+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE broken-smt-backend
2+
main.c
3+
4+
^\[main.assertion.12\] line 34 assertion arr\[1\].c\[2\] == 0: FAILURE$
5+
^\[main.assertion.13\] line 35 assertion arr\[1\].c\[3\] == 0: FAILURE$
6+
^\[main.assertion.14\] line 36 assertion arr\[1\].c\[4\] == 0: FAILURE$
7+
^\*\* 3 of 21 failed
8+
^VERIFICATION FAILED$
9+
^EXIT=10$
10+
^SIGNAL=0$
11+
--
12+
^warning: ignoring
13+
--
14+
Verify the properties of various cprover array primitves

src/pointer-analysis/value_set_dereference.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -572,12 +572,12 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
572572
else if(
573573
root_object_type.id() == ID_array &&
574574
dereference_type_compare(
575-
to_array_type(root_object_type).element_type(), dereference_type, ns))
575+
to_array_type(root_object_type).element_type(), dereference_type, ns) &&
576+
pointer_offset_bits(to_array_type(root_object_type).element_type(), ns) ==
577+
pointer_offset_bits(dereference_type, ns))
576578
{
577579
// We have an array with a subtype that matches
578580
// the dereferencing type.
579-
// We will require well-alignedness!
580-
581581
exprt offset;
582582

583583
// this should work as the object is essentially the root object
@@ -609,13 +609,9 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
609609
adjusted_offset=binary_exprt(
610610
offset, ID_div, element_size_expr, offset.type());
611611

612-
// TODO: need to assert well-alignedness
613612
}
614613

615-
const index_exprt &index_expr = index_exprt(
616-
root_object,
617-
adjusted_offset,
618-
to_array_type(root_object_type).element_type());
614+
index_exprt index_expr{root_object, adjusted_offset};
619615
result.value =
620616
typecast_exprt::conditional_cast(index_expr, dereference_type);
621617
result.pointer = typecast_exprt::conditional_cast(

0 commit comments

Comments
 (0)