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 28 class 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 40 Positive1 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 44 struct VirtualBase { 45 int foo; 46 }; 47 48 class 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 58 ClassWithVirtualBase class_with_virtual_base; 59 60 class 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 70 WithFlexibleArray1 with_flexible_array1; 71 // CHECK: %class.WithFlexibleArray1 = type { i32, [12 x i8], [33 x i8], [15 x i8], [0 x i32] } 72 73 class WithFlexibleArray2 { 74 public: 75 char x[21]; 76 WithFlexibleArray1 flex1; // Don't insert padding after this field. 77 }; 78 79 WithFlexibleArray2 with_flexible_array2; 80 // CHECK: %class.WithFlexibleArray2 = type { [21 x i8], [11 x i8], %class.WithFlexibleArray1 } 81 82 class WithFlexibleArray3 { 83 public: 84 char x[13]; 85 WithFlexibleArray2 flex2; // Don't insert padding after this field. 86 }; 87 88 WithFlexibleArray3 with_flexible_array3; 89 90 91 class Negative1 { 92 public: 93 Negative1() {} 94 int public1, public2; 95 }; 96 Negative1 negative1; 97 // CHECK: type { i32, i32 } 98 99 class Negative2 { 100 public: 101 Negative2() {} 102 private: 103 int private1, private2; 104 }; 105 Negative2 negative2; 106 // CHECK: type { i32, i32 } 107 108 union Negative3 { 109 char m1[8]; 110 long long m2; 111 }; 112 113 Negative3 negative3; 114 // CHECK: type { i64 } 115 116 class 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 126 Negative4 negative4; 127 // CHECK: type { i32, i8, i32 } 128 129 class __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 139 Negative5 negative5; 140 // CHECK: type <{ i32, i8, i32 }> 141 142 143 namespace SomeNamespace { 144 class 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 155 SomeNamespace::BlacklistedByName blacklisted_by_name; 156 157 extern "C" { 158 class 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 169 ExternCStruct 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 199 struct WithVirtualDtor { 200 virtual ~WithVirtualDtor(); 201 int x, y; 202 }; 203 struct InheritsFrom_WithVirtualDtor: WithVirtualDtor { 204 int a, b; 205 InheritsFrom_WithVirtualDtor() {} 206 ~InheritsFrom_WithVirtualDtor() {} 207 }; 208 209 void 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. 224 struct ClassWithTrivialCopy { 225 ClassWithTrivialCopy(); 226 ~ClassWithTrivialCopy(); 227 void *a; 228 private: 229 void *c; 230 }; 231 232 void 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