Skip to content

Commit 8f30441

Browse files
authored
Merge pull request #6100 from tautschnig/boolbv_index-oob
boolbv_index: preserve endianness when generating byte extract
2 parents d76e3ff + a419041 commit 8f30441

File tree

5 files changed

+84
-4
lines changed

5 files changed

+84
-4
lines changed

regression/cbmc/member_bounds3/main.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <assert.h>
2+
3+
#pragma pack(push, 1)
4+
struct S
5+
{
6+
int a[2];
7+
int x;
8+
};
9+
#pragma pack(pop)
10+
11+
#ifdef _MSC_VER
12+
# define _Static_assert(x, m) static_assert(x, m)
13+
#endif
14+
15+
int main()
16+
{
17+
int A[3];
18+
_Static_assert(sizeof(A) == sizeof(struct S), "");
19+
struct S *s = A;
20+
A[2] = 42;
21+
assert(s->a[2] == 42);
22+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE broken-smt-backend
2+
main.c
3+
--no-simplify
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

regression/cbmc/member_bounds4/main.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <assert.h>
2+
#include <inttypes.h>
3+
4+
union U {
5+
uint8_t a[4];
6+
};
7+
8+
int main()
9+
{
10+
uint32_t x[2] = {0xDEADBEEF, 0xDEADBEEF};
11+
union U *u = x;
12+
uint8_t c4 = u->a[4];
13+
14+
unsigned word = 1;
15+
if(*(char *)&word == 1)
16+
assert(c4 == 0xEF); // little endian
17+
else
18+
assert(c4 == 0xDE); // big endian
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE broken-smt-backend
2+
main.c
3+
--no-simplify
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

src/solvers/flattening/boolbv_index.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,10 @@ bvt boolbvt::convert_index(
321321
std::size_t offset_int = numeric_cast_v<std::size_t>(offset);
322322
return bvt(tmp.begin() + offset_int, tmp.begin() + offset_int + width);
323323
}
324-
else if(
325-
array.id() == ID_member || array.id() == ID_index ||
326-
array.id() == ID_byte_extract_big_endian ||
327-
array.id() == ID_byte_extract_little_endian)
324+
else if(array.id() == ID_member || array.id() == ID_index)
328325
{
326+
// out of bounds for the component, but not necessarily outside the bounds
327+
// of the underlying object
329328
object_descriptor_exprt o;
330329
o.build(array, ns);
331330
CHECK_RETURN(o.offset().id() != ID_unknown);
@@ -344,6 +343,30 @@ bvt boolbvt::convert_index(
344343

345344
return convert_bv(be);
346345
}
346+
else if(
347+
array.id() == ID_byte_extract_big_endian ||
348+
array.id() == ID_byte_extract_little_endian)
349+
{
350+
const byte_extract_exprt &byte_extract_expr = to_byte_extract_expr(array);
351+
352+
const auto subtype_bytes_opt =
353+
pointer_offset_size(array_type.subtype(), ns);
354+
CHECK_RETURN(subtype_bytes_opt.has_value());
355+
356+
// add offset to index
357+
exprt new_offset = simplify_expr(
358+
plus_exprt{
359+
byte_extract_expr.offset(),
360+
from_integer(
361+
index * (*subtype_bytes_opt), byte_extract_expr.offset().type())},
362+
ns);
363+
364+
byte_extract_exprt be = byte_extract_expr;
365+
be.offset() = new_offset;
366+
be.type() = array_type.subtype();
367+
368+
return convert_bv(be);
369+
}
347370
else
348371
{
349372
// out of bounds

0 commit comments

Comments
 (0)