Skip to content

Commit d4d2aaf

Browse files
committed
Byte-operator lowering: ensure index type consistency
We must not assume that byte-operator offsets and arrays indices use the same type (without at least checking that they do). Always use types available from the context, and type cast as needed.
1 parent 1f088d7 commit d4d2aaf

File tree

1 file changed

+60
-23
lines changed

1 file changed

+60
-23
lines changed

src/util/lower_byte_operators.cpp

+60-23
Original file line numberDiff line numberDiff line change
@@ -434,17 +434,20 @@ static exprt::operandst instantiate_byte_array(
434434
src.operands().begin() + narrow_cast<std::ptrdiff_t>(upper_bound)};
435435
}
436436

437-
PRECONDITION(src.type().id() == ID_array || src.type().id() == ID_vector);
437+
const typet &element_type = src.type().id() == ID_array
438+
? to_array_type(src.type()).element_type()
439+
: to_vector_type(src.type()).element_type();
440+
const typet index_type = src.type().id() == ID_array
441+
? to_array_type(src.type()).index_type()
442+
: to_vector_type(src.type()).index_type();
438443
PRECONDITION(
439-
can_cast_type<bitvector_typet>(
440-
to_type_with_subtype(src.type()).subtype()) &&
441-
to_bitvector_type(to_type_with_subtype(src.type()).subtype()).get_width() ==
442-
bits_per_byte);
444+
can_cast_type<bitvector_typet>(element_type) &&
445+
to_bitvector_type(element_type).get_width() == bits_per_byte);
443446
exprt::operandst bytes;
444447
bytes.reserve(upper_bound - lower_bound);
445448
for(std::size_t i = lower_bound; i < upper_bound; ++i)
446449
{
447-
const index_exprt idx{src, from_integer(i, c_index_type())};
450+
const index_exprt idx{src, from_integer(i, index_type)};
448451
bytes.push_back(simplify_expr(idx, ns));
449452
}
450453
return bytes;
@@ -465,19 +468,22 @@ static exprt unpack_array_vector_no_known_bounds(
465468
const std::size_t bits_per_byte,
466469
const namespacet &ns)
467470
{
471+
const typet index_type = src.type().id() == ID_array
472+
? to_array_type(src.type()).index_type()
473+
: to_vector_type(src.type()).index_type();
474+
468475
// TODO we either need a symbol table here or make array comprehensions
469476
// introduce a scope
470477
static std::size_t array_comprehension_index_counter = 0;
471478
++array_comprehension_index_counter;
472479
symbol_exprt array_comprehension_index{
473480
"$array_comprehension_index_a_v" +
474481
std::to_string(array_comprehension_index_counter),
475-
c_index_type()};
482+
index_type};
476483

477484
index_exprt element{
478485
src,
479-
div_exprt{
480-
array_comprehension_index, from_integer(el_bytes, c_index_type())}};
486+
div_exprt{array_comprehension_index, from_integer(el_bytes, index_type)}};
481487

482488
exprt sub =
483489
unpack_rec(element, little_endian, {}, {}, bits_per_byte, ns, false);
@@ -577,6 +583,9 @@ static exprt unpack_array_vector(
577583
num_elements = *max_bytes;
578584

579585
const exprt src_simp = simplify_expr(src, ns);
586+
const typet index_type = src_simp.type().id() == ID_array
587+
? to_array_type(src_simp.type()).index_type()
588+
: to_vector_type(src_simp.type()).index_type();
580589

581590
for(mp_integer i = first_element; i < *num_elements; ++i)
582591
{
@@ -591,7 +600,7 @@ static exprt unpack_array_vector(
591600
}
592601
else
593602
{
594-
element = index_exprt(src_simp, from_integer(i, c_index_type()));
603+
element = index_exprt(src_simp, from_integer(i, index_type));
595604
}
596605

597606
// recursively unpack each element so that we eventually just have an array
@@ -1022,14 +1031,17 @@ static exprt unpack_rec(
10221031
src, bv_typet{numeric_cast_v<std::size_t>(total_bits)});
10231032
auto const byte_type = bv_typet{bits_per_byte};
10241033
exprt::operandst byte_operands;
1034+
array_typet array_type{
1035+
bv_typet{bits_per_byte}, from_integer(0, size_type())};
1036+
10251037
for(; bit_offset < last_bit; bit_offset += bits_per_byte)
10261038
{
10271039
PRECONDITION(
10281040
pointer_offset_bits(src_as_bitvector.type(), ns).has_value());
10291041
extractbits_exprt extractbits(
10301042
src_as_bitvector,
1031-
from_integer(bit_offset + bits_per_byte - 1, c_index_type()),
1032-
from_integer(bit_offset, c_index_type()),
1043+
from_integer(bit_offset + bits_per_byte - 1, array_type.index_type()),
1044+
from_integer(bit_offset, array_type.index_type()),
10331045
byte_type);
10341046

10351047
// endianness_mapt should be the point of reference for mapping out
@@ -1042,9 +1054,8 @@ static exprt unpack_rec(
10421054
}
10431055

10441056
const std::size_t size = byte_operands.size();
1045-
return array_exprt(
1046-
std::move(byte_operands),
1047-
array_typet{bv_typet{bits_per_byte}, from_integer(size, size_type())});
1057+
array_type.size() = from_integer(size, size_type());
1058+
return array_exprt{std::move(byte_operands), std::move(array_type)};
10481059
}
10491060

10501061
return array_exprt(
@@ -1112,7 +1123,7 @@ static exprt lower_byte_extract_array_vector(
11121123
symbol_exprt array_comprehension_index{
11131124
"$array_comprehension_index_a" +
11141125
std::to_string(array_comprehension_index_counter),
1115-
c_index_type()};
1126+
array_type.index_type()};
11161127

11171128
plus_exprt new_offset{
11181129
unpacked.offset(),
@@ -1347,10 +1358,17 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
13471358
const exprt &offset = unpacked.offset();
13481359

13491360
optionalt<typet> subtype;
1361+
optionalt<typet> index_type;
13501362
if(root.type().id() == ID_vector)
1363+
{
13511364
subtype = to_vector_type(root.type()).element_type();
1365+
index_type = to_vector_type(root.type()).index_type();
1366+
}
13521367
else
1368+
{
13531369
subtype = to_array_type(root.type()).element_type();
1370+
index_type = to_array_type(root.type()).index_type();
1371+
}
13541372

13551373
auto subtype_bits = pointer_offset_bits(*subtype, ns);
13561374

@@ -1383,7 +1401,9 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
13831401
// the most significant byte comes first in the concatenation!
13841402
std::size_t offset_int = little_endian ? (width_bytes - i - 1) : i;
13851403

1386-
plus_exprt offset_i(from_integer(offset_int, offset.type()), offset);
1404+
plus_exprt offset_i{
1405+
from_integer(offset_int, *index_type),
1406+
typecast_exprt::conditional_cast(offset, *index_type)};
13871407
simplify(offset_i, ns);
13881408

13891409
mp_integer index = 0;
@@ -1447,7 +1467,7 @@ static exprt lower_byte_update_byte_array_vector_non_const(
14471467
symbol_exprt array_comprehension_index{
14481468
"$array_comprehension_index_u_a_v" +
14491469
std::to_string(array_comprehension_index_counter),
1450-
c_index_type()};
1470+
to_array_type(src.type()).index_type()};
14511471

14521472
binary_predicate_exprt lower_bound{
14531473
typecast_exprt::conditional_cast(
@@ -1514,6 +1534,10 @@ static exprt lower_byte_update_byte_array_vector(
15141534
src.id() == ID_byte_update_big_endian);
15151535
const bool little_endian = src.id() == ID_byte_update_little_endian;
15161536

1537+
const typet index_type = src.type().id() == ID_array
1538+
? to_array_type(src.type()).index_type()
1539+
: to_vector_type(src.type()).index_type();
1540+
15171541
// apply 'array-update-with' num_elements times
15181542
exprt result = src.op();
15191543

@@ -1522,7 +1546,10 @@ static exprt lower_byte_update_byte_array_vector(
15221546
const exprt &element = value_as_byte_array.operands()[i];
15231547

15241548
exprt where = simplify_expr(
1525-
plus_exprt{src.offset(), from_integer(i, src.offset().type())}, ns);
1549+
plus_exprt{
1550+
typecast_exprt::conditional_cast(src.offset(), index_type),
1551+
from_integer(i, index_type)},
1552+
ns);
15261553

15271554
// skip elements that wouldn't change (skip over typecasts as we might have
15281555
// some signed/unsigned char conversions)
@@ -1593,9 +1620,10 @@ static exprt lower_byte_update_array_vector_unbounded(
15931620
symbol_exprt array_comprehension_index{
15941621
"$array_comprehension_index_u_a_v_u" +
15951622
std::to_string(array_comprehension_index_counter),
1596-
c_index_type()};
1623+
to_array_type(src.type()).index_type()};
15971624

15981625
// all arithmetic uses offset/index types
1626+
PRECONDITION(array_comprehension_index.type() == src.offset().type());
15991627
PRECONDITION(subtype_size.type() == src.offset().type());
16001628
PRECONDITION(initial_bytes.type() == src.offset().type());
16011629
PRECONDITION(first_index.type() == src.offset().type());
@@ -1727,6 +1755,8 @@ static exprt lower_byte_update_array_vector_non_const(
17271755

17281756
// compute the index of the first element of the array/vector that may be
17291757
// updated
1758+
PRECONDITION(
1759+
src.offset().type() == to_array_type(src.op().type()).index_type());
17301760
exprt first_index = div_exprt{src.offset(), subtype_size};
17311761
simplify(first_index, ns);
17321762

@@ -1862,10 +1892,17 @@ static exprt lower_byte_update_array_vector(
18621892
{
18631893
const bool is_array = src.type().id() == ID_array;
18641894
exprt size;
1895+
typet index_type;
18651896
if(is_array)
1897+
{
18661898
size = to_array_type(src.type()).size();
1899+
index_type = to_array_type(src.type()).index_type();
1900+
}
18671901
else
1902+
{
18681903
size = to_vector_type(src.type()).size();
1904+
index_type = to_vector_type(src.type()).index_type();
1905+
}
18691906

18701907
auto subtype_bits = pointer_offset_bits(subtype, ns);
18711908

@@ -1894,7 +1931,7 @@ static exprt lower_byte_update_array_vector(
18941931
(i + 1) * *subtype_bits <= offset_bytes * src.get_bits_per_byte();
18951932
++i)
18961933
{
1897-
elements.push_back(index_exprt{src.op(), from_integer(i, c_index_type())});
1934+
elements.push_back(index_exprt{src.op(), from_integer(i, index_type)});
18981935
}
18991936

19001937
// the modified elements
@@ -1932,7 +1969,7 @@ static exprt lower_byte_update_array_vector(
19321969

19331970
const byte_update_exprt bu{
19341971
src.id(),
1935-
index_exprt{src.op(), from_integer(i, c_index_type())},
1972+
index_exprt{src.op(), from_integer(i, index_type)},
19361973
from_integer(update_offset < 0 ? 0 : update_offset, src.offset().type()),
19371974
array_exprt{
19381975
std::move(update_values),
@@ -1945,7 +1982,7 @@ static exprt lower_byte_update_array_vector(
19451982

19461983
// copy the tail not affected by the update
19471984
for(; i < num_elements; ++i)
1948-
elements.push_back(index_exprt{src.op(), from_integer(i, c_index_type())});
1985+
elements.push_back(index_exprt{src.op(), from_integer(i, index_type)});
19491986

19501987
if(is_array)
19511988
return simplify_expr(

0 commit comments

Comments
 (0)