Skip to content

Commit 07ae494

Browse files
committed
add a check for overflow on unsigned unary minus
This adds a check that the operand of an unsigned unary minus is not zero when unsigned overflow checks are enabled. Closes #6114.
1 parent 942685c commit 07ae494

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <limits.h>
2+
3+
int main()
4+
{
5+
signed int x, y;
6+
7+
x = INT_MIN;
8+
9+
// this is an overflow
10+
y = -x;
11+
12+
// ok
13+
x = -(x + 1);
14+
15+
unsigned a, b;
16+
17+
a = 1;
18+
a = -a; // overflow, -1 is not representable
19+
20+
b = 0;
21+
b = -b; // ok
22+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
unary_minus_overflow.c
3+
--signed-overflow-check --unsigned-overflow-check
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[.*\] line .* arithmetic overflow on signed unary minus in -x: FAILURE$
7+
^\[.*\] line .* arithmetic overflow on signed unary minus in -\(x \+ 1\): SUCCESS$
8+
^\[.*\] line .* arithmetic overflow on unsigned unary minus in -a: SUCCESS$
9+
^\[.*\] line .* arithmetic overflow on unsigned unary minus in -b: FAILURE$
10+
--

src/analyses/goto_check.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,8 @@ void goto_checkt::integer_overflow_check(
734734
{
735735
if(type.id()==ID_signedbv)
736736
{
737-
// overflow on unary- can only happen with the smallest
738-
// representable number 100....0
737+
// overflow on unary- on signed integers can only happen with the
738+
// smallest representable number 100....0
739739

740740
equal_exprt int_min_eq(
741741
to_unary_minus_expr(expr).op(), to_signedbv_type(type).smallest_expr());
@@ -748,6 +748,22 @@ void goto_checkt::integer_overflow_check(
748748
expr,
749749
guard);
750750
}
751+
else if(type.id() == ID_unsignedbv)
752+
{
753+
// Overflow on unary- on unsigned integers happens for all operands
754+
// that are not zero.
755+
756+
notequal_exprt not_eq_zero(
757+
to_unary_minus_expr(expr).op(), to_unsignedbv_type(type).zero_expr());
758+
759+
add_guarded_property(
760+
not_eq_zero,
761+
"arithmetic overflow on unsigned unary minus",
762+
"overflow",
763+
expr.find_source_location(),
764+
expr,
765+
guard);
766+
}
751767

752768
return;
753769
}

0 commit comments

Comments
 (0)