Bug#823222: gcc-4.9: reordering of signed int operations triggers overflow
Package: gcc-4.9
Version: 4.9.2-10
Severity: normal
I compiled the program
#include <stdio.h>
#include <limits.h>
int main() {
int s = 1 << 30;
s += (s - 1);
printf("%d\n%d\n%d\n", sizeof s, s, INT_MAX);
return 0;
}
with "gcc -W -Wall -ansi -pedantic -O0 -fsanitize=undefined".
The executable emits warnings for undefined behaviour at runtime:
a.c:6:7: runtime error: signed integer overflow: 1073741824 + 1073741824 cannot be represented in type 'int'
a.c:6:7: runtime error: signed integer overflow: -2147483648 + -1 cannot be represented in type 'int'
4
2147483647
2147483647
As far as I can tell, the program is correct, and does not involve undefined
behaviour because no signed-integer overflow occurs. It turns out, however,
that gcc transforms
s += (s - 1);
into
s += s;
s -= 1;
even at -O0, as is apparent in the generated assembly code (gcc -O0 -S)
...
movl $1073741824, -12(%ebp)
movl -12(%ebp), %eax
addl %eax, %eax
subl $1, %eax
movl %eax, -12(%ebp)
...
Here, it seems that the compiler and libubsan disagree, and I'm not sure which
one is right.
Best regards,
g.
-- System Information:
Debian Release: 8.4
APT prefers stable
APT policy: (500, 'stable')
Architecture: i386 (i686)
Kernel: Linux 3.16.0-4-686-pae (SMP w/2 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash
Init: sysvinit (via /sbin/init)
Versions of packages gcc-4.9 depends on:
ii binutils 2.25-5
ii cpp-4.9 4.9.2-10
ii gcc-4.9-base 4.9.2-10
ii libc6 2.19-18+deb8u4
ii libcloog-isl4 0.18.2-1+b2
ii libgcc-4.9-dev 4.9.2-10
ii libgmp10 2:6.0.0+dfsg-6
ii libisl10 0.12.2-2
ii libmpc3 1.0.2-1
ii libmpfr4 3.1.2-2
ii zlib1g 1:1.2.8.dfsg-2+b1
Versions of packages gcc-4.9 recommends:
ii libc6-dev 2.19-18+deb8u4
Versions of packages gcc-4.9 suggests:
ii gcc-4.9-doc 4.9.1-3
pn gcc-4.9-locales <none>
pn gcc-4.9-multilib <none>
pn libasan1-dbg <none>
pn libatomic1-dbg <none>
pn libcilkrts5-dbg <none>
pn libgcc1-dbg <none>
pn libgomp1-dbg <none>
pn libitm1-dbg <none>
pn liblsan0-dbg <none>
pn libquadmath0-dbg <none>
pn libtsan0-dbg <none>
pn libubsan0-dbg <none>
-- no debconf information
Reply to: