Skip to content

Commit 91fadf4

Browse files
authored
Merge pull request #7420 from tautschnig/bugfixes/7288-byte-byte-extract
Byte operator lowering: no type casts to/from compound types
2 parents e29f861 + 7d10a08 commit 91fadf4

File tree

3 files changed

+71
-16
lines changed

3 files changed

+71
-16
lines changed

regression/cbmc/byte_update17/main.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <inttypes.h>
2+
#include <string.h>
3+
4+
// a union that is exactly one byte wide
5+
union U
6+
{
7+
unsigned char c;
8+
};
9+
10+
int main()
11+
{
12+
unsigned char size;
13+
__CPROVER_assume(size > 1);
14+
__CPROVER_assume(size < 5);
15+
__CPROVER_assume(size % 4 == 0);
16+
union U u[size];
17+
u[0].c = 42;
18+
u[1].c = 42;
19+
u[2].c = 42;
20+
u[3].c = 42;
21+
int32_t dest;
22+
memcpy(&dest, u, size);
23+
__CPROVER_assert(dest == 42 | 42 << 8 | 42 << 16 | 42 << 24, "");
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE broken-cprover-smt-backend
2+
main.c
3+
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
10+
This test currently does not pass with CPROVER SMT2 backend
11+
because the solver does not fully support quantified expressions.

src/util/lower_byte_operators.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -877,8 +877,12 @@ static exprt unpack_rec(
877877
auto element_bits = pointer_offset_bits(subtype, ns);
878878
CHECK_RETURN(element_bits.has_value());
879879

880-
if(!unpack_byte_array && *element_bits == bits_per_byte)
880+
if(
881+
!unpack_byte_array && *element_bits == bits_per_byte &&
882+
can_cast_type<bitvector_typet>(subtype))
883+
{
881884
return src;
885+
}
882886

883887
const auto constant_size_opt = numeric_cast<mp_integer>(array_type.size());
884888
return unpack_array_vector(
@@ -899,8 +903,12 @@ static exprt unpack_rec(
899903
auto element_bits = pointer_offset_bits(subtype, ns);
900904
CHECK_RETURN(element_bits.has_value());
901905

902-
if(!unpack_byte_array && *element_bits == bits_per_byte)
906+
if(
907+
!unpack_byte_array && *element_bits == bits_per_byte &&
908+
can_cast_type<bitvector_typet>(subtype))
909+
{
903910
return src;
911+
}
904912

905913
return unpack_array_vector(
906914
src,
@@ -1455,17 +1463,27 @@ static exprt lower_byte_update_byte_array_vector_non_const(
14551463
src.offset(), non_const_update_bound.type()),
14561464
non_const_update_bound}};
14571465

1466+
PRECONDITION(
1467+
src.id() == ID_byte_update_little_endian ||
1468+
src.id() == ID_byte_update_big_endian);
1469+
const bool little_endian = src.id() == ID_byte_update_little_endian;
1470+
endianness_mapt map(
1471+
to_array_type(value_as_byte_array.type()).element_type(),
1472+
little_endian,
1473+
ns);
14581474
if_exprt array_comprehension_body{
14591475
or_exprt{std::move(lower_bound), std::move(upper_bound)},
14601476
index_exprt{src.op(), array_comprehension_index},
1461-
typecast_exprt::conditional_cast(
1477+
bv_to_expr(
14621478
index_exprt{
14631479
value_as_byte_array,
14641480
minus_exprt{
14651481
array_comprehension_index,
14661482
typecast_exprt::conditional_cast(
14671483
src.offset(), array_comprehension_index.type())}},
1468-
subtype)};
1484+
subtype,
1485+
map,
1486+
ns)};
14691487

14701488
return simplify_expr(
14711489
array_comprehension_exprt{
@@ -1491,6 +1509,11 @@ static exprt lower_byte_update_byte_array_vector(
14911509
const optionalt<exprt> &non_const_update_bound,
14921510
const namespacet &ns)
14931511
{
1512+
PRECONDITION(
1513+
src.id() == ID_byte_update_little_endian ||
1514+
src.id() == ID_byte_update_big_endian);
1515+
const bool little_endian = src.id() == ID_byte_update_little_endian;
1516+
14941517
// apply 'array-update-with' num_elements times
14951518
exprt result = src.op();
14961519

@@ -1511,21 +1534,18 @@ static exprt lower_byte_update_byte_array_vector(
15111534
continue;
15121535
}
15131536

1514-
exprt update_value;
1537+
endianness_mapt map(element.type(), little_endian, ns);
1538+
exprt update_value = bv_to_expr(element, subtype, map, ns);
15151539
if(non_const_update_bound.has_value())
15161540
{
1517-
update_value = typecast_exprt::conditional_cast(
1518-
if_exprt{
1519-
binary_predicate_exprt{
1520-
from_integer(i, non_const_update_bound->type()),
1521-
ID_lt,
1522-
*non_const_update_bound},
1523-
element,
1524-
index_exprt{src.op(), where}},
1525-
subtype);
1541+
update_value = if_exprt{
1542+
binary_predicate_exprt{
1543+
from_integer(i, non_const_update_bound->type()),
1544+
ID_lt,
1545+
*non_const_update_bound},
1546+
update_value,
1547+
index_exprt{src.op(), where}};
15261548
}
1527-
else
1528-
update_value = typecast_exprt::conditional_cast(element, subtype);
15291549

15301550
if(result.id() != ID_with)
15311551
result = with_exprt{result, std::move(where), std::move(update_value)};

0 commit comments

Comments
 (0)