Skip to content

Commit b89ed34

Browse files
committed
Rewriting of (T)(x OP y) must not introduce overflow
Distributing signed-to-unsigned type casts over addition can result in an unsigned overflow where previously there was no overflow.
1 parent e08c77d commit b89ed34

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
int main()
2+
{
3+
int x;
4+
int y;
5+
__CPROVER_assume(x > 0 && -x == y);
6+
unsigned result = x + y;
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--constant-propagator --signed-overflow-check --unsigned-overflow-check
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
10+
This use of "--constant-propagator" is just to exercise expression
11+
simplification. In this example, distributing the type cast from signed to
12+
unsigned int over "x+y" would result in an unsigned integer overflow. The
13+
original program, which does not have such a type cast on each of the operands,
14+
does not have any (unsigned) overflow.

src/util/simplify_expr.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,9 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
918918
to_bitvector_type(expr_type).get_width()>
919919
to_bitvector_type(op_type).get_width();
920920

921-
if(!enlarge)
921+
if(
922+
!enlarge &&
923+
(expr_type.id() != ID_unsignedbv || op_type.id() == ID_unsignedbv))
922924
{
923925
irep_idt op_id = expr.op().id();
924926

0 commit comments

Comments
 (0)