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
 |