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