Skip to content

Commit 1d9087e

Browse files
committed
Support reordered pointer operands in local_bitvector_analysis
`local_bitvector_analysist` previously assumed that pointer arithmetic expressions with 3+ operands always have the pointer operand at position `op0()`. We do not, however, have such a requirement anywhere, and even if front-ends construct expressions this way then simplification may re-order the operands. Fixes: #2689
1 parent 4fe3ade commit 1d9087e

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Test case for issue #2689
2+
// This test verifies that goto-instrument can analyze binaries
3+
// generated by goto-analyzer --simplify without assertion failures
4+
// in local_bitvector_analysis.cpp
5+
6+
int array[10];
7+
8+
int main()
9+
{
10+
int *p = array;
11+
// Pointer arithmetic that may be simplified in various ways
12+
int *q = p + 1 + 2; // This could be simplified to p + 3
13+
int *r = p + 1 + 2 + 3; // Multiple additions
14+
15+
// Access through computed pointer
16+
*q = 42;
17+
*r = 43;
18+
19+
return 0;
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
--call-graph
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring

src/analyses/local_bitvector_analysis.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,26 @@ local_bitvector_analysist::flagst local_bitvector_analysist::get_rec(
173173

174174
if(plus_expr.operands().size() >= 3)
175175
{
176-
DATA_INVARIANT(
177-
plus_expr.op0().type().id() == ID_pointer,
178-
"pointer in pointer-typed sum must be op0");
179-
return get_rec(plus_expr.op0(), loc_info_src) | flagst::mk_uses_offset();
176+
// In pointer arithmetic with 3+ operands, typically the pointer is op0,
177+
// but simplification may reorder operands. Search for the pointer operand.
178+
if(plus_expr.op0().type().id() == ID_pointer)
179+
{
180+
return get_rec(plus_expr.op0(), loc_info_src) |
181+
flagst::mk_uses_offset();
182+
}
183+
else
184+
{
185+
// Search for pointer operand in remaining operands
186+
for(const auto &op : plus_expr.operands())
187+
{
188+
if(op.type().id() == ID_pointer)
189+
{
190+
return get_rec(op, loc_info_src) | flagst::mk_uses_offset();
191+
}
192+
}
193+
// No pointer operand found
194+
return flagst::mk_unknown();
195+
}
180196
}
181197
else if(plus_expr.operands().size() == 2)
182198
{

0 commit comments

Comments
 (0)