Skip to content

Commit 314c1c5

Browse files
committed
Remove well-alignedness assumption from pointer-into-array
84df81e fixed the case for unaligned access into arrays when the dereference type did not match the size of array elements. This was, however, missing the case that an unaligned access into an array is done with matching dereference type size. Co-authored-by: Enrico Steffinlongo <[email protected]> Fixes: #7265
1 parent 115b214 commit 314c1c5

File tree

7 files changed

+78
-28
lines changed

7 files changed

+78
-28
lines changed

jbmc/src/java_bytecode/java_trace_validation.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ bool can_evaluate_to_constant(const exprt &expression)
7979
{
8080
return can_cast_expr<constant_exprt>(skip_typecast(expression)) ||
8181
can_cast_expr<symbol_exprt>(skip_typecast(expression)) ||
82-
can_cast_expr<plus_exprt>(skip_typecast(expression));
82+
can_cast_expr<plus_exprt>(skip_typecast(expression)) ||
83+
can_cast_expr<mult_exprt>(skip_typecast(expression));
8384
}
8485

8586
bool check_index_structure(const exprt &index_expr)

regression/cbmc/Pointer_Arithmetic19/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE new-smt-backend
22
main.c
33
--program-only
4-
ASSERT\(\{ 42, 43 \}\[POINTER_OFFSET\(p!0@1#2\) / \d+l*\] == 43\)$
4+
ASSERT\(byte_extract_little_endian\(\{ 42, 43 \}, POINTER_OFFSET\(p!0@1#2\), signed int\) == 43\)$
55
^EXIT=0$
66
^SIGNAL=0$
77
--
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--big-endian -D__BIG_ENDIAN__
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc/Pointer_array7/main.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <assert.h>
2+
#include <stdint.h>
3+
4+
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
5+
6+
# if defined(__avr32__) || defined(__hppa__) || defined(__m68k__) || \
7+
defined(__mips__) || defined(__powerpc__) || defined(__s390__) || \
8+
defined(__s390x__) || defined(__sparc__)
9+
10+
# define __BIG_ENDIAN__
11+
12+
# endif
13+
14+
#endif
15+
16+
int main()
17+
{
18+
uint16_t x[2];
19+
x[0] = 1;
20+
x[1] = 2;
21+
uint8_t *y = (uint8_t *)x;
22+
uint16_t z = *((uint16_t *)(y + 1));
23+
24+
#ifdef __BIG_ENDIAN__
25+
assert(z == 256u);
26+
#else
27+
assert(z == 512u);
28+
#endif
29+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--little-endian -D__LITTLE_ENDIAN__
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc/address_space_size_limit3/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 thorough-smt-backend
22
main.i
33
--32 --little-endian --object-bits 25 --pointer-check
44
^EXIT=10$

src/pointer-analysis/value_set_dereference.cpp

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -577,23 +577,27 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
577577
result.value = typecast_exprt::conditional_cast(object, dereference_type);
578578
result.pointer =
579579
typecast_exprt::conditional_cast(object_pointer, pointer_type);
580+
581+
return result;
580582
}
581-
else if(
583+
584+
// this is relative to the root object
585+
exprt offset;
586+
if(o.offset().is_constant())
587+
offset = o.offset();
588+
else
589+
offset = simplify_expr(pointer_offset(pointer_expr), ns);
590+
591+
if(
582592
root_object_type.id() == ID_array &&
583593
dereference_type_compare(
584594
to_array_type(root_object_type).element_type(), dereference_type, ns) &&
585595
pointer_offset_bits(to_array_type(root_object_type).element_type(), ns) ==
586-
pointer_offset_bits(dereference_type, ns))
596+
pointer_offset_bits(dereference_type, ns) &&
597+
offset.is_constant())
587598
{
588599
// We have an array with a subtype that matches
589600
// the dereferencing type.
590-
exprt offset;
591-
592-
// this should work as the object is essentially the root object
593-
if(o.offset().is_constant())
594-
offset=o.offset();
595-
else
596-
offset=pointer_offset(pointer_expr);
597601

598602
// are we doing a byte?
599603
auto element_size =
@@ -605,18 +609,25 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
605609
to_array_type(root_object_type).element_type().pretty();
606610
}
607611

608-
exprt element_size_expr = from_integer(*element_size, offset.type());
612+
const auto offset_int =
613+
numeric_cast_v<mp_integer>(to_constant_expr(offset));
609614

610-
exprt adjusted_offset =
611-
simplify_expr(div_exprt{offset, element_size_expr}, ns);
615+
if(offset_int % *element_size == 0)
616+
{
617+
index_exprt index_expr{
618+
root_object,
619+
from_integer(
620+
offset_int / *element_size,
621+
to_array_type(root_object_type).index_type())};
622+
result.value =
623+
typecast_exprt::conditional_cast(index_expr, dereference_type);
624+
result.pointer = typecast_exprt::conditional_cast(
625+
address_of_exprt{index_expr}, pointer_type);
612626

613-
index_exprt index_expr{root_object, adjusted_offset};
614-
result.value =
615-
typecast_exprt::conditional_cast(index_expr, dereference_type);
616-
result.pointer = typecast_exprt::conditional_cast(
617-
address_of_exprt{index_expr}, pointer_type);
627+
return result;
628+
}
618629
}
619-
else
630+
620631
{
621632
// try to build a member/index expression - do not use byte_extract
622633
auto subexpr = get_subexpression_at_offset(
@@ -641,13 +652,6 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
641652
result.pointer = typecast_exprt::conditional_cast(
642653
address_of_exprt{skip_typecast(o.root_object())}, pointer_type);
643654

644-
// this is relative to the root object
645-
exprt offset;
646-
if(o.offset().id()==ID_unknown)
647-
offset=pointer_offset(pointer_expr);
648-
else
649-
offset=o.offset();
650-
651655
if(memory_model(result.value, dereference_type, offset, ns))
652656
{
653657
// ok, done

0 commit comments

Comments
 (0)