Skip to content

Commit 28c2022

Browse files
committed
process_array_expr must not generate arrays of negative size
process_array_expr performed an unconditional subtraction to compute the array size of a newly formed type. As the regression test showed, this could result in arrays of negative size being built. (At least) simplify_byte_extract would fail in such cases, as it tested for the size being non-zero, assuming that negative values were impossible. Test is a further simplification of code generated using C-Reduce when starting from SV-COMP's linux-4.0-rc1---drivers--scsi--pmcraid.ko.cil.i.
1 parent 95097a8 commit 28c2022

File tree

4 files changed

+50
-1
lines changed

4 files changed

+50
-1
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// #include <string.h> intentionally omitted
2+
3+
struct c
4+
{
5+
int d;
6+
};
7+
8+
struct e
9+
{
10+
struct c *f;
11+
};
12+
13+
struct g
14+
{
15+
const char *b;
16+
};
17+
18+
int main()
19+
{
20+
unsigned long nondet;
21+
22+
struct g *r = (struct g *)nondet;
23+
r->b = "";
24+
25+
struct e *x = (struct e *)nondet;
26+
int *d = &x->f->d;
27+
28+
memcpy(d + 2, 0, 0);
29+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
^warning: ignoring
9+
Invariant check failed
10+
--
11+
memcpy invocations must not result in generating arrays of negative size, which
12+
process_array_expr previously generated when trying to access a string literal
13+
out of bounds.

src/goto-symex/symex_clean_expr.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,12 @@ process_array_expr(exprt &expr, bool do_simplify, const namespacet &ns)
113113
exprt subtype_size = typecast_exprt::conditional_cast(
114114
subtype_size_opt.value(), array_size_type);
115115
new_offset = div_exprt(new_offset, subtype_size);
116-
minus_exprt new_size(prev_array_type.size(), new_offset);
116+
minus_exprt subtraction{prev_array_type.size(), new_offset};
117+
if_exprt new_size{
118+
binary_predicate_exprt{
119+
subtraction, ID_ge, from_integer(0, subtraction.type())},
120+
subtraction,
121+
from_integer(0, subtraction.type())};
117122
if(do_simplify)
118123
simplify(new_size, ns);
119124

src/util/simplify_expr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,6 +1886,8 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
18861886
}
18871887

18881888
const auto el_size = pointer_offset_bits(expr.type(), ns);
1889+
if(el_size.has_value() && *el_size < 0)
1890+
return unchanged(expr);
18891891

18901892
// byte_extract(byte_extract(root, offset1), offset2) =>
18911893
// byte_extract(root, offset1+offset2)

0 commit comments

Comments
 (0)