Clang Project

clang_source_code/test/CodeGen/sanitize-address-field-padding.cpp
1// Test -fsanitize-address-field-padding
2// RUN: echo 'type:SomeNamespace::BlacklistedByName=field-padding' > %t.type.blacklist
3// RUN: echo 'src:*sanitize-address-field-padding.cpp=field-padding' > %t.file.blacklist
4// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s
5// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.type.blacklist -Rsanitize-address -emit-llvm -o - %s -O1 -mconstructor-aliases 2>&1 | FileCheck %s --check-prefix=WITH_CTOR_ALIASES
6// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsanitize=address -fsanitize-address-field-padding=1 -fsanitize-blacklist=%t.file.blacklist -Rsanitize-address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=FILE_BLACKLIST
7// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=NO_PADDING
8// Try to emulate -save-temps option and make sure -disable-llvm-passes will not run sanitize instrumentation.
9// RUN: %clang_cc1 -fsanitize=address -emit-llvm -disable-llvm-passes -o - %s | %clang_cc1 -fsanitize=address -emit-llvm -o - -x ir | FileCheck %s --check-prefix=NO_PADDING
10//
11
12// The reasons to ignore a particular class are not set in stone and will change.
13//
14// CHECK: -fsanitize-address-field-padding applied to Positive1
15// CHECK: -fsanitize-address-field-padding ignored for Negative1 because it is trivially copyable
16// CHECK: -fsanitize-address-field-padding ignored for Negative2 because it is trivially copyable
17// CHECK: -fsanitize-address-field-padding ignored for Negative3 because it is a union
18// CHECK: -fsanitize-address-field-padding ignored for Negative4 because it is trivially copyable
19// CHECK: -fsanitize-address-field-padding ignored for Negative5 because it is packed
20// CHECK: -fsanitize-address-field-padding ignored for SomeNamespace::BlacklistedByName because it is blacklisted
21// CHECK: -fsanitize-address-field-padding ignored for ExternCStruct because it is not C++
22//
23// FILE_BLACKLIST: -fsanitize-address-field-padding ignored for Positive1 because it is in a blacklisted file
24// FILE_BLACKLIST-NOT: __asan_poison_intra_object_redzone
25// NO_PADDING-NOT: __asan_poison_intra_object_redzone
26
27
28class Positive1 {
29 public:
30  Positive1() {}
31  ~Positive1() {}
32  int make_it_non_standard_layout;
33 private:
34  char private1;
35  int private2;
36  short private_array[6];
37  long long private3;
38};
39
40Positive1 positive1;
41// Positive1 with extra paddings
42// CHECK: type { i32, [12 x i8], i8, [15 x i8], i32, [12 x i8], [6 x i16], [12 x i8], i64, [8 x i8] }
43
44struct VirtualBase {
45  int foo;
46};
47
48class ClassWithVirtualBase : public virtual VirtualBase {
49 public:
50  ClassWithVirtualBase() {}
51  ~ClassWithVirtualBase() {}
52  int make_it_non_standard_layout;
53 private:
54  char x[7];
55  char y[9];
56};
57
58ClassWithVirtualBase class_with_virtual_base;
59
60class WithFlexibleArray1 {
61 public:
62  WithFlexibleArray1() {}
63  ~WithFlexibleArray1() {}
64  int make_it_non_standard_layout;
65 private:
66  char private1[33];
67  int flexible[];  // Don't insert padding after this field.
68};
69
70WithFlexibleArray1 with_flexible_array1;
71// CHECK: %class.WithFlexibleArray1 = type { i32, [12 x i8], [33 x i8], [15 x i8], [0 x i32] }
72
73class WithFlexibleArray2 {
74 public:
75  char x[21];
76  WithFlexibleArray1 flex1;  // Don't insert padding after this field.
77};
78
79WithFlexibleArray2 with_flexible_array2;
80// CHECK: %class.WithFlexibleArray2 = type { [21 x i8], [11 x i8], %class.WithFlexibleArray1 }
81
82class WithFlexibleArray3 {
83 public:
84  char x[13];
85  WithFlexibleArray2 flex2;  // Don't insert padding after this field.
86};
87
88WithFlexibleArray3 with_flexible_array3;
89
90
91class Negative1 {
92 public:
93  Negative1() {}
94  int public1, public2;
95};
96Negative1 negative1;
97// CHECK: type { i32, i32 }
98
99class Negative2 {
100 public:
101  Negative2() {}
102 private:
103  int private1, private2;
104};
105Negative2 negative2;
106// CHECK: type { i32, i32 }
107
108union Negative3 {
109  char m1[8];
110  long long m2;
111};
112
113Negative3 negative3;
114// CHECK: type { i64 }
115
116class Negative4 {
117 public:
118  Negative4() {}
119  // No DTOR
120  int make_it_non_standard_layout;
121 private:
122  char private1;
123  int private2;
124};
125
126Negative4 negative4;
127// CHECK: type { i32, i8, i32 }
128
129class __attribute__((packed)) Negative5 {
130 public:
131  Negative5() {}
132  ~Negative5() {}
133  int make_it_non_standard_layout;
134 private:
135  char private1;
136  int private2;
137};
138
139Negative5 negative5;
140// CHECK: type <{ i32, i8, i32 }>
141
142
143namespace SomeNamespace {
144class BlacklistedByName {
145 public:
146  BlacklistedByName() {}
147  ~BlacklistedByName() {}
148  int make_it_non_standard_layout;
149 private:
150  char private1;
151  int private2;
152};
153}  // SomeNamespace
154
155SomeNamespace::BlacklistedByName blacklisted_by_name;
156
157extern "C" {
158class ExternCStruct {
159 public:
160  ExternCStruct() {}
161  ~ExternCStruct() {}
162  int make_it_non_standard_layout;
163 private:
164  char private1;
165  int private2;
166};
167}  // extern "C"
168
169ExternCStruct extern_C_struct;
170
171// CTOR
172// CHECK-LABEL: define {{.*}}Positive1C1Ev
173// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12)
174// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}15)
175// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12)
176// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12)
177// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}8)
178// CHECK-NOT: __asan_poison_intra_object_redzone
179// CHECK: ret void
180//
181// DTOR
182// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12)
183// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}15)
184// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12)
185// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12)
186// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}8)
187// CHECK-NOT: __asan_unpoison_intra_object_redzone
188// CHECK: ret void
189//
190//
191// CHECK-LABEL: define linkonce_odr void @_ZN20ClassWithVirtualBaseC1Ev
192// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 12)
193// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 9)
194// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 15)
195// CHECK-NOT: __asan_poison_intra_object_redzone
196// CHECK: ret void
197//
198
199struct WithVirtualDtor {
200  virtual ~WithVirtualDtor();
201  int x, y;
202};
203struct InheritsFrom_WithVirtualDtor: WithVirtualDtor {
204  int a, b;
205  InheritsFrom_WithVirtualDtor() {}
206  ~InheritsFrom_WithVirtualDtor() {}
207};
208
209void Create_InheritsFrom_WithVirtualDtor() {
210  InheritsFrom_WithVirtualDtor x;
211}
212
213
214// Make sure the dtor of InheritsFrom_WithVirtualDtor remains in the code,
215// i.e. we ignore -mconstructor-aliases when field paddings are added
216// because the paddings in InheritsFrom_WithVirtualDtor needs to be unpoisoned
217// in the dtor.
218// WITH_CTOR_ALIASES-LABEL: define void @_Z35Create_InheritsFrom_WithVirtualDtor
219// WITH_CTOR_ALIASES-NOT: call void @_ZN15WithVirtualDtorD2Ev
220// WITH_CTOR_ALIASES: call void @_ZN28InheritsFrom_WithVirtualDtorD2Ev
221// WITH_CTOR_ALIASES: ret void
222
223// Make sure we don't emit memcpy for operator= if paddings are inserted.
224struct ClassWithTrivialCopy {
225  ClassWithTrivialCopy();
226  ~ClassWithTrivialCopy();
227  void *a;
228 private:
229  void *c;
230};
231
232void MakeTrivialCopy(ClassWithTrivialCopy *s1, ClassWithTrivialCopy *s2) {
233  *s1 = *s2;
234  ClassWithTrivialCopy s3(*s2);
235}
236
237// CHECK-LABEL: define void @_Z15MakeTrivialCopyP20ClassWithTrivialCopyS0_
238// CHECK-NOT: memcpy
239// CHECK: ret void
240