xref: /llvm-project/clang/test/CodeGen/bounds-checking.c (revision 5bb650345d83669434713146aaa431c1f7ad43d6)
1 // N.B. The clang driver defaults to -fsanitize-merge but clang_cc1 effectively
2 // defaults to -fno-sanitize-merge.
3 // RUN: %clang_cc1 -fsanitize=array-bounds -O -fsanitize-trap=array-bounds -emit-llvm -triple x86_64-apple-darwin10 -DNO_DYNAMIC %s -o - |     FileCheck %s
4 // RUN: %clang_cc1 -fsanitize=array-bounds -O                              -emit-llvm -triple x86_64-apple-darwin10 %s -o -              | not FileCheck %s
5 //
6 // RUN: %clang_cc1 -fsanitize=local-bounds    -fsanitize-trap=local-bounds -emit-llvm -triple x86_64-apple-darwin10              %s -o - |     FileCheck %s
7 //
8 // RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds                               -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - |     FileCheck %s --check-prefixes=NOOPTLOCAL
9 // RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -fno-sanitize-merge           -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - |     FileCheck %s --check-prefixes=NOOPTLOCAL
10 // RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -fsanitize-merge=local-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s --check-prefixes=NOOPTLOCAL
11 //
12 // RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds                               -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - |     FileCheck %s --check-prefixes=NOOPTARRAY
13 // RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -fno-sanitize-merge           -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - |     FileCheck %s --check-prefixes=NOOPTARRAY
14 // RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -fsanitize-merge=array-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s --check-prefixes=NOOPTARRAY
15 //
16 // REQUIRES: x86-registered-target
17 
18 // CHECK-LABEL: @f1
19 double f1(int b, int i) {
20   double a[b];
21   // CHECK: call {{.*}} @llvm.{{(ubsan)?trap}}
22   return a[i];
23 }
24 
25 // CHECK-LABEL: @f2
26 void f2(void) {
27   // everything is constant; no trap possible
28   // CHECK-NOT: call {{.*}} @llvm.{{(ubsan)?trap}}
29   int a[2];
30   a[1] = 42;
31 
32 #ifndef NO_DYNAMIC
33   extern void *malloc(__typeof__(sizeof(0)));
34   short *b = malloc(64);
35   b[5] = *a + a[1] + 2;
36 #endif
37 }
38 
39 // CHECK-LABEL: @f3
40 void f3(void) {
41   int a[1];
42   // CHECK: call {{.*}} @llvm.{{(ubsan)?trap}}
43   a[2] = 1;
44 }
45 
46 // CHECK-LABEL: @f4
47 __attribute__((no_sanitize("bounds")))
48 int f4(int i) {
49   int b[64];
50   // CHECK-NOT: call void @llvm.trap()
51   // CHECK-NOT: trap:
52   // CHECK-NOT: cont:
53   return b[i];
54 }
55 
56 // Union flexible-array members are a C99 extension. All array members with a
57 // constant size should be considered FAMs.
58 
59 union U { int a[0]; int b[1]; int c[2]; };
60 
61 // CHECK-LABEL: @f5
62 int f5(union U *u, int i) {
63   // a is treated as a flexible array member.
64   // CHECK-NOT: @llvm.ubsantrap
65   return u->a[i];
66 }
67 
68 // CHECK-LABEL: @f6
69 int f6(union U *u, int i) {
70   // b is treated as a flexible array member.
71   // CHECK-NOT: call {{.*}} @llvm.{{(ubsan)?trap}}
72   return u->b[i];
73 }
74 
75 // CHECK-LABEL: @f7
76 int f7(union U *u, int i) {
77   // c is treated as a flexible array member.
78   // CHECK-NOT: @llvm.ubsantrap
79   return u->c[i];
80 }
81 
82 char B[10];
83 char B2[10];
84 // CHECK-LABEL: @f8
85 // Check the label to prevent spuriously matching ubsantraps from other
86 // functions.
87 // NOOPTLOCAL-LABEL: @f8
88 // NOOPTARRAY-LABEL: @f8
89 void f8(int i, int k) {
90   // NOOPTLOCAL: call void @llvm.ubsantrap(i8 3) #[[ATTR1:[0-9]+]]
91   // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) #[[ATTR2:[0-9]+]]
92   B[i] = '\0';
93 
94   // NOOPTLOCAL: call void @llvm.ubsantrap(i8 5) #[[ATTR1:[0-9]+]]
95   // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) #[[ATTR2:[0-9]+]]
96   B2[k] = '\0';
97 }
98 
99 // See commit 9a954c6 that caused a SEGFAULT in this code.
100 struct S {
101   __builtin_va_list ap;
102 } *s;
103 // CHECK-LABEL: @f9
104 struct S *f9(int i) {
105   return &s[i];
106 }
107 // NOOPTLOCAL: attributes #[[ATTR1]] = { nomerge noreturn nounwind }
108 // NOOPTARRAY: attributes #[[ATTR2]] = { nomerge noreturn nounwind }
109