-
-
Save bcantrill/7b30914541fe6c3306fc174992d497ec to your computer and use it in GitHub Desktop.
Punishment doesn't fit the crime?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define NULL ((void *)0) | |
static char *arr[2] = { "nasal", "demons" }; | |
long | |
func() | |
{ | |
int i; | |
for (i = 0; i <= 2; i++) { | |
if (arr[i] == NULL && i == 0) | |
return (0xbad); | |
} | |
return (0xfad); | |
} |
I don't know what's going on here but this is fun:
ubuntu:tmp$ gcc --version
gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ubuntu:tmp$ gcc -O1 -c ub.c && objdump -d ub.o
ub.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <func>:
0: b8 ad 0f 00 00 mov $0xfad,%eax
5: c3 retq
ubuntu:tmp$ gcc -O2 -c ub.c && objdump -d ub.o
ub.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <func>:
0: b8 ad 0b 00 00 mov $0xbad,%eax
5: c3 retq
GCC 6.3 or earlier doesn't even produce output under -O2
. Heh.
So, adding -fno-aggressive-loop-optimizations
makes this code run correctly -- a flag that itself was added because the aggressive loop optimization broke SPEC CPU 2006. As for the GCC code itself, it is remarkably frank about this optimization.
More weird example (https://godbolt.org/z/VM3nMo):
static char *arr[2] = { "nasal", "demons" };
long
func_n()
{
int i;
for (i = 0; i <= 2; i++) {
if (!arr[i])
return (1);
}
return (0);
}
long
func_p()
{
int i;
for (i = 0; i <= 2; i++) {
if (arr[i])
return (1);
}
return (0);
}
long
func_control(int control)
{
int i;
for (i = 0; i <= 2; i++) {
if ( (!control && !arr[i]) || (control && arr[i]) )
return (1);
}
return (0);
}
results into:
func_n:
mov eax, 1
ret
func_p:
mov eax, 1
ret
func_control:
mov edx, 3
mov eax, 1
test edi, edi
jne .L4
.L9:
sub edx, 1
jne .L9
xor eax, eax
.L4:
ret
As one could see the UB is abruptly "conditional" (in func_control
) if one extend it with control-switch.
And as already said, what on this UB is unexpected for developer (sorry for tautology):
- this does not produce the warning
array subscript 2 is above array bounds of 'char *[2]' [-Warray-bounds]
.
Even not with-Wall
or-Wextra
; - small amends (like variable
control
condition infunc_control
) change the UB drastically; - it is extremely unstable between gcc-versions (and of course the compile-flags).
Clear, it is an UB, but why this could not be a bit "stable" UB, remaining the same result between versions.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Compiling
-O2
on GCC 7:Seems a tad harsh!