Skip to content

Commit 8e651e4

Browse files
authored
Merge pull request #6107 from tautschnig/value-set-byte_extract
Value sets: fix byte extracts from structs
2 parents ffd4ccf + 6ac8ebb commit 8e651e4

File tree

3 files changed

+95
-15
lines changed

3 files changed

+95
-15
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
#ifdef _MSC_VER
5+
# define _Static_assert(x, m) static_assert(x, m)
6+
#endif
7+
8+
struct list;
9+
10+
typedef struct list list_nodet;
11+
12+
list_nodet fill_node(signed int depth_tag_list);
13+
14+
struct list
15+
{
16+
int datum;
17+
struct list *next;
18+
};
19+
20+
int max_depth = 2;
21+
22+
list_nodet *build_node(int depth)
23+
{
24+
if(max_depth < depth)
25+
return ((list_nodet *)NULL);
26+
else
27+
{
28+
_Static_assert(sizeof(list_nodet) == 16, "");
29+
list_nodet *result = malloc(16);
30+
31+
if(result)
32+
{
33+
*result = fill_node(depth + 1);
34+
}
35+
return result;
36+
}
37+
}
38+
39+
list_nodet fill_node(int depth)
40+
{
41+
list_nodet result;
42+
result.datum = depth;
43+
result.next = build_node(depth);
44+
return result;
45+
}
46+
47+
int main()
48+
{
49+
list_nodet *node = build_node(0);
50+
int i = 0;
51+
list_nodet *list_walker = node;
52+
for(; list_walker; list_walker = list_walker->next)
53+
{
54+
i = i + 1;
55+
}
56+
assert(i == 3);
57+
return 0;
58+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--64 --unwind 4 --unwinding-assertions
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
^CONVERSION ERROR$

src/pointer-analysis/value_set.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -891,34 +891,47 @@ void value_sett::get_value_set_rec(
891891

892892
bool found=false;
893893

894-
exprt op1 = byte_extract_expr.op1();
895-
if(eval_pointer_offset(op1, ns))
896-
simplify(op1, ns);
897-
898-
const auto op1_offset = numeric_cast<mp_integer>(op1);
899894
const typet &op_type = ns.follow(byte_extract_expr.op().type());
900-
if(op1_offset.has_value() && op_type.id() == ID_struct)
895+
if(op_type.id() == ID_struct)
901896
{
897+
exprt offset = byte_extract_expr.offset();
898+
if(eval_pointer_offset(offset, ns))
899+
simplify(offset, ns);
900+
901+
const auto offset_int = numeric_cast<mp_integer>(offset);
902+
const auto type_size = pointer_offset_size(expr.type(), ns);
903+
902904
const struct_typet &struct_type = to_struct_type(op_type);
903905

904906
for(const auto &c : struct_type.components())
905907
{
906908
const irep_idt &name = c.get_name();
907909

908-
auto comp_offset = member_offset(struct_type, name, ns);
909-
910-
if(!comp_offset.has_value())
911-
continue;
912-
else if(*comp_offset > *op1_offset)
913-
break;
914-
else if(*comp_offset != *op1_offset)
915-
continue;
910+
if(offset_int.has_value())
911+
{
912+
auto comp_offset = member_offset(struct_type, name, ns);
913+
if(comp_offset.has_value())
914+
{
915+
if(
916+
type_size.has_value() && *offset_int + *type_size <= *comp_offset)
917+
{
918+
break;
919+
}
920+
921+
auto member_size = pointer_offset_size(c.type(), ns);
922+
if(
923+
member_size.has_value() &&
924+
*offset_int >= *comp_offset + *member_size)
925+
{
926+
continue;
927+
}
928+
}
929+
}
916930

917931
found=true;
918932

919933
member_exprt member(byte_extract_expr.op(), c);
920934
get_value_set_rec(member, dest, suffix, original_type, ns);
921-
break;
922935
}
923936
}
924937

0 commit comments

Comments
 (0)