導讀:本文由猶他州大學的計算機系的 John Regehr 整理。
雖然我不清楚到底有多少人喜歡看讓編譯器崩潰的程式,但這篇文章就是給這些的人(包括我)。我們討論編譯器Bug測試案例的論文就包括很多這種崩潰型的Bug。下文是就是這些 C 語言程式碼段,由工具逐字輸出,程式碼格式上肯定會有些問題。(程式碼段後面申明瞭對應被崩潰的編譯器,有讀者問為什麼沒有 MSVC 編譯器的,Regehr 回覆說他們並沒有測試MSVC 。)
看完這些程式,我們就能總結出什麼東西嗎?這很難說…… 很多 C 語言程式碼段是不容易看出來有問題,如果瞭解其中問題,我們需要知道一個特定編譯器內部解析程式碼的細節。
C1 : Crashes Clang 2.6 at -O0:
1 2 3 4 5 6 7 8 9 10 |
#pragma pack(1) struct S1 { int f0; char f2 }; struct { struct S1 f0 } a[] = { 0 } ; |
C2 : Crashes Clang 2.6 at -O2:
1 2 3 4 5 6 7 8 9 10 |
struct S0 { int f0:1; int f4 } a; void fn1 () { struct S0 b[][1][1] = { 0 }; b[0][0][0] = a; } |
C3 : Crashes Clang 2.6 at -O2:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
unsigned short a; int b; char c; short fn1 () { return 1 / a; } void fn2 () { b = fn1 (); char d = b; c = d % 3; } |
C4 : Crashes Clang 2.6 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
int a, b, c, d, e; #pragma pack(1) struct S0 { int f0:14; int f1:13; int f2:28; int f3:23; int f4:12 }; void fn1 (struct S0); void fn2 () { int f; lbl_2311: ; struct S0 g = { 0, 0, 1 }; fn1 (g); b && e; for (; c;) { if (d) goto lbl_2311; f = a && 1 ? 0 : 1; g.f4 = f; } } |
C5 : Crashes Clang 2.6 at -O2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
int crc32_context, g_2 = 0, g_5; int g_8; int *g_39, *g_371; int g_81; int func_1_l_15 ; static short safe_add_func_int16_t_s_s ( short si1, int si2 ) { return si1 > 67 ? si1 : si1 + si2; } static int func_1 ( ) { int l_462 = 0; g_2 = 0; for ( ; g_2 < 12; g_2 = safe_add_func_int16_t_s_s ( g_2, 5 ) ) { g_5 = 1; for ( ; g_5; ++g_5 ) { g_8 = 1; for ( ; g_8 >= 0; g_8 = g_8 - 1 ) { func_1_l_15 = 1; for ( ; func_1_l_15; func_1_l_15 = func_1_l_15 - 1 ) if ( g_8 ) break; } g_371 = &l_462; int *l_128 = &g_81; *l_128 = *g_39; } *g_371 = 0 != 0 ; } return 0; } int main ( ) { func_1 ( ); crc32_context = g_2; crc32_context += g_5; } |
C6 : Crashes Clang 2.6 at -O0:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#pragma pack(1) struct S2 { int f1; short f4 }; struct S3 { struct S2 f1; int f3:14 }; struct { struct S3 f3 } a = { 0, 0, 0 }; |
C7 : Crashes Clang 2.6 at -O1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int *a; static int **b; int c, d, e; void fn1 () { d = &b == c; for (;;) { int **f = &a; if (e) { } else b = f; if (**b) continue; **f; } } |
C8 : Crashes Clang 2.6 at -O1:
1 2 3 4 5 6 7 8 9 10 |
#pragma pack(1) struct S0 { int f3; char f4 }; struct { struct S0 f6; int f8 } a = { 0, 0, 0 }; |
C9 : Crashes Clang 2.6 at -O2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
struct S0 { int f0; int f1; short f3; int f7; int f8 } b; int a, c, d, e, f; void fn1 (struct S0 p1) { d++; c = p1.f8; e = 0; a = p1.f7; } void fn2 () { e = 0; for (; e; e++) { if (d) for (;;) { } --f; } fn1 (b); } |
C10 : Crashes Clang 2.6 at -O1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
union U2 { int f0; unsigned short f2 } b; static int a = 1; void fn1 (int p1, unsigned short p2) { } int fn2 (union U2); union U2 fn3 (); static unsigned long long fn5 () { fn1 (b.f2, b.f0); return 0; } static char fn4 () { fn5 (); return 0; } int main () { a || fn2 (fn3 (fn4 () ) ); } |
C11 : Crashes Clang 2.7 at -O1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int *a; static int **b; int c, d, e; void fn1 () { d = &b == c; for (;;) { int **f = &a; if (e) { } else b = f; if (**b) continue; **f; } } |
C12 : Crashes Clang 2.7 at -O0:
1 2 3 4 5 6 7 |
char a; unsigned char b; int c; void fn1 () { (b ^= c) != a; } |
C13 : Crashes Clang 2.7 at -O2:
1 2 3 4 5 6 7 8 9 |
int a, b; void fn1 (); void fn2 (short p1) { short c; c = (65532 | 3) + p1; fn1 (c && 1); b = (0 == p1) * a; } |
C14 : Crashes GCC 3.2.0 at -O1:
1 2 3 4 5 6 7 8 |
void fn1 () { struct S0 *a; struct S0 *b, *c = &a; struct S0 **d = &c; if (&b == &a) { } } |
C15 : Crashes GCC 3.2.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
volatile int a, b, c, i; char d; void fn1 () { int e; { for (;; c++) { int f[50] = { }; if (b) { { 0; { { int g = a, h = d; e = h ? g : g / 0; } } a = e; } } } } } void main () { i = 0 / 0; a; } |
C16 : Crashes GCC 3.2.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int a, c; volatile int b; void fn1 () { b; for (;;) break; int d = b, e = a; c = a ? d : d % 0; } void fn2 () { if (0 % 0) b; } |
C17 : Crashes GCC 3.2.0 at -O2:
1 2 3 4 5 6 7 8 9 10 |
union U1 { int f0; char f1 }; void fn1 (union U1 p1) { p1.f1 = 0; for (; p1.f1;) { } } |
C18 : Crashes GCC 3.2.0 at -O1:
1 2 3 4 5 |
int a, b; void fn1 () { b = 4294967290UL <= a | b; } |
C19 : Crashes GCC 3.2.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int a, b, c; int fn1 (int p1, int p2) { return p1 - p2; } void fn2 () { int d; int **e; int ***f = &e; d = a && b ? a : a % 0; if (fn1 (f == 0, 2) ) c = ***f; } |
C20 : Crashes GCC 3.3.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
int a, b, d; struct S0 { int f3 }; int *volatile c; void fn1 (struct S0); void fn2 () { int e; struct S0 **f; struct S0 ***g = &f; (a && b && b ? 0 : b) > (&c && 0); e = 0 == g; d = e >> 1; for (;;) fn1 (***g); } |
C21 : Crashes GCC 3.4.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 |
int a, b; struct U0 { char f0; int f2 }; void fn1 () { struct U0 c; for (; c.f0 != 1; c.f0 = c.f0 + a) b -= 1; } |
C22 : Crashes GCC 3.4.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int a, b, d, e; struct S0 { int f3 }; int *c; void fn1 (struct S0); void fn2 () { struct S0 **f; struct S0 ***g = &f; (a && b && b ? 0 : b) > (&c == d); e = 1 < (0 == g); for (;;) fn1 (***g); } |
C23 : Crashes GCC 4.0.0 at -O2:
1 2 3 4 5 6 7 8 |
int ***a; int b; int *c; void main () { if (&c == a) b = 0 == *a; } |
C24 : Crashes GCC 4.0.0 at -O2:
1 2 3 4 5 6 |
int a[][0]; int *const b = &a[0][1]; int fn1 () { return *b; } |
C25 : Crashes GCC 4.0.0 at -O0:
1 2 3 4 5 6 |
int a, b; unsigned char c; void fn1 () { (0 >= a & (0 || b) ) > c; } |
C26 : Crashes GCC 4.0.0 at -O1:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
struct { int f9:1 } a; const int b[] = { 0 }; void fn1 (); void main () { for (;;) { a.f9 = b[0]; fn1 (); } } |
C27 : Crashes GCC 4.0.0 at -O0:
1 2 3 4 5 6 |
int a, c; unsigned char b; void fn1 () { b > (c > 0 & 0 < a); } |
C28 : Crashes GCC 4.0.0 at -O2:
1 2 3 4 5 6 7 8 9 10 11 12 |
int **a[][0]; static int ***const b = &a[0][1]; void fn1 (); int fn2 () { return ***b; fn1 (); } void fn1 () { **b; } |
C29 : Crashes GCC 4.1.0 at -O1:
1 2 3 4 5 6 7 8 |
volatile int ***a; int b; int **c; void fn1 () { if (&c == a) b = 0 == *a; } |
C30 : Crashes GCC 4.1.0 at -O1:
1 2 3 4 5 6 7 8 9 10 11 12 |
struct { int f0; int f2 } a; int b; void fn1 () { a.f2 = 0; int *c[] = { 0, 0, 0, 0, &a.f0, 0, 0, 0, &a.f0 }; b = *c[4]; } |
C31 : Crashes GCC 4.1.0 at -O2:
1 2 3 4 5 6 7 8 |
int a, b; unsigned c; void fn1 () { for (; c <= 0;) if (b < c) a = 1 && c; } |
C32 : Crashes GCC 4.1.0 at -O1:
1 2 3 4 5 6 7 8 |
unsigned a; int b; void main () { unsigned c = 4294967295; int d = c; b = a <= d || a; } |
C33 : Crashes GCC 4.1.0 at -O1:
1 2 3 4 5 |
const volatile long a; void main () { printf ("%d\n", (int) a); } |
C34 : Crashes GCC 4.1.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int a, b; union U1 { int f0; int f1 }; void fn1 () { union U1 c = { 1 }; int d = 1; if ( (c.f1 & a ? c.f1 : 1 - a) ^ d) { } else b = 0; } |
C35 : Crashes GCC 4.2.0 at -O1:
1 2 3 4 5 6 7 8 |
volatile int ***a; int b; int **c; void fn1 () { if (&c == a) b = 0 == *a; } |
C36 : Crashes GCC 4.2.0 at -O1:
1 2 3 4 5 6 7 8 9 |
struct S2 { volatile int f5:1; int f6 }; static struct S2 a; void main () { printf ("%d\n", a.f5); } |
C37 : Crashes GCC 4.3.0 at -O1:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
long long *a; int b; void fn1 () { long long **c = &a; int d = 7; lbl_2890: { long long **e = &a; b = (e == c) < d; d = 0; goto lbl_2890; } } |
C38 : Crashes GCC 4.3.0 at -O2:
1 2 3 4 5 6 7 8 9 |
struct S2 { volatile int f5:1; int f6 }; static struct S2 a; void main () { printf ("%d\n", a.f5); } |
C39 : Crashes GCC 4.3.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 |
int a; short b; void fn1 () { int c[0]; for (;;) { a = c[0]; b = 0; for (; b < 7; b += 1) c[b] = 0; } } |
C40 : Crashes GCC 4.3.0 at -O1:
1 2 3 4 5 6 7 |
volatile int **a; int *b; void fn1 () { if (a == &b) **a; } |
C41 : Crashes GCC 4.3.0 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 |
int a, b, c, d, e, f; void fn1 () { char g; lbl_120: if (b || e >= 0 & d >= 0 || a) return; g = f < 0 ? 1 : f; d = g == 0 || (char) f == 0 && g == 1 ? 0 : 0 % 0; if (c) goto lbl_120; } |
C42 : Crashes Intel CC 12.0.5 at -O1:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
struct U0 { int f0 } a; struct U0 fn1 () { return a; } void main () { 0 > a.f0; fn1 (); } |
C43 : Crashes Open64 4.2.4 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 |
int a; int *b; unsigned c; void fn1 () { for (; a; a--) if (*b) { c = 0; for (; c >= 5; c++) { } } } |
C44 : Crashes Open64 4.2.4 at -O3:
1 2 3 4 5 6 7 |
short a; void fn1 () { long b; b = 44067713550; a |= b; } |
C45 : Crashes Open64 4.2.4 at -O3:
1 2 3 4 5 6 |
volatile int a; void fn1 () { int b = 1; a || b--; } |
C46 : Crashes Open64 4.2.4 at -O2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
int a, b; void fn1 (); void fn2 (); void fn3 () { fn2 (); fn1 (); } void fn2 () { if (1) { } else for (;; b++) { int c = 0; int *d = &a; int **e = &d; *e = &c; *d = 0; *d |= 0; } } |
C47 : Crashes Open64 4.2.4 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
struct S0 { int f1:1 }; int a, b; void fn1 () { for (; b;) { struct S0 c = { }; if (1) { c = c; a = c.f1; } } } |
C48 : Crashes Open64 4.2.4 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 |
int a, b; int fn1 () { int *c = &b; a = 0; for (; a >= -26; --a) { unsigned d = 18446744073709551615; int *e = &b; *e &= d; } return *c; } |
C49 : Crashes Open64 4.2.4 at -O3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
static int a, c, d; int b; int *e; void fn1 () { for (; a; a += 1) { b = 0; for (; b > -16; --b) for (; c;) { int *f = &d; *f = 0; } *e = 0; } } |
C50 : Crashes Sun CC 5.11 at -xO4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
unsigned char a, d; struct { int f2 } b; int c, e; void fn1 (p1) { } void fn2 () { c = 0; for (; c <= 0;) e = b.f2; fn1 (0); b = b; d = -a; } |
C51 : Crashes Sun CC 5.11 at -fast:
1 2 3 4 5 6 7 8 9 10 |
int a, c; int b[1]; void fn1 () { short d; for (; a; a -= 1) { d = b1 = b1; b[0] = 0; } } |
C52 : Crashes Sun CC 5.11 at -xO4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int a, b, d; short c; int fn1 (p1) { return a ? 0 : p1; } void fn2 () { int e = 0; for (;;) { c = 0; d = fn1 (e ^ ~~c); d && b; } } |
C53 : Crashes Sun CC 5.11 at -fast:
1 2 3 4 5 6 7 8 9 10 11 12 |
long a; int b, d; int *c; void fn1 () { int *e; for (;; b--) for (; d;) { *c = 0; *c &= (&e != 1) / a; } } |
C54 : Crashes Sun CC 5.11 at -xO0:
1 2 3 4 5 6 |
#pragma pack(1) struct { int f3:1; int f4:16 } a = { 1, 0 }; |
C55 : Crashes Sun CC 5.11 at -xO3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int a, c; static int b = 1; void fn1 (); void fn2 () { for (; a; a--) { c = 0; for (; c != 1;) { if (b) break; fn1 (); } } } |
C56 : Crashes Sun CC 5.11 at -xO4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#pragma pack(1) struct S0 { int f1; int f3:1 } a; void fn1 (struct S0 p1) { p1.f3 = 0; } void fn2 () { fn1 (a); } |
C57 : Crashes Sun CC 5.11 at -fast:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
int a, c, d, e, f, g, h, i, j, k; volatile int b; int fn1 () { for (; d; d = a) { int *l = &c; c = -3; for (; c > -23; --c) if (k) { if (*l) continue; return b; } for (; i; ++i) { j = 0; g = h; for (; f <= 1; f += 1) { } } } return e; } |
英文原文:John Regehr 編譯:伯樂線上 – 黃利民
【如需轉載,請標註並保留原文連結、譯文連結和譯者等資訊,謝謝合作!】