Skip to content

Commit cee3d49

Browse files
committed
byte-operators unpack_rec: enforce max-bytes if supplied
Otherwise it may return more bytes than were requested, leading to an invariant violation in lower_byte_update which passes a constant limit and enforces that it is obeyed. Also remove the broken-smt-backend tag from tests which now pass.
1 parent c1c0356 commit cee3d49

File tree

7 files changed

+51
-7
lines changed

7 files changed

+51
-7
lines changed

regression/cbmc/byte_update14/test.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
int main(int argc, char **argv)
5+
{
6+
int array[10];
7+
char *ptr = argc % 2 ? (char *)&array[0] : (char *)&argc;
8+
ptr[argc] = 'a';
9+
ptr[1] = (char)argc;
10+
assert(ptr[1] == (char)argc);
11+
assert(array[1] == (char)argc);
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE broken-smt-backend
2+
test.c
3+
4+
^VERIFICATION FAILED$
5+
^\[main.assertion\.1\] line 10.*SUCCESS$
6+
^\[main.assertion\.2\] line 11.*FAILURE$
7+
^EXIT=10$
8+
^SIGNAL=0$

regression/cbmc/dynamic_size1/stack_object.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
stack_object.c
33
--pointer-check
44
^EXIT=0$

regression/cbmc/pointer-function-parameters-struct-mutual-recursion/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --pointer-check
44
^EXIT=0$

regression/cbmc/pointer-function-parameters-struct-simple-recursion-2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 2 --pointer-check
44
^EXIT=0$

regression/cbmc/pointer-function-parameters-struct-simple-recursion/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --pointer-check
44
^EXIT=0$

src/solvers/lowering/byte_operators.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,11 +583,24 @@ static exprt unpack_array_vector(
583583

584584
// recursively unpack each element so that we eventually just have an array
585585
// of bytes left
586-
exprt sub = unpack_rec(element, little_endian, {}, max_bytes, ns, true);
586+
587+
const optionalt<mp_integer> element_max_bytes =
588+
max_bytes
589+
? std::min(mp_integer{el_bytes}, *max_bytes - byte_operands.size())
590+
: optionalt<mp_integer>{};
591+
const std::size_t element_max_bytes_int =
592+
element_max_bytes ? numeric_cast_v<std::size_t>(*element_max_bytes)
593+
: el_bytes;
594+
595+
exprt sub =
596+
unpack_rec(element, little_endian, {}, element_max_bytes, ns, true);
587597
exprt::operandst sub_operands =
588-
instantiate_byte_array(sub, 0, el_bytes, ns);
598+
instantiate_byte_array(sub, 0, element_max_bytes_int, ns);
589599
byte_operands.insert(
590600
byte_operands.end(), sub_operands.begin(), sub_operands.end());
601+
602+
if(max_bytes && byte_operands.size() >= *max_bytes)
603+
break;
591604
}
592605

593606
const std::size_t size = byte_operands.size();
@@ -926,10 +939,21 @@ static exprt unpack_rec(
926939
// endianness
927940
auto bits_opt = pointer_offset_bits(src.type(), ns);
928941
DATA_INVARIANT(bits_opt.has_value(), "basic type should have a fixed size");
942+
929943
mp_integer bits = *bits_opt;
944+
mp_integer i = 0;
945+
946+
if(max_bytes.has_value())
947+
{
948+
const auto max_bits = *max_bytes * 8;
949+
if(little_endian)
950+
bits = std::min(bits, max_bits);
951+
else
952+
i = std::max(mp_integer{0}, bits - max_bits);
953+
}
930954

931955
exprt::operandst byte_operands;
932-
for(mp_integer i=0; i<bits; i+=8)
956+
for(; i < bits; i += 8)
933957
{
934958
extractbits_exprt extractbits(
935959
typecast_exprt::conditional_cast(

0 commit comments

Comments
 (0)