Re: [PATCH] D12616: Failing test highlighting no poisoning if dtor undeclared.
nmusgrave updated this revision to Diff 34220. nmusgrave marked an inline comment as done. nmusgrave added a comment. - Rename test. http://reviews.llvm.org/D12616 Files: test/CodeGenCXX/sanitize-dtor-trivial.cpp Index: test/CodeGenCXX/sanitize-dtor-trivial.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-trivial.cpp @@ -0,0 +1,15 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue: +//https://github.com/google/sanitizers/issues/596 +// XFAIL: * + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK: call void @__sanitizer_dtor_callback Index: test/CodeGenCXX/sanitize-dtor-trivial.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-trivial.cpp @@ -0,0 +1,15 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue: +//https://github.com/google/sanitizers/issues/596 +// XFAIL: * + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK: call void @__sanitizer_dtor_callback ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r247025 - Failing test highlighting no poisoning if dtor undeclared.
Author: nmusgrave Date: Tue Sep 8 11:38:17 2015 New Revision: 247025 URL: http://llvm.org/viewvc/llvm-project?rev=247025&view=rev Log: Failing test highlighting no poisoning if dtor undeclared. Summary: If class or struct has not declared a destructor, no destructor is emitted, and members are not poisoned after destruction. This case highlights bug in current implementation of use-after-dtor poisoning (detailed in https://github.com/google/sanitizers/issues/596). Reviewers: eugenis, kcc Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D12616 Only check simplest object for existence of sanitizing callback. Rename test. Added: cfe/trunk/test/CodeGenCXX/sanitize-dtor-trivial.cpp Added: cfe/trunk/test/CodeGenCXX/sanitize-dtor-trivial.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/sanitize-dtor-trivial.cpp?rev=247025&view=auto == --- cfe/trunk/test/CodeGenCXX/sanitize-dtor-trivial.cpp (added) +++ cfe/trunk/test/CodeGenCXX/sanitize-dtor-trivial.cpp Tue Sep 8 11:38:17 2015 @@ -0,0 +1,15 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue: +//https://github.com/google/sanitizers/issues/596 +// XFAIL: * + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK: call void @__sanitizer_dtor_callback ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave created this revision. nmusgrave added reviewers: eugenis, kcc. nmusgrave added a subscriber: cfe-commits. After destruction, invocation of virtual functions prevented by poisoning vtable pointer. http://reviews.llvm.org/D12712 Files: lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-derived-class.cpp test/CodeGenCXX/sanitize-dtor-vtable.cpp Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -52,13 +52,17 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}BaseD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}DerivedD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev // CHECK-NOT: call void @__sanitizer_dtor_callback Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1668,9 +1668,20 @@ // Prevent the current stack frame from disappearing from the stack trace. CGF.CurFn->addFnAttr("disable-tail-calls", "true"); + ASTContext &Context = CGF.getContext(); + // Poison vtable and vtable ptr if they exist for this class. + if (Dtor->getParent()->isDynamicClass()) { +llvm::Value *VTablePtr = CGF.LoadCXXThis(); + +CharUnits::QuantityType PoisonSize = +Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity(); +// Pass in void pointer and size of region as arguments to runtime +// function +Poison(CGF, VTablePtr, PoisonSize); + } + // Construct pointer to region to begin poisoning, and calculate poison // size, so that only members declared in this class are poisoned. - ASTContext &Context = CGF.getContext(); unsigned fieldIndex = 0; int startIndex = -1; // RecordDecl::field_iterator Field; @@ -1732,10 +1743,16 @@ if (PoisonSize == 0) return; + Poison(CGF, OffsetPtr, PoisonSize); +} + +void Poison(CodeGenFunction &CGF, llvm::Value *OffsetPtr, +CharUnits::QuantityType PoisonSize) { // Pass in void pointer and size of region as arguments to runtime // function - llvm::Value *Args[] = {CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + llvm::Value *Args[] = { + CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -52,13 +52,17 @@ // CHECK-NOT: call void @__s
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave updated this revision to Diff 34357. nmusgrave added a comment. - Fixed testing callback emission order to account for vptr. Vptr poisoned after all virtual and member destructors are invoked, in order to prevent a data race an on the virtual function invoked by a class instance. (https://github.com/google/sanitizers/wiki/ThreadSanitizerPopularDataRaces#data-race-on-vptr) http://reviews.llvm.org/D12712 Files: lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-derived-class.cpp test/CodeGenCXX/sanitize-dtor-vtable.cpp Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -52,14 +52,17 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}BaseD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}DerivedD2Ev // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback // CHECK: ret void Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1648,11 +1648,15 @@ } }; - class SanitizeDtor final : public EHScopeStack::Cleanup { + + static void Poison(CodeGenFunction &CGF, llvm::Value *OffsetPtr, +CharUnits::QuantityType PoisonSize); + + class SanitizeDtorMembers final : public EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; public: -SanitizeDtor(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} +SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} // Generate function call for handling object poisoning. // Disables tail call elimination, to prevent the current stack frame @@ -1668,9 +1672,21 @@ // Prevent the current stack frame from disappearing from the stack trace. CGF.CurFn->addFnAttr("disable-tail-calls", "true"); + ASTContext &Context = CGF.getContext(); + /* + // Poison vtable and vtable ptr if they exist for this class. + if (Dtor->getParent()->isDynamicClass()) { +llvm::Value *VTablePtr = CGF.LoadCXXThis(); + +CharUnits::QuantityType PoisonSize = +Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity(); +// Pass in void pointer and size of region as arguments to runtime +// function +Poison(CGF, VTablePtr, PoisonSize); + } + */ // Construct pointer to region to begin poisoning, and calculate poison // size, so that only members declared in this class are poisoned. - ASTContext &Context = CGF.getContext(); unsigned fieldIndex = 0; int startIndex = -1; // RecordDecl::field_iterator Field; @@ -1684,11 +1700,11 @@ // Currently on the last field, and it must be poisoned with the // current block. if (fieldIndex == Layout.getFieldCount() - 1) { -PoisonBlock(CGF, startIndex, Layout.getFieldCount()); +PoisonMembers(CGF, startIndex, Layout.getFieldCount()); } } else if (startIndex >= 0) { // No longer within a block of memory to poison, so poison the block - PoisonBlock(CGF, startIndex, fieldIndex); + PoisonMembers(CGF, startIndex, fieldIndex); // Re-set the start index startIndex = -1; } @@ -1701,7 +1717,7 @@ /// start poisoning (inclusive) /// \param layoutEndOffset index of the ASTRecordLayout field to /// end poisoning (exclusive) -void PoisonBlock(CodeGenFunction &CGF, unsigned layoutStartOffset, +void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset,
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave marked an inline comment as done. nmusgrave added a comment. http://reviews.llvm.org/D12712 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave updated this revision to Diff 34373. nmusgrave added a comment. - Cleaned up impl. http://reviews.llvm.org/D12712 Files: lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-derived-class.cpp test/CodeGenCXX/sanitize-dtor-vtable.cpp Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -52,14 +52,17 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}BaseD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}DerivedD2Ev // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback // CHECK: ret void Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1648,11 +1648,15 @@ } }; - class SanitizeDtor final : public EHScopeStack::Cleanup { + + static void Poison(CodeGenFunction &CGF, llvm::Value *OffsetPtr, +CharUnits::QuantityType PoisonSize); + + class SanitizeDtorMembers final : public EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; public: -SanitizeDtor(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} +SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} // Generate function call for handling object poisoning. // Disables tail call elimination, to prevent the current stack frame @@ -1684,11 +1688,11 @@ // Currently on the last field, and it must be poisoned with the // current block. if (fieldIndex == Layout.getFieldCount() - 1) { -PoisonBlock(CGF, startIndex, Layout.getFieldCount()); +PoisonMembers(CGF, startIndex, Layout.getFieldCount()); } } else if (startIndex >= 0) { // No longer within a block of memory to poison, so poison the block - PoisonBlock(CGF, startIndex, fieldIndex); + PoisonMembers(CGF, startIndex, fieldIndex); // Re-set the start index startIndex = -1; } @@ -1701,7 +1705,7 @@ /// start poisoning (inclusive) /// \param layoutEndOffset index of the ASTRecordLayout field to /// end poisoning (exclusive) -void PoisonBlock(CodeGenFunction &CGF, unsigned layoutStartOffset, +void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset, unsigned layoutEndOffset) { ASTContext &Context = CGF.getContext(); const ASTRecordLayout &Layout = @@ -1732,20 +1736,46 @@ if (PoisonSize == 0) return; - // Pass in void pointer and size of region as arguments to runtime - // function - llvm::Value *Args[] = {CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + Poison(CGF, OffsetPtr, PoisonSize); +} + }; + + class SanitizeDtorVTable final : public EHScopeStack::Cleanup { +const CXXDestructorDecl *Dtor; - llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + public: +SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} + +// Generate function call for handling vtable pointer poisoning. +void Emit(CodeGenFunction &CGF, Flags flags) override { + assert(Dtor->getParent()->isDynamicClass()); + ASTContext &Context = CGF.getContext(); + // Poison vtable and vtable ptr if they exist for this class. + llvm::Value *VTablePtr = CGF.LoadCXXThis(); - llvm::FunctionType *FnType = - llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); - llvm::Value *Fn = - CGF.CGM.CreateRuntimeFunction(FnType
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave marked an inline comment as done. Comment at: lib/CodeGen/CGClass.cpp:1685 @@ -1680,3 +1684,3 @@ // Start sanitizing at this field if (startIndex < 0) startIndex = fieldIndex; compiler-rt/test/msan/dtor-multiple-inheritance.cc checks that vtable is still accessible within dtors. http://reviews.llvm.org/D12712 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave marked 2 inline comments as done. Comment at: lib/CodeGen/CGClass.cpp:1652 @@ +1651,3 @@ + + static void Poison(CodeGenFunction &CGF, llvm::Value *OffsetPtr, +CharUnits::QuantityType PoisonSize); eugenis wrote: > If it's a global function, it should have a more descriptive name, like > EmitSanitizerDtorCallback. > OffsetPtr => just Ptr > And move the body of the function to this line to avoid unnecessary > redeclaration. It's inside of a namespace- is it still global? http://reviews.llvm.org/D12712 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave updated this revision to Diff 34614. nmusgrave marked 2 inline comments as done. nmusgrave added a comment. - Fixed testing callback emission order to account for vptr. http://reviews.llvm.org/D12712 Files: lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-derived-class.cpp test/CodeGenCXX/sanitize-dtor-vtable.cpp Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -52,14 +52,17 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}BaseD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}DerivedD2Ev // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK: ret void Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1648,11 +1648,27 @@ } }; - class SanitizeDtor final : public EHScopeStack::Cleanup { + static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr, + CharUnits::QuantityType PoisonSize) { + // Pass in void pointer and size of region as arguments to runtime + // function + llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + + llvm::FunctionType *FnType = + llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); + llvm::Value *Fn = + CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + CGF.EmitNounwindRuntimeCall(Fn, Args); + } + + class SanitizeDtorMembers final : public EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; public: -SanitizeDtor(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} +SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} // Generate function call for handling object poisoning. // Disables tail call elimination, to prevent the current stack frame @@ -1684,11 +1700,11 @@ // Currently on the last field, and it must be poisoned with the // current block. if (fieldIndex == Layout.getFieldCount() - 1) { -PoisonBlock(CGF, startIndex, Layout.getFieldCount()); +PoisonMembers(CGF, startIndex, Layout.getFieldCount()); } } else if (startIndex >= 0) { // No longer within a block of memory to poison, so poison the block - PoisonBlock(CGF, startIndex, fieldIndex); + PoisonMembers(CGF, startIndex, fieldIndex); // Re-set the start index startIndex = -1; } @@ -1701,7 +1717,7 @@ /// start poisoning (inclusive) /// \param layoutEndOffset index of the ASTRecordLayout field to /// end poisoning (exclusive) -void PoisonBlock(CodeGenFunction &CGF, unsigned layoutStartOffset, +void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset, unsigned layoutEndOffset) { ASTContext &Context = CGF.getContext(); const ASTRecordLayout &Layout = @@ -1732,20 +1748,30 @@ if (PoisonSize == 0) return; - // Pass in void pointer and size of region as arguments to runtime - // function - llvm::Value *Args[] = {CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + EmitSanitizerDtorCallback(CGF, OffsetPtr, PoisonSize); +} + }; + + class SanitizeDtorVTable final : public EHScopeStack::Cleanup { +const CXXDestructorDecl *Dtor; +
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave updated this revision to Diff 34617. nmusgrave added a comment. - Poison vtable in either complete or base dtor. http://reviews.llvm.org/D12712 Files: lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-derived-class.cpp test/CodeGenCXX/sanitize-dtor-vtable.cpp Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// Only the last dtor of a class invokes the sanitizing callback -// Sanitizing callback emited prior to base class dtor invocations +// Base dtor poisons members +// Complete dtor poisons vtable ptr after destroying members and +// virtual bases class Base { public: @@ -52,14 +53,17 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}BaseD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison member and vtable pointer. // CHECK-LABEL: define {{.*}}DerivedD2Ev // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK: ret void Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1648,11 +1648,27 @@ } }; - class SanitizeDtor final : public EHScopeStack::Cleanup { + static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr, + CharUnits::QuantityType PoisonSize) { + // Pass in void pointer and size of region as arguments to runtime + // function + llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + + llvm::FunctionType *FnType = + llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); + llvm::Value *Fn = + CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + CGF.EmitNounwindRuntimeCall(Fn, Args); + } + + class SanitizeDtorMembers final : public EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; public: -SanitizeDtor(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} +SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} // Generate function call for handling object poisoning. // Disables tail call elimination, to prevent the current stack frame @@ -1684,11 +1700,11 @@ // Currently on the last field, and it must be poisoned with the // current block. if (fieldIndex == Layout.getFieldCount() - 1) { -PoisonBlock(CGF, startIndex, Layout.getFieldCount()); +PoisonMembers(CGF, startIndex, Layout.getFieldCount()); } } else if (startIndex >= 0) { // No longer within a block of memory to poison, so poison the block - PoisonBlock(CGF, startIndex, fieldIndex); + PoisonMembers(CGF, startIndex, fieldIndex); // Re-set the start index startIndex = -1; } @@ -1701,7 +1717,7 @@ /// start poisoning (inclusive) /// \param layoutEndOffset index of the ASTRecordLayout field to /// end poisoning (exclusive) -void PoisonBlock(CodeGenFunction &CGF, unsigned layoutStartOffset, +void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset, unsigned layoutEndOffset) { ASTContext &Context = C
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave updated this revision to Diff 34822. nmusgrave added a comment. - Re-checking testing for poisoning vtable. http://reviews.llvm.org/D12712 Files: lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-derived-class.cpp test/CodeGenCXX/sanitize-dtor-vtable.cpp Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +class B : virtual public A { + public: + int y; + B() {} + ~B() {} +}; +B b; + +// CHECK-LABEL: define {{.*}}AD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}AD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// After invoking base dtor and dtor for virtual base, poison vtable ptr. +// CHECK-LABEL: define {{.*}}BD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}BD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Since no virtual bases, poison vtable ptr here. +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Poison members +// CHECK-LABEL: define {{.*}}BD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// Only the last dtor of a class invokes the sanitizing callback -// Sanitizing callback emited prior to base class dtor invocations +// Base dtor poisons members +// Complete dtor poisons vtable ptr after destroying members and +// virtual bases class Base { public: @@ -28,6 +29,7 @@ Derived d; +// Invoke base destructor. No vtable pointer to poison. // CHECK-LABEL: define {{.*}}DerivedD1Ev // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}DerivedD2Ev @@ -40,6 +42,7 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Invokes base destructor, and poison vtable pointer. // CHECK-LABEL: define {{.*}}BaseD1Ev // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev @@ -52,14 +55,17 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison members and vtable ptr. // CHECK-LABEL: define {{.*}}BaseD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison members and destroy non-virtual base. // CHECK-LABEL: define {{.*}}DerivedD2Ev // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK: ret void Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1648,11 +1648,27 @@ } }; - class SanitizeDtor final : public EHScopeStack::Cleanup { + static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr, + CharUnits::QuantityType PoisonSize) { + // Pass in void pointer and size of region as arguments to runtime + // function + llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + + llvm::FunctionType *FnType = + llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); + llvm::Value *Fn = + CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + CGF.EmitNounwindRuntimeCall(Fn, Args); + } + + class
Re: [PATCH] D12712: Implementation and testing for poisoning vtable ptr in dtor.
nmusgrave updated this revision to Diff 34851. nmusgrave added a comment. - Remove commented-out block. http://reviews.llvm.org/D12712 Files: lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-derived-class.cpp test/CodeGenCXX/sanitize-dtor-vtable.cpp Index: test/CodeGenCXX/sanitize-dtor-vtable.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-vtable.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +class A { + public: + int x; + A() {} + virtual ~A() {} +}; +A a; + +class B : virtual public A { + public: + int y; + B() {} + ~B() {} +}; +B b; + +// CHECK-LABEL: define {{.*}}AD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}AD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// After invoking base dtor and dtor for virtual base, poison vtable ptr. +// CHECK-LABEL: define {{.*}}BD1Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}BD2Ev +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Since no virtual bases, poison vtable ptr here. +// CHECK-LABEL: define {{.*}}AD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// Poison members +// CHECK-LABEL: define {{.*}}BD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-derived-class.cpp === --- test/CodeGenCXX/sanitize-dtor-derived-class.cpp +++ test/CodeGenCXX/sanitize-dtor-derived-class.cpp @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// Only the last dtor of a class invokes the sanitizing callback -// Sanitizing callback emited prior to base class dtor invocations +// Base dtor poisons members +// Complete dtor poisons vtable ptr after destroying members and +// virtual bases class Base { public: @@ -28,6 +29,7 @@ Derived d; +// Invoke base destructor. No vtable pointer to poison. // CHECK-LABEL: define {{.*}}DerivedD1Ev // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}DerivedD2Ev @@ -40,6 +42,7 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Invokes base destructor, and poison vtable pointer. // CHECK-LABEL: define {{.*}}BaseD1Ev // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev @@ -52,14 +55,17 @@ // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison members and vtable ptr. // CHECK-LABEL: define {{.*}}BaseD2Ev // CHECK: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void +// Poison members and destroy non-virtual base. // CHECK-LABEL: define {{.*}}DerivedD2Ev // CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: call void {{.*}}BaseD2Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void @__sanitizer_dtor_callback{{.*}}i64 8 // CHECK: ret void Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1648,11 +1648,27 @@ } }; - class SanitizeDtor final : public EHScopeStack::Cleanup { + static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr, + CharUnits::QuantityType PoisonSize) { + // Pass in void pointer and size of region as arguments to runtime + // function + llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + + llvm::FunctionType *FnType = + llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); + llvm::Value *Fn = + CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + CGF.EmitNounwindRuntimeCall(Fn, Args); + } + + class SanitizeDtorM
r247762 - Implementation and testing for poisoning vtable
Author: nmusgrave Date: Tue Sep 15 19:38:22 2015 New Revision: 247762 URL: http://llvm.org/viewvc/llvm-project?rev=247762&view=rev Log: Implementation and testing for poisoning vtable ptr in dtor. Summary: After destruction, invocation of virtual functions prevented by poisoning vtable pointer. Reviewers: eugenis, kcc Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D12712 Fixed testing callback emission order to account for vptr. Poison vtable in either complete or base dtor, depending on if virtual bases exist. If virtual bases exist, poison in complete dtor. Otherwise, poison in base. Remove commented-out block. Added: cfe/trunk/test/CodeGenCXX/sanitize-dtor-vtable.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-derived-class.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=247762&r1=247761&r2=247762&view=diff == --- cfe/trunk/lib/CodeGen/CGClass.cpp (original) +++ cfe/trunk/lib/CodeGen/CGClass.cpp Tue Sep 15 19:38:22 2015 @@ -1676,11 +1676,27 @@ namespace { } }; - class SanitizeDtor final : public EHScopeStack::Cleanup { + static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr, + CharUnits::QuantityType PoisonSize) { + // Pass in void pointer and size of region as arguments to runtime + // function + llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + + llvm::FunctionType *FnType = + llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); + llvm::Value *Fn = + CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + CGF.EmitNounwindRuntimeCall(Fn, Args); + } + + class SanitizeDtorMembers final : public EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; public: -SanitizeDtor(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} +SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} // Generate function call for handling object poisoning. // Disables tail call elimination, to prevent the current stack frame @@ -1712,11 +1728,11 @@ namespace { // Currently on the last field, and it must be poisoned with the // current block. if (fieldIndex == Layout.getFieldCount() - 1) { -PoisonBlock(CGF, startIndex, Layout.getFieldCount()); +PoisonMembers(CGF, startIndex, Layout.getFieldCount()); } } else if (startIndex >= 0) { // No longer within a block of memory to poison, so poison the block - PoisonBlock(CGF, startIndex, fieldIndex); + PoisonMembers(CGF, startIndex, fieldIndex); // Re-set the start index startIndex = -1; } @@ -1729,7 +1745,7 @@ namespace { /// start poisoning (inclusive) /// \param layoutEndOffset index of the ASTRecordLayout field to /// end poisoning (exclusive) -void PoisonBlock(CodeGenFunction &CGF, unsigned layoutStartOffset, +void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset, unsigned layoutEndOffset) { ASTContext &Context = CGF.getContext(); const ASTRecordLayout &Layout = @@ -1760,20 +1776,30 @@ namespace { if (PoisonSize == 0) return; - // Pass in void pointer and size of region as arguments to runtime - // function - llvm::Value *Args[] = {CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + EmitSanitizerDtorCallback(CGF, OffsetPtr, PoisonSize); +} + }; + + class SanitizeDtorVTable final : public EHScopeStack::Cleanup { +const CXXDestructorDecl *Dtor; - llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + public: +SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} - llvm::FunctionType *FnType = - llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); - llvm::Value *Fn = - CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); - CGF.EmitNounwindRuntimeCall(Fn, Args); +// Generate function call for handling vtable pointer poisoning. +void Emit(CodeGenFunction &CGF, Flags flags) override { + assert(Dtor->getParent()->isDynamicClass()); + ASTContext &Context = CGF.getContext(); + // Poison vtable and vtable ptr if they exist for this class. + llvm::Value *VTablePtr = CGF.LoadCXXThis(); + + CharUnits::QuantityType PoisonSize = + Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity(); + // Pass in void pointer and size of region as arguments to runtime + // function + EmitSanitizerDtorCallback(CGF, VTab
r247871 - Updating docs for MSan to describe poison-in-dtor.
Author: nmusgrave Date: Wed Sep 16 19:10:59 2015 New Revision: 247871 URL: http://llvm.org/viewvc/llvm-project?rev=247871&view=rev Log: Updating docs for MSan to describe poison-in-dtor. Summary: Describe the compile and runtime flags to enable MemorySanitizer detection of use-after-destroy. Reviewers: eugenis Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D12914 Revise doc description of use-after-dtor. Change wording to specify memory no longer readable. Modified: cfe/trunk/docs/UsersManual.rst Modified: cfe/trunk/docs/UsersManual.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.rst?rev=247871&r1=247870&r2=247871&view=diff == --- cfe/trunk/docs/UsersManual.rst (original) +++ cfe/trunk/docs/UsersManual.rst Wed Sep 16 19:10:59 2015 @@ -1065,6 +1065,16 @@ are listed below. order of memory stores the uninitialized value went through. This mode may use extra memory in programs that copy uninitialized memory a lot. + - ``-fsanitize-memory-use-after-dtor``: Enables use-after-destruction + detection in MemorySanitizer. After invocation of the destructor, + the object is considered no longer readable. Facilitates the + detection of use-after-destroy bugs. + + Setting the MSAN_OPTIONS=poison_in_dtor=1 enables the poisoning of + memory at runtime. Any subsequent access to the destroyed object + fails at runtime. This feature is still experimental, but this + environment variable must be set to 1 in order for the above flag + to have any effect. The ``-fsanitize=`` argument must also be provided when linking, in order to link to the appropriate runtime library. When using ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r244819 - Implement poisoning of only class members in dtor, as opposed to also poisoning fields inherited from base classes.
Author: nmusgrave Date: Wed Aug 12 16:37:40 2015 New Revision: 244819 URL: http://llvm.org/viewvc/llvm-project?rev=244819&view=rev Log: Implement poisoning of only class members in dtor, as opposed to also poisoning fields inherited from base classes. Verify emitted code for derived class with virtual destructor sanitizes its members only once. Changed emission order for dtor callback, so only the last dtor for a class emits the sanitizing callback, while ensuring that class members are poisoned before base class destructors are invoked. Skip poisoning of members, if class has no fields. Removed patch file containing extraneous changes. Summary: Poisoning applied to only class members, and before dtors for base class invoked Reviewers: eugenis, kcc Differential Revision: http://reviews.llvm.org/D11951 Added: cfe/trunk/test/CodeGenCXX/sanitize-dtor-derived-class.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=244819&r1=244818&r2=244819&view=diff == --- cfe/trunk/lib/CodeGen/CGClass.cpp (original) +++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Aug 12 16:37:40 2015 @@ -1376,9 +1376,30 @@ static void EmitDtorSanitizerCallback(Co const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Dtor->getParent()); + // Nothing to poison + if(Layout.getFieldCount() == 0) +return; + + // Construct pointer to region to begin poisoning, and calculate poison + // size, so that only members declared in this class are poisoned. + llvm::Value *OffsetPtr; + CharUnits::QuantityType PoisonSize; + ASTContext &Context = CGF.getContext(); + + llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( + CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). + getQuantity()); + + OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( + CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); + + PoisonSize = Layout.getSize().getQuantity() - + Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); + llvm::Value *Args[] = { - CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, Layout.getSize().getQuantity())}; +CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), +llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; llvm::FunctionType *FnType = @@ -1386,6 +1407,8 @@ static void EmitDtorSanitizerCallback(Co llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + // Disables tail call elimination, to prevent the current stack frame from + // disappearing from the stack trace. CGF.CurFn->addFnAttr("disable-tail-calls", "true"); CGF.EmitNounwindRuntimeCall(Fn, Args); } @@ -1468,6 +1491,13 @@ void CodeGenFunction::EmitDestructorBody // the caller's body. if (getLangOpts().AppleKext) CurFn->addFnAttr(llvm::Attribute::AlwaysInline); + +// Insert memory-poisoning instrumentation, before final clean ups, +// to ensure this class's members are protected from invalid access. +if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor +&& SanOpts.has(SanitizerKind::Memory)) + EmitDtorSanitizerCallback(*this, Dtor); + break; } @@ -1477,11 +1507,6 @@ void CodeGenFunction::EmitDestructorBody // Exit the try if applicable. if (isTryBody) ExitCXXTryStmt(*cast(Body), true); - - // Insert memory-poisoning instrumentation. - if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor - && SanOpts.has(SanitizerKind::Memory)) -EmitDtorSanitizerCallback(*this, Dtor); } void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) { Modified: cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp?rev=244819&r1=244818&r2=244819&view=diff == --- cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp (original) +++ cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp Wed Aug 12 16:37:40 2015 @@ -7,7 +7,8 @@ struct Simple { Simple s; // Simple internal member is poisoned by compiler-generated dtor // CHECK-LABEL: define {{.*}}SimpleD1Ev -// CHECK: call void @__sanitizer_dtor_callback +// CHECK-NOT: call void @__sanitizer_dtor_callback +// CHECK: call void {{.*}}SimpleD2Ev // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void @@ -17,7 +18,8 @@ struct Inlined { Inlined i; // Simple internal member is poisoned by compiler-generated dtor // CHECK-LABEL: define {{.*}}InlinedD1Ev -// CHECK: call void @__sanitizer_dt
r244820 - Revert "Implement poisoning of only class members in dtor, as opposed to also poisoning fields inherited from base classes."
Author: nmusgrave Date: Wed Aug 12 17:07:24 2015 New Revision: 244820 URL: http://llvm.org/viewvc/llvm-project?rev=244820&view=rev Log: Revert "Implement poisoning of only class members in dtor, as opposed to also poisoning fields inherited from base classes." This reverts commit 8dbbf3578a9a5d063232b59e558e5fe46e2cd42c. Rolled back due to buildbot failures on 'ninja check-clang'. Removed: cfe/trunk/test/CodeGenCXX/sanitize-dtor-derived-class.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=244820&r1=244819&r2=244820&view=diff == --- cfe/trunk/lib/CodeGen/CGClass.cpp (original) +++ cfe/trunk/lib/CodeGen/CGClass.cpp Wed Aug 12 17:07:24 2015 @@ -1376,30 +1376,9 @@ static void EmitDtorSanitizerCallback(Co const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Dtor->getParent()); - // Nothing to poison - if(Layout.getFieldCount() == 0) -return; - - // Construct pointer to region to begin poisoning, and calculate poison - // size, so that only members declared in this class are poisoned. - llvm::Value *OffsetPtr; - CharUnits::QuantityType PoisonSize; - ASTContext &Context = CGF.getContext(); - - llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( - CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). - getQuantity()); - - OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( - CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); - - PoisonSize = Layout.getSize().getQuantity() - - Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); - llvm::Value *Args[] = { -CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), -llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; - + CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, Layout.getSize().getQuantity())}; llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; llvm::FunctionType *FnType = @@ -1407,8 +1386,6 @@ static void EmitDtorSanitizerCallback(Co llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); - // Disables tail call elimination, to prevent the current stack frame from - // disappearing from the stack trace. CGF.CurFn->addFnAttr("disable-tail-calls", "true"); CGF.EmitNounwindRuntimeCall(Fn, Args); } @@ -1491,13 +1468,6 @@ void CodeGenFunction::EmitDestructorBody // the caller's body. if (getLangOpts().AppleKext) CurFn->addFnAttr(llvm::Attribute::AlwaysInline); - -// Insert memory-poisoning instrumentation, before final clean ups, -// to ensure this class's members are protected from invalid access. -if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor -&& SanOpts.has(SanitizerKind::Memory)) - EmitDtorSanitizerCallback(*this, Dtor); - break; } @@ -1507,6 +1477,11 @@ void CodeGenFunction::EmitDestructorBody // Exit the try if applicable. if (isTryBody) ExitCXXTryStmt(*cast(Body), true); + + // Insert memory-poisoning instrumentation. + if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor + && SanOpts.has(SanitizerKind::Memory)) +EmitDtorSanitizerCallback(*this, Dtor); } void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) { Modified: cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp?rev=244820&r1=244819&r2=244820&view=diff == --- cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp (original) +++ cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp Wed Aug 12 17:07:24 2015 @@ -7,8 +7,7 @@ struct Simple { Simple s; // Simple internal member is poisoned by compiler-generated dtor // CHECK-LABEL: define {{.*}}SimpleD1Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback -// CHECK: call void {{.*}}SimpleD2Ev +// CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void @@ -18,8 +17,7 @@ struct Inlined { Inlined i; // Simple internal member is poisoned by compiler-generated dtor // CHECK-LABEL: define {{.*}}InlinedD1Ev -// CHECK-NOT: call void @__sanitizer_dtor_callback -// CHECK: call void {{.*}}InlinedD2Ev +// CHECK: call void @__sanitizer_dtor_callback // CHECK-NOT: call void @__sanitizer_dtor_callback // CHECK: ret void @@ -46,8 +44,7 @@ Defaulted_Non_Trivial def_non_trivial; // By including a Simple member in the struct, the compiler is // forced to generate a non-trivial destructor. // CHECK-LABEL: define {{.*}}Defaulted_Non_TrivialD1Ev -// CHECK-NOT: call void @__sa
r244933 - Fix previous commit: poison only class members, simpler tests
Author: nmusgrave Date: Thu Aug 13 13:35:11 2015 New Revision: 244933 URL: http://llvm.org/viewvc/llvm-project?rev=244933&view=rev Log: Fix previous commit: poison only class members, simpler tests Summary: Poisoning applied to only class members, and before dtors for base class invoked Implement poisoning of only class members in dtor, as opposed to also poisoning fields inherited from base classes. Members are poisoned only once, by the last dtor for a class. Skip poisoning if class has no fields. Verify emitted code for derived class with virtual destructor sanitizes its members only once. Removed patch file containing extraneous changes. Reviewers: eugenis, kcc Differential Revision: http://reviews.llvm.org/D11951 Simplified test cases for use-after-dtor Summary: Simplified test cases to focus on one feature at time. Tests updated to align with new emission order for sanitizing callback. Reviewers: eugenis, kcc Differential Revision: http://reviews.llvm.org/D12003 Added: cfe/trunk/test/CodeGenCXX/sanitize-dtor-derived-class.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-fn-attribute.cpp Modified: cfe/trunk/lib/CodeGen/CGClass.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=244933&r1=244932&r2=244933&view=diff == --- cfe/trunk/lib/CodeGen/CGClass.cpp (original) +++ cfe/trunk/lib/CodeGen/CGClass.cpp Thu Aug 13 13:35:11 2015 @@ -1376,9 +1376,30 @@ static void EmitDtorSanitizerCallback(Co const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Dtor->getParent()); + // Nothing to poison + if(Layout.getFieldCount() == 0) +return; + + // Construct pointer to region to begin poisoning, and calculate poison + // size, so that only members declared in this class are poisoned. + llvm::Value *OffsetPtr; + CharUnits::QuantityType PoisonSize; + ASTContext &Context = CGF.getContext(); + + llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( + CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). + getQuantity()); + + OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( + CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); + + PoisonSize = Layout.getSize().getQuantity() - + Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); + llvm::Value *Args[] = { - CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, Layout.getSize().getQuantity())}; +CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), +llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; llvm::FunctionType *FnType = @@ -1386,6 +1407,8 @@ static void EmitDtorSanitizerCallback(Co llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + // Disables tail call elimination, to prevent the current stack frame from + // disappearing from the stack trace. CGF.CurFn->addFnAttr("disable-tail-calls", "true"); CGF.EmitNounwindRuntimeCall(Fn, Args); } @@ -1468,6 +1491,13 @@ void CodeGenFunction::EmitDestructorBody // the caller's body. if (getLangOpts().AppleKext) CurFn->addFnAttr(llvm::Attribute::AlwaysInline); + +// Insert memory-poisoning instrumentation, before final clean ups, +// to ensure this class's members are protected from invalid access. +if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor +&& SanOpts.has(SanitizerKind::Memory)) + EmitDtorSanitizerCallback(*this, Dtor); + break; } @@ -1477,11 +1507,6 @@ void CodeGenFunction::EmitDestructorBody // Exit the try if applicable. if (isTryBody) ExitCXXTryStmt(*cast(Body), true); - - // Insert memory-poisoning instrumentation. - if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor - && SanOpts.has(SanitizerKind::Memory)) -EmitDtorSanitizerCallback(*this, Dtor); } void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) { Modified: cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp?rev=244933&r1=244932&r2=244933&view=diff == --- cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp (original) +++ cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp Thu Aug 13 13:35:11 2015 @@ -1,24 +1,26 @@ // Test -fsanitize-memory-use-after-dtor // RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// Sanitizing dtor is emitted in dtor for every class + struct Simple { + int x; ~Simple() {} }; Simple s; // Simple internal member is poisoned by compiler-generated dt
r245124 - clarified test comment
Author: nmusgrave Date: Fri Aug 14 18:22:03 2015 New Revision: 245124 URL: http://llvm.org/viewvc/llvm-project?rev=245124&view=rev Log: clarified test comment Modified: cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp Modified: cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp?rev=245124&r1=245123&r2=245124&view=diff == --- cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp (original) +++ cfe/trunk/test/CodeGenCXX/sanitize-dtor-callback.cpp Fri Aug 14 18:22:03 2015 @@ -1,7 +1,8 @@ // Test -fsanitize-memory-use-after-dtor // RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s -// Sanitizing dtor is emitted in dtor for every class +// Sanitizing dtor is emitted in dtor for every class, and only +// poisons once. struct Simple { int x; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 32600. nmusgrave added a comment. - CFE test for dtor aliasing, and repression of aliasing in dtor code generation. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,26 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int y; + Derived() { y = 10; } + ~Derived() {} +}; + +Derived d; + +// Declaration of virtual function table +// CHECK: $_ZTV7Derived = comdat any + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1367,52 +1367,6 @@ return true; } -// Generates function call for handling object poisoning, passing in -// references to 'this' and its size as arguments. -// Disables tail call elimination, to prevent the current stack frame from -// disappearing from the stack trace. -static void EmitDtorSanitizerCallback(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor) { - const ASTRecordLayout &Layout = - CGF.getContext().getASTRecordLayout(Dtor->getParent()); - - // Nothing to poison - if(Layout.getFieldCount() == 0) -return; - - // Construct pointer to region to begin poisoning, and calculate poison - // size, so that only members declared in this class are poisoned. - llvm::Value *OffsetPtr; - CharUnits::QuantityType PoisonSize; - ASTContext &Context = CGF.getContext(); - - llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( - CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). - getQuantity()); - - OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( - CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); - - PoisonSize = Layout.getSize().getQuantity() - - Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); - - llvm::Value *Args[] = { -CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), -llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; - - llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; - - llvm::FunctionType *FnType = - llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); - llvm::Value *Fn = - CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); - - // Disables tail call elimination, to prevent the current stack frame from - // disappearing from the stack trace. - CGF.CurFn->addFnAttr("disable-tail-calls", "true"); - CGF.EmitNounwindRuntimeCall(Fn, Args); -} - /// EmitDestructorBody - Emits the body of the current destructor. void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { const CXXDestructorDecl *Dtor = cast(CurGD.getDecl()); @@ -1492,12 +1446,6 @@ if (getLangOpts().AppleKext) CurFn->addFnAttr(llvm::Attribute::AlwaysInline); -// Insert memory-poisoning instrumentation, before final clean ups, -// to ensure this class's members are protected from invalid access. -if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor -&& SanOpts.has(SanitizerKind::Memory)) - EmitDtorSanitizerCallback(*this, Dtor); - break; } @@ -1586,6 +1534,59 @@ flags.isForNormalCleanup() && useEHCleanupForArray); } }; + +class SanitizeDtor : public EHScopeStack::Cleanup { + const CXXDestructorDecl *Dtor; + public: + SanitizeDtor(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} + + // Generate function call for handling object poisoning. + // Disables tail call elimination, to prevent the current stack frame + // from disappearing from the stack trace. + void Emit(CodeGenFunction &CGF, Flags flags) override { +// Check flags to determine if allowed to emit. +if (!CGF.CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor || +!CGF.SanOpts.has(SanitizerKind::Memory)) + return; + +const ASTRecordLayout &Layout = +CGF.getContext().getASTRecordLayout(Dtor->get
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 32608. nmusgrave added a comment. - More complex testing for destruction order. Tests class with base, virtual base, trivial, and nontrivial member to ensure destruction order is correct. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,84 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct VirtualBase { + int y; + VirtualBase() { y = 10; } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int z; + Vector v; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// Declaration of virtual function table +// CHECK: $_ZTV7Derived = comdat any + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: call void {{.*}}ZN7DerivedD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback(i8* %{{[0-9]*}}, i64 4) +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN4BaseD1Ev +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN4BaseD0Ev +// CHECK: call void {{.*}}ZN4BaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback(i8* %{{[0-9]*}}, i64 4) +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback(i8* %{{[0-9]*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1367,52 +1367,6 @@ return true; } -// Generates function call for handling object poisoning, passing in -// references to 'this' and its size as arguments. -// Disables tail call elimination, to prevent the current stack frame from -// disappearing from the stack trace. -static void EmitDtorSanitizerCallback(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor) { - const ASTRecordLayout &Layout = - CGF.getContext().getASTRecordLayout(Dtor->getParent()); - - // Nothing to poison - if(Layout.getFieldCount() == 0) -return; - - // Construct pointer to region to begin poisoning, and calculate poison - // size, so that only members declared in this class are poisoned. - llvm::Value *OffsetPtr; - CharUnits::QuantityType PoisonSize; - ASTContext &Context = CGF.getContext(); - - llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( - CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). - getQuantity()); - - OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( - CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); - - PoisonSize = Layout.getSize().getQuantity() - - Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); - - llvm::Value *Args[] = { -CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), -llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; - - llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; - - llvm::FunctionType *FnType = - llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); - llvm::Value *Fn = - CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); - - // Disables tail call elimination, to prevent the current stack frame from - // disappearing
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 32873. nmusgrave marked 2 inline comments as done. nmusgrave added a comment. - Poisoning on field-by-field basis, with collective poisoning of trivial members when possible. - Cleaned up implementation of calculating region to poison in dtor. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,14 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context,
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave added inline comments. Comment at: lib/CodeGen/CGCXX.cpp:41 @@ +40,3 @@ + if (getCodeGenOpts().SanitizeMemoryUseAfterDtor && Layout.getFieldCount() > 0 + && HasTrivialDestructorBody(Context, D->getParent(), D->getParent())) { +return true; eugenis wrote: > I'm not sure this is correct. It says not to use an alias if D has trivial > body. Should not it be the other way around? It's counter-intuitive: TryEmitBaseDestructorAsAlias returns false when TryEmitDefinitionAsAlias returns false. TryEmitDefinitionAsAlias returns false when an alias is successfully created (line 216 in this CL) http://reviews.llvm.org/D12022 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave added inline comments. Comment at: lib/CodeGen/CGCXX.cpp:41 @@ +40,3 @@ + if (getCodeGenOpts().SanitizeMemoryUseAfterDtor && Layout.getFieldCount() > 0 + && HasTrivialDestructorBody(Context, D->getParent(), D->getParent())) { +return true; nmusgrave wrote: > eugenis wrote: > > I'm not sure this is correct. It says not to use an alias if D has trivial > > body. Should not it be the other way around? > It's counter-intuitive: > TryEmitBaseDestructorAsAlias returns false when TryEmitDefinitionAsAlias > returns false. > TryEmitDefinitionAsAlias returns false when an alias is successfully created > (line 216 in this CL) For example: line 3711 of clang/lib/CodeGen/MicrosoftCXXABI.cpp bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias( GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base), true); ^uses the negation of the function's return value http://reviews.llvm.org/D12022 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave added inline comments. Comment at: lib/CodeGen/CGClass.cpp:1578 @@ +1577,3 @@ +if (CGF.CGM.FieldHasTrivialDestructorBody(Context, Field) || +Field->getType()->isPointerType()) { + // Start sanitizing at this field eugenis wrote: > Why do you need to special-case pointers? FieldHasTrivialDestructorBody doesn't catch pointers- it identifies their base type as some class, and returns false http://reviews.llvm.org/D12022 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 32930. nmusgrave added a comment. - Refactoring dtor sanitizing emission order - support for virtual functions & virtual bases WIP - Repress dtor aliasing when sanitizing in dtor - CFE test for dtor aliasing, and repression of aliasing in dtor code generation. - More complex testing for destruction order. - Poison trivial members one-by-one. - Poisoning on field-by-field basis, with collective poisoning of trivial members when possible. - Cleaned up implementation of calculating region to poison in dtor. - Checking for existence of a single trivial field. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 32986. nmusgrave added a comment. - Refactored for simpler trivial field checking http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl) { @@ -1332,10 +1328,12 @@ return true; } -static
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33037. nmusgrave marked 4 inline comments as done. nmusgrave added a comment. - Simplify function invocations http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl) { @@ -1332,10 +1328,12 @@
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33100. nmusgrave marked an inline comment as done. nmusgrave added a comment. - Check flags before dtor sanitizing http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl) { @@ -1332,10 +1328,1
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33115. nmusgrave added a comment. - Simplify parameters, rename function, for examining fields of class to destroy. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl) { @@ -1332,10 +1328
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33436. nmusgrave added a comment. - Checking for existence of fields to poison in alias emission. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl) { @@ -1332,10 +1328,12 @@ return tr
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave marked 3 inline comments as done. nmusgrave added a comment. http://reviews.llvm.org/D12022 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave added inline comments. Comment at: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp:30 @@ +29,2 @@ +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}(void (%struct.Derived*)* @_ZN7DerivedD1Ev to i8*){{.*}}(void (%struct.Derived*)* @_ZN7DerivedD0Ev to i8*) Its checking that my aliasing is repressed when appropriate.Should I keep or get rid of this test case? http://reviews.llvm.org/D12022 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33463. nmusgrave marked an inline comment as done. nmusgrave added a comment. - Alias-repressing test case ignores casting of pointers. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1098,6 +1098,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl) { @@ -1332,10 +1328,12 @@ return true; } -static bool -FieldHa
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33752. nmusgrave marked 13 inline comments as done. nmusgrave added a comment. - Simplified implementation of class field poisoning, to avoid redundant counting and conditional checks. Expensive checks delayed. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1099,6 +1099,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClas
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave added inline comments. Comment at: lib/CodeGen/CGCXX.cpp:42-44 @@ -33,1 +41,5 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { + // If sanitizing memory to check for use-after-dtor, do not emit as + // an alias, unless it has no fields or has only fields with non-trivial + // destructors. + if (getCodeGenOpts().SanitizeMemoryUseAfterDtor) vptr poisoning will be implemented in another CL after this is approved http://reviews.llvm.org/D12022 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33887. nmusgrave marked 4 inline comments as done. nmusgrave added a comment. - Update comments, consistent style for attribute checking. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: lib/CodeGen/CodeGenModule.h === --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1099,6 +1099,13 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + bool + HasTrivialDestructorBody(ASTContext &Context, + const CXXRecordDecl *BaseClassDecl, + const CXXRecordDecl *MostDerivedClassDecl); + bool + FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); + bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); Index: lib/CodeGen/CGClass.cpp === --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1286,11 +1286,7 @@ CM.finish(); } -static bool -FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); - -static bool -HasTrivialDestructorBody(ASTContext &Context, +bool CodeGenModule::HasTrivialDestructorBody(ASTContext &Context, const CXXRecordDecl *BaseClassDecl, const CXXRecordDecl *MostDerivedClassDecl) { @@ -1332,9 +1328,8 @@ return true; } -static bool -FieldHa
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33956. nmusgrave marked 4 inline comments as done. nmusgrave added a comment. - Testing sanitizing bit fields. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-bit-field.cpp test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-bit-field.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-bit-field.cpp @@ -0,0 +1,66 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// 24 bytes total +struct Packed { + // Packed into 4 bytes + unsigned int a : 1; + unsigned int b : 1; + //unsigned int c : 1; + // Force alignment to next 4 bytes + unsigned int : 0; + unsigned int d : 1; + // Force alignment, 8 more bytes + double e = 5.0; + // 4 bytes + unsigned int f : 1; +}; +Packed p; + + +// 1 byte total +struct Empty { + unsigned int : 0; +}; +Empty e; + + +// 4 byte total +struct Simple { + unsigned int a : 1; +}; +Simple s; + + +// 8 bytes total +struct Anon { + // 1 byte + unsigned int a : 1; + unsigned int b : 2; + // Force alignment to next byte + unsigned int : 0; + unsigned int c : 1; +}; +Anon a; + +struct Foo { + int f; +}; +Foo f; + +// CHECK-LABEL: define {{.*}}PackedD2Ev +//
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33959. nmusgrave added a comment. - Refined testing for bit fields. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-bit-field.cpp test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-bit-field.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-bit-field.cpp @@ -0,0 +1,65 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// 24 bytes total +struct Packed { + // Packed into 4 bytes + unsigned int a : 1; + unsigned int b : 1; + //unsigned int c : 1; + // Force alignment to next 4 bytes + unsigned int : 0; + unsigned int d : 1; + // Force alignment, 8 more bytes + double e = 5.0; + // 4 bytes + unsigned int f : 1; + ~Packed() {} +}; +Packed p; + + +// 1 byte total +struct Empty { + unsigned int : 0; + ~Empty() {} +}; +Empty e; + + +// 4 byte total +struct Simple { + unsigned int a : 1; + ~Simple() {} +}; +Simple s; + + +// 8 bytes total +struct Anon { + // 1 byte + unsigned int a : 1; + unsigned int b : 2; + // Force alignment to next byte + unsigned int : 0; + unsigned int c : 1; + ~Anon() {} +}; +Anon a; + +// CHECK-LABEL: define {{.*}}PackedD2Ev +// CHECK: call void @_
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33978. nmusgrave marked 4 inline comments as done. nmusgrave added a comment. - Simplified fields and checks for aliasing. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-bit-field.cpp test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-bit-field.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-bit-field.cpp @@ -0,0 +1,84 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// 24 bytes total +struct Packed { + // Packed into 4 bytes + unsigned int a : 1; + unsigned int b : 1; + //unsigned int c : 1; + // Force alignment to next 4 bytes + unsigned int : 0; + unsigned int d : 1; + // Force alignment, 8 more bytes + double e = 5.0; + // 4 bytes + unsigned int f : 1; + ~Packed() {} +}; +Packed p; + + +// 1 byte total +struct Empty { + unsigned int : 0; + ~Empty() {} +}; +Empty e; + + +// 4 byte total +struct Simple { + unsigned int a : 1; + ~Simple() {} +}; +Simple s; + + +// 8 bytes total +struct Anon { + // 1 byte + unsigned int a : 1; + unsigned int b : 2; + // Force alignment to next byte + unsigned int : 0; + unsigned int c : 1; + ~Anon() {} +}; +Anon an; + + +struc
Re: [PATCH] D12022: Refactored dtor sanitizing into EHScopeStack
nmusgrave updated this revision to Diff 33982. nmusgrave marked 2 inline comments as done. nmusgrave added a comment. - Clean method headers, style. http://reviews.llvm.org/D12022 Files: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/sanitize-dtor-bit-field.cpp test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Index: test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp @@ -0,0 +1,30 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O2 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() {} +}; + +// Virtual function table for the derived class only contains +// its own destructors, with no aliasing to base class dtors. +struct Base { + Vector v; + int x; + Base() { x = 5; } + virtual ~Base() {} +}; + +struct Derived : public Base { + int z; + Derived() { z = 10; } + ~Derived() {} +}; + +Derived d; + +// Definition of virtual function table +// CHECK: @_ZTV7Derived = {{.*}}@_ZN7DerivedD1Ev{{.*}}@_ZN7DerivedD0Ev Index: test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsanitize=memory -O0 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsanitize=memory -O1 -fsanitize-memory-use-after-dtor -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +template +class Vector { +public: + int size; + ~Vector() { +size += 1; + } +}; + +struct Base { + int b1; + double b2; + Base() { +b1 = 5; +b2 = 10.989; + } + virtual ~Base() {} +}; + +struct VirtualBase { + int vb1; + int vb2; + VirtualBase() { +vb1 = 10; +vb2 = 11; + } + virtual ~VirtualBase() {} +}; + +struct Derived : public Base, public virtual VirtualBase { + int d1; + Vector v; + int d2; + Derived() { +d1 = 10; + } + ~Derived() {} +}; + +Derived d; + +// Destruction order: +// Derived: int, Vector, Base, VirtualBase + +// CHECK-LABEL: define {{.*}}ZN7DerivedD1Ev +// CHECK: call void {{.*}}ZN11VirtualBaseD2Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN7DerivedD0Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD1Ev +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD0Ev +// CHECK: ret void + +// poison 2 ints +// CHECK-LABEL: define {{.*}}ZN11VirtualBaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 8) +// CHECK: ret void + +// poison int and double +// CHECK-LABEL: define {{.*}}ZN4BaseD2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 16) +// CHECK: ret void + +// poison int, ignore vector, poison int +// CHECK-LABEL: define {{.*}}ZN7DerivedD2Ev +// CHECK: call void {{.*}}ZN6VectorIiED1Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: call void {{.*}}ZN4BaseD2Ev +// CHECK: ret void + +// poison int +// CHECK-LABEL: define {{.*}}ZN6VectorIiED2Ev +// CHECK: call void {{.*}}sanitizer_dtor_callback({{.*}}, i64 4) +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-bit-field.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-bit-field.cpp @@ -0,0 +1,84 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// 24 bytes total +struct Packed { + // Packed into 4 bytes + unsigned int a : 1; + unsigned int b : 1; + //unsigned int c : 1; + // Force alignment to next 4 bytes + unsigned int : 0; + unsigned int d : 1; + // Force alignment, 8 more bytes + double e = 5.0; + // 4 bytes + unsigned int f : 1; + ~Packed() {} +}; +Packed p; + + +// 1 byte total +struct Empty { + unsigned int : 0; + ~Empty() {} +}; +Empty e; + + +// 4 byte total +struct Simple { + unsigned int a : 1; + ~Simple() {} +}; +Simple s; + + +// 8 bytes total +struct Anon { + // 1 byte + unsigned int a : 1; + unsigned int b : 2; + // Force alignment to next byte + unsigned int : 0; + unsigned int c : 1; + ~Anon() {} +}; +Anon an; + + +struct CharStruct {
r246815 - Refactored dtor sanitizing into EHScopeStack
Author: nmusgrave Date: Thu Sep 3 18:02:30 2015 New Revision: 246815 URL: http://llvm.org/viewvc/llvm-project?rev=246815&view=rev Log: Refactored dtor sanitizing into EHScopeStack Summary: Dtor sanitization handled amidst other dtor cleanups, between cleaning bases and fields. Sanitizer call pushed onto stack of cleanup operations. Reviewers: eugenis, kcc Differential Revision: http://reviews.llvm.org/D12022 Refactoring dtor sanitizing emission order. - Support multiple inheritance by poisoning after member destructors are invoked, and before base class destructors are invoked. - Poison for virtual destructor and virtual bases. - Repress dtor aliasing when sanitizing in dtor. - CFE test for dtor aliasing, and repression of aliasing in dtor code generation. - Poison members on field-by-field basis, with collective poisoning of trivial members when possible. - Check msan flags and existence of fields, before dtor sanitizing, and when determining if aliasing is allowed. - Testing sanitizing bit fields. Added: cfe/trunk/test/CodeGenCXX/sanitize-dtor-bit-field.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-nontrivial-virtual-base.cpp cfe/trunk/test/CodeGenCXX/sanitize-dtor-repress-aliasing.cpp Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp cfe/trunk/lib/CodeGen/CGClass.cpp cfe/trunk/lib/CodeGen/CodeGenModule.h Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=246815&r1=246814&r2=246815&view=diff == --- cfe/trunk/lib/CodeGen/CGCXX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGCXX.cpp Thu Sep 3 18:02:30 2015 @@ -39,6 +39,12 @@ bool CodeGenModule::TryEmitBaseDestructo if (getCodeGenOpts().OptimizationLevel == 0) return true; + // If sanitizing memory to check for use-after-dtor, do not emit as + // an alias, unless this class owns no members. + if (getCodeGenOpts().SanitizeMemoryUseAfterDtor && + !D->getParent()->field_empty()) +return true; + // If the destructor doesn't have a trivial body, we have to emit it // separately. if (!D->hasTrivialBody()) Modified: cfe/trunk/lib/CodeGen/CGClass.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=246815&r1=246814&r2=246815&view=diff == --- cfe/trunk/lib/CodeGen/CGClass.cpp (original) +++ cfe/trunk/lib/CodeGen/CGClass.cpp Thu Sep 3 18:02:30 2015 @@ -1334,7 +1334,7 @@ HasTrivialDestructorBody(ASTContext &Con static bool FieldHasTrivialDestructorBody(ASTContext &Context, - const FieldDecl *Field) + const FieldDecl *Field) { QualType FieldBaseElementType = Context.getBaseElementType(Field->getType()); @@ -1353,7 +1353,7 @@ FieldHasTrivialDestructorBody(ASTContext /// CanSkipVTablePointerInitialization - Check whether we need to initialize /// any vtable pointers before calling this destructor. -static bool CanSkipVTablePointerInitialization(ASTContext &Context, +static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor) { if (!Dtor->hasTrivialBody()) return false; @@ -1361,58 +1361,12 @@ static bool CanSkipVTablePointerInitiali // Check the fields. const CXXRecordDecl *ClassDecl = Dtor->getParent(); for (const auto *Field : ClassDecl->fields()) -if (!FieldHasTrivialDestructorBody(Context, Field)) +if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field)) return false; return true; } -// Generates function call for handling object poisoning, passing in -// references to 'this' and its size as arguments. -// Disables tail call elimination, to prevent the current stack frame from -// disappearing from the stack trace. -static void EmitDtorSanitizerCallback(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor) { - const ASTRecordLayout &Layout = - CGF.getContext().getASTRecordLayout(Dtor->getParent()); - - // Nothing to poison - if(Layout.getFieldCount() == 0) -return; - - // Construct pointer to region to begin poisoning, and calculate poison - // size, so that only members declared in this class are poisoned. - llvm::Value *OffsetPtr; - CharUnits::QuantityType PoisonSize; - ASTContext &Context = CGF.getContext(); - - llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( - CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). - getQuantity()); - - OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( - CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); - - PoisonSize = Layout.getSize().getQuantity() - - Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); - - llvm::Value *Args[] = { -CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrT
[PATCH] D12616: Failing test highlighting no poisoning if dtor undeclared.
nmusgrave created this revision. nmusgrave added reviewers: eugenis, kcc. nmusgrave added a subscriber: cfe-commits. If class or struct has not declared a destructor, no destsructor is emitted, and members are not poisoned after destruction. This case highlights bug in current implementation of use-after-dtor poisoning. http://reviews.llvm.org/D12616 Files: test/CodeGenCXX/sanitize-dtor-generated.cpp Index: test/CodeGenCXX/sanitize-dtor-generated.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-generated.cpp @@ -0,0 +1,32 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue 596 +// XFAIL: * + +template class Vector { + public: + int size; + ~Vector() {} +}; + +struct NonTrivial { + int a; + Vector v; +}; +NonTrivial nt; + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK-LABEL: define {{.*}}NonTrivialD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}TrivialD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: ret void Index: test/CodeGenCXX/sanitize-dtor-generated.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-generated.cpp @@ -0,0 +1,32 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue 596 +// XFAIL: * + +template class Vector { + public: + int size; + ~Vector() {} +}; + +struct NonTrivial { + int a; + Vector v; +}; +NonTrivial nt; + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK-LABEL: define {{.*}}NonTrivialD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: ret void + +// CHECK-LABEL: define {{.*}}TrivialD2Ev +// CHECK: call void @__sanitizer_dtor_callback +// CHECK: ret void ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12616: Failing test highlighting no poisoning if dtor undeclared.
nmusgrave updated this revision to Diff 34094. nmusgrave marked an inline comment as done. nmusgrave added a comment. - Only check simplest object for existence of sanitizing callback. http://reviews.llvm.org/D12616 Files: test/CodeGenCXX/sanitize-dtor-generated.cpp Index: test/CodeGenCXX/sanitize-dtor-generated.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-generated.cpp @@ -0,0 +1,15 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue: +//https://github.com/google/sanitizers/issues/596 +// XFAIL: * + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK: call void @__sanitizer_dtor_callback Index: test/CodeGenCXX/sanitize-dtor-generated.cpp === --- /dev/null +++ test/CodeGenCXX/sanitize-dtor-generated.cpp @@ -0,0 +1,15 @@ +// Test -fsanitize-memory-use-after-dtor +// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s + +// TODO Success pending on resolution of issue: +//https://github.com/google/sanitizers/issues/596 +// XFAIL: * + +struct Trivial { + int a; + int b; +}; +Trivial t; + +// CHECK: call void @__sanitizer_dtor_callback ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits