Skip to content

Commit 6b09359

Browse files
committed
Offset computation can handle zero-sized objects
Although any access would result in an out-of-bounds access (within the program being verified), it's perfectly fine to perform offset computation.
1 parent 95097a8 commit 6b09359

File tree

6 files changed

+49
-9
lines changed

6 files changed

+49
-9
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
struct B
2+
{
3+
} b[1];
4+
struct c
5+
{
6+
void *d;
7+
} e = {b};
8+
struct
9+
{
10+
struct c f;
11+
} * g;
12+
int main()
13+
{
14+
g->f;
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE broken-smt-backend
2+
main.c
3+
--pointer-check
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
^warning: ignoring
9+
Invariant check failed
10+
--
11+
Taking the address of an empty struct resulted in an invariant failure in
12+
address-of flattening. This test was generated using C-Reduce plus some further
13+
manual simplification.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <string.h>
2+
3+
struct a
4+
{
5+
} b()
6+
{
7+
struct a *c;
8+
memcpy(c + 2, c, 1);
9+
}
10+
int main()
11+
{
12+
b();
13+
}

src/solvers/flattening/boolbv_get.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ exprt boolbvt::bv_get_rec(
126126
dest.operands().swap(op);
127127
return dest;
128128
}
129+
else
130+
{
131+
return array_exprt{{}, to_array_type(type)};
132+
}
129133
}
130134
else if(type.id()==ID_struct_tag)
131135
{

src/solvers/flattening/bv_pointers.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ bool bv_pointerst::convert_address_of_rec(
138138

139139
// get size
140140
auto size = pointer_offset_size(array_type.subtype(), ns);
141-
CHECK_RETURN(size.has_value() && *size > 0);
141+
CHECK_RETURN(size.has_value() && *size >= 0);
142142

143143
offset_arithmetic(bv, *size, index);
144144
CHECK_RETURN(bv.size()==bits);
@@ -342,7 +342,7 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr)
342342
else
343343
{
344344
auto size_opt = pointer_offset_size(pointer_sub_type, ns);
345-
CHECK_RETURN(size_opt.has_value() && *size_opt > 0);
345+
CHECK_RETURN(size_opt.has_value() && *size_opt >= 0);
346346
size = *size_opt;
347347
}
348348
}

src/util/pointer_offset_size.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -670,13 +670,8 @@ optionalt<exprt> get_subexpression_at_offset(
670670

671671
// no arrays of non-byte-aligned, zero-, or unknown-sized objects
672672
if(
673-
!elem_size_bits.has_value() || *elem_size_bits == 0 ||
674-
*elem_size_bits % 8 != 0)
675-
{
676-
return {};
677-
}
678-
679-
if(*target_size_bits <= *elem_size_bits)
673+
elem_size_bits.has_value() && *elem_size_bits > 0 &&
674+
*elem_size_bits % 8 == 0 && *target_size_bits <= *elem_size_bits)
680675
{
681676
const mp_integer elem_size_bytes = *elem_size_bits / 8;
682677
const auto offset_inside_elem = offset_bytes % elem_size_bytes;

0 commit comments

Comments
 (0)