Home | History | Annotate | Download | only in CodeGen
      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