#pragma
in the program code. Usually, the result of UB is much duller: the compiler simply optimizes the code for those cases when UB does not occur, without giving the slightest importance to what this code will do in the case of UB - because the standard allows you to do anything in this case! int table[4]; bool exists_in_table(int v) { for (int i = 0; i <= 4; i++) { if (table[i] == v) return true; } return false; }
<=
instead of <
. As a result, exists_in_table()
must either return true
on one of the first four iterations, or it will read the table[4]
, which is UB, and in this case, exists_in_table()
can do anything, including return true
! In full compliance with the standard, the compiler can optimize the exists_in_table()
code to int table[4]; bool exists_in_table(int v) { return true; }
NULL
allowed the compiler to remove this check, creating a vulnerability in the system.p
not initialized, the program can execute both the code inside if (p) { ... }
and the code inside if (!p) { ... }
.INT_MAX
variable x
is equal to INT_MAX
, the expression (x+1)>x
in different places of the same program can be interpreted as both true and false. int a; void bar (void) { setlinebuf(stdout); printf ("hello!\n"); } void foo3 (unsigned y, unsigned z) { bar(); a = y%z; } int main (void) { foo3(1,0); return 0; }
realloc()
is UB. His program prints different values using the same pointer: #include <stdio.h> #include <stdlib.h> int main() { int *p = (int*)malloc(sizeof(int)); int *q = (int*)realloc(p, sizeof(int)); *p = 1; *q = 2; if (p == q) printf("%d %d\n", *p, *q); }
$ clang -O realloc.c; ./a.out 12
while (1) { }
or for (;;) { }
- they understand that the code following such a cycle will never be executed, which means there is no need to compile it. For example, the function void foo (void) { for (;;) { } open_pod_bay_doors(); }
foo: L2: jmp L2
unsigned int i = 0; do { i+=2; } while (0==(i&1));
jmp
instruction. int fermat (void) { const int MAX = 1000; int a=1,b=1,c=1; while (1) { if (((a*a*a) == ((b*b*b)+(c*c*c)))) return 1; a++; if (a>MAX) { a=1; b++; } if (b>MAX) { b=1; c++; } if (c>MAX) { c=1; } } return 0; } #include <stdio.h> int main (void) { if (fermat()) { printf ("Fermat's Last Theorem has been disproved.\n"); } else { printf ("Fermat's Last Theorem has not been disproved.\n"); } return 0; }
regehr @ john-home: ~ $ icc fermat2.c -o fermat2 regehr @ john-home: ~ $ ./fermat2 Fermat's Last Theorem has been disproved. regehr @ john-home: ~ $ suncc -O fermat2.c -o fermat2 "fermat2.c", line 20: warning: statement not reached regehr @ john-home: ~ $ ./fermat2 Fermat's Last Theorem has been disproved.
return 1;
- the compiler was able to prove that Fermat's theorem is incorrect ?!a,b,c
he “found”?return 1;
- that's when the compiler recognized the impotence and honestly compiled an infinite loop. (Nothing, naturally, was printed.)while(1)
is the operator return 1;
, and operator return 0;
end fermat()
unreachable; so he optimizes this feature until int fermat (void) { return 1; }
volatile
.Source: https://habr.com/ru/post/229963/
All Articles