forked from OSchip/llvm-project
240 lines
7.3 KiB
C++
240 lines
7.3 KiB
C++
// Test -fsanitize-address-field-padding
|
|
// RUN: echo 'type:SomeNamespace::BlacklistedByName=field-padding' > %t.type.blacklist
|
|
// RUN: echo 'src:*sanitize-address-field-padding.cpp=field-padding' > %t.file.blacklist
|
|
// 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
|
|
// 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 -fno-experimental-new-pass-manager -mconstructor-aliases 2>&1 | FileCheck %s --check-prefix=WITH_CTOR_ALIASES
|
|
// 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
|
|
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s 2>&1 | FileCheck %s --check-prefix=NO_PADDING
|
|
// Try to emulate -save-temps option and make sure -disable-llvm-passes will not run sanitize instrumentation.
|
|
// 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
|
|
//
|
|
|
|
// The reasons to ignore a particular class are not set in stone and will change.
|
|
//
|
|
// CHECK: -fsanitize-address-field-padding applied to Positive1
|
|
// CHECK: -fsanitize-address-field-padding ignored for Negative1 because it is trivially copyable
|
|
// CHECK: -fsanitize-address-field-padding ignored for Negative2 because it is trivially copyable
|
|
// CHECK: -fsanitize-address-field-padding ignored for Negative3 because it is a union
|
|
// CHECK: -fsanitize-address-field-padding ignored for Negative4 because it is trivially copyable
|
|
// CHECK: -fsanitize-address-field-padding ignored for Negative5 because it is packed
|
|
// CHECK: -fsanitize-address-field-padding ignored for SomeNamespace::BlacklistedByName because it is blacklisted
|
|
// CHECK: -fsanitize-address-field-padding ignored for ExternCStruct because it is not C++
|
|
//
|
|
// FILE_BLACKLIST: -fsanitize-address-field-padding ignored for Positive1 because it is in a blacklisted file
|
|
// FILE_BLACKLIST-NOT: __asan_poison_intra_object_redzone
|
|
// NO_PADDING-NOT: __asan_poison_intra_object_redzone
|
|
|
|
|
|
class Positive1 {
|
|
public:
|
|
Positive1() {}
|
|
~Positive1() {}
|
|
int make_it_non_standard_layout;
|
|
private:
|
|
char private1;
|
|
int private2;
|
|
short private_array[6];
|
|
long long private3;
|
|
};
|
|
|
|
Positive1 positive1;
|
|
// Positive1 with extra paddings
|
|
// CHECK: type { i32, [12 x i8], i8, [15 x i8], i32, [12 x i8], [6 x i16], [12 x i8], i64, [8 x i8] }
|
|
|
|
struct VirtualBase {
|
|
int foo;
|
|
};
|
|
|
|
class ClassWithVirtualBase : public virtual VirtualBase {
|
|
public:
|
|
ClassWithVirtualBase() {}
|
|
~ClassWithVirtualBase() {}
|
|
int make_it_non_standard_layout;
|
|
private:
|
|
char x[7];
|
|
char y[9];
|
|
};
|
|
|
|
ClassWithVirtualBase class_with_virtual_base;
|
|
|
|
class WithFlexibleArray1 {
|
|
public:
|
|
WithFlexibleArray1() {}
|
|
~WithFlexibleArray1() {}
|
|
int make_it_non_standard_layout;
|
|
private:
|
|
char private1[33];
|
|
int flexible[]; // Don't insert padding after this field.
|
|
};
|
|
|
|
WithFlexibleArray1 with_flexible_array1;
|
|
// CHECK: %class.WithFlexibleArray1 = type { i32, [12 x i8], [33 x i8], [15 x i8], [0 x i32] }
|
|
|
|
class WithFlexibleArray2 {
|
|
public:
|
|
char x[21];
|
|
WithFlexibleArray1 flex1; // Don't insert padding after this field.
|
|
};
|
|
|
|
WithFlexibleArray2 with_flexible_array2;
|
|
// CHECK: %class.WithFlexibleArray2 = type { [21 x i8], [11 x i8], %class.WithFlexibleArray1 }
|
|
|
|
class WithFlexibleArray3 {
|
|
public:
|
|
char x[13];
|
|
WithFlexibleArray2 flex2; // Don't insert padding after this field.
|
|
};
|
|
|
|
WithFlexibleArray3 with_flexible_array3;
|
|
|
|
|
|
class Negative1 {
|
|
public:
|
|
Negative1() {}
|
|
int public1, public2;
|
|
};
|
|
Negative1 negative1;
|
|
// CHECK: type { i32, i32 }
|
|
|
|
class Negative2 {
|
|
public:
|
|
Negative2() {}
|
|
private:
|
|
int private1, private2;
|
|
};
|
|
Negative2 negative2;
|
|
// CHECK: type { i32, i32 }
|
|
|
|
union Negative3 {
|
|
char m1[8];
|
|
long long m2;
|
|
};
|
|
|
|
Negative3 negative3;
|
|
// CHECK: type { i64 }
|
|
|
|
class Negative4 {
|
|
public:
|
|
Negative4() {}
|
|
// No DTOR
|
|
int make_it_non_standard_layout;
|
|
private:
|
|
char private1;
|
|
int private2;
|
|
};
|
|
|
|
Negative4 negative4;
|
|
// CHECK: type { i32, i8, i32 }
|
|
|
|
class __attribute__((packed)) Negative5 {
|
|
public:
|
|
Negative5() {}
|
|
~Negative5() {}
|
|
int make_it_non_standard_layout;
|
|
private:
|
|
char private1;
|
|
int private2;
|
|
};
|
|
|
|
Negative5 negative5;
|
|
// CHECK: type <{ i32, i8, i32 }>
|
|
|
|
|
|
namespace SomeNamespace {
|
|
class BlacklistedByName {
|
|
public:
|
|
BlacklistedByName() {}
|
|
~BlacklistedByName() {}
|
|
int make_it_non_standard_layout;
|
|
private:
|
|
char private1;
|
|
int private2;
|
|
};
|
|
} // SomeNamespace
|
|
|
|
SomeNamespace::BlacklistedByName blacklisted_by_name;
|
|
|
|
extern "C" {
|
|
class ExternCStruct {
|
|
public:
|
|
ExternCStruct() {}
|
|
~ExternCStruct() {}
|
|
int make_it_non_standard_layout;
|
|
private:
|
|
char private1;
|
|
int private2;
|
|
};
|
|
} // extern "C"
|
|
|
|
ExternCStruct extern_C_struct;
|
|
|
|
// CTOR
|
|
// CHECK-LABEL: define {{.*}}Positive1C1Ev
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12)
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}15)
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12)
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}12)
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}}8)
|
|
// CHECK-NOT: __asan_poison_intra_object_redzone
|
|
// CHECK: ret void
|
|
//
|
|
// DTOR
|
|
// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12)
|
|
// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}15)
|
|
// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12)
|
|
// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}12)
|
|
// CHECK: call void @__asan_unpoison_intra_object_redzone({{.*}}8)
|
|
// CHECK-NOT: __asan_unpoison_intra_object_redzone
|
|
// CHECK: ret void
|
|
//
|
|
//
|
|
// CHECK-LABEL: define linkonce_odr void @_ZN20ClassWithVirtualBaseC1Ev
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 12)
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 9)
|
|
// CHECK: call void @__asan_poison_intra_object_redzone({{.*}} 15)
|
|
// CHECK-NOT: __asan_poison_intra_object_redzone
|
|
// CHECK: ret void
|
|
//
|
|
|
|
struct WithVirtualDtor {
|
|
virtual ~WithVirtualDtor();
|
|
int x, y;
|
|
};
|
|
struct InheritsFrom_WithVirtualDtor: WithVirtualDtor {
|
|
int a, b;
|
|
InheritsFrom_WithVirtualDtor() {}
|
|
~InheritsFrom_WithVirtualDtor() {}
|
|
};
|
|
|
|
void Create_InheritsFrom_WithVirtualDtor() {
|
|
InheritsFrom_WithVirtualDtor x;
|
|
}
|
|
|
|
|
|
// Make sure the dtor of InheritsFrom_WithVirtualDtor remains in the code,
|
|
// i.e. we ignore -mconstructor-aliases when field paddings are added
|
|
// because the paddings in InheritsFrom_WithVirtualDtor needs to be unpoisoned
|
|
// in the dtor.
|
|
// WITH_CTOR_ALIASES-LABEL: define{{.*}} void @_Z35Create_InheritsFrom_WithVirtualDtor
|
|
// WITH_CTOR_ALIASES-NOT: call void @_ZN15WithVirtualDtorD2Ev
|
|
// WITH_CTOR_ALIASES: call void @_ZN28InheritsFrom_WithVirtualDtorD2Ev
|
|
// WITH_CTOR_ALIASES: ret void
|
|
|
|
// Make sure we don't emit memcpy for operator= if paddings are inserted.
|
|
struct ClassWithTrivialCopy {
|
|
ClassWithTrivialCopy();
|
|
~ClassWithTrivialCopy();
|
|
void *a;
|
|
private:
|
|
void *c;
|
|
};
|
|
|
|
void MakeTrivialCopy(ClassWithTrivialCopy *s1, ClassWithTrivialCopy *s2) {
|
|
*s1 = *s2;
|
|
ClassWithTrivialCopy s3(*s2);
|
|
}
|
|
|
|
// CHECK-LABEL: define{{.*}} void @_Z15MakeTrivialCopyP20ClassWithTrivialCopyS0_
|
|
// CHECK-NOT: memcpy
|
|
// CHECK: ret void
|