r216434 - [clang/asan] call __asan_poison_cxx_array_cookie after operator new[]

Kostya Serebryany kcc at google.com
Mon Aug 25 19:30:00 PDT 2014


Author: kcc
Date: Mon Aug 25 21:29:59 2014
New Revision: 216434

URL: http://llvm.org/viewvc/llvm-project?rev=216434&view=rev
Log:
[clang/asan] call __asan_poison_cxx_array_cookie after operator new[]

Summary:
PR19838
When operator new[] is called and an array cookie is created
we want asan to detect buffer overflow bugs that touch the cookie.
For that we need to
  a) poison the shadow for the array cookie (call __asan_poison_cxx_array_cookie).
  b) ignore the legal accesses to the cookie generated by clang (add 'nosanitize' metadata)

Reviewers: timurrrr, samsonov, rsmith

Reviewed By: rsmith

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D4774

Added:
    cfe/trunk/test/CodeGen/address-sanitizer-and-array-cookie.cpp
Modified:
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/lib/CodeGen/SanitizerMetadata.cpp
    cfe/trunk/lib/CodeGen/SanitizerMetadata.h

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=216434&r1=216433&r2=216434&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Aug 25 21:29:59 2014
@@ -1683,11 +1683,8 @@ void CodeGenFunction::InsertHelper(llvm:
                                    llvm::BasicBlock *BB,
                                    llvm::BasicBlock::iterator InsertPt) const {
   LoopStack.InsertHelper(I);
-  if (IsSanitizerScope) {
-    I->setMetadata(
-        CGM.getModule().getMDKindID("nosanitize"),
-        llvm::MDNode::get(CGM.getLLVMContext(), ArrayRef<llvm::Value *>()));
-  }
+  if (IsSanitizerScope)
+    CGM.getSanitizerMetadata()->disableSanitizerForInstruction(I);
 }
 
 template <bool PreserveNames>

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=216434&r1=216433&r2=216434&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Mon Aug 25 21:29:59 2014
@@ -1472,10 +1472,19 @@ llvm::Value *ItaniumCXXABI::InitializeAr
                                                  CookieOffset.getQuantity());
 
   // Write the number of elements into the appropriate slot.
-  llvm::Value *NumElementsPtr
-    = CGF.Builder.CreateBitCast(CookiePtr,
-                                CGF.ConvertType(SizeTy)->getPointerTo(AS));
-  CGF.Builder.CreateStore(NumElements, NumElementsPtr);
+  llvm::Type *NumElementsTy = CGF.ConvertType(SizeTy)->getPointerTo(AS);
+  llvm::Value *NumElementsPtr =
+      CGF.Builder.CreateBitCast(CookiePtr, NumElementsTy);
+  llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr);
+  if (CGM.getLangOpts().Sanitize.Address &&
+      expr->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
+    CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI);
+    llvm::FunctionType *FTy =
+        llvm::FunctionType::get(CGM.VoidTy, NumElementsTy, false);
+    llvm::Constant *F =
+        CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie");
+    CGF.Builder.CreateCall(F, NumElementsPtr);
+  }
 
   // Finally, compute a pointer to the actual data buffer by skipping
   // over the cookie completely.
@@ -1498,7 +1507,10 @@ llvm::Value *ItaniumCXXABI::readArrayCoo
   unsigned AS = allocPtr->getType()->getPointerAddressSpace();
   numElementsPtr = 
     CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS));
-  return CGF.Builder.CreateLoad(numElementsPtr);
+  llvm::Instruction *LI = CGF.Builder.CreateLoad(numElementsPtr);
+  if (CGM.getLangOpts().Sanitize.Address)
+    CGM.getSanitizerMetadata()->disableSanitizerForInstruction(LI);
+  return LI;
 }
 
 CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {

Modified: cfe/trunk/lib/CodeGen/SanitizerMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/SanitizerMetadata.cpp?rev=216434&r1=216433&r2=216434&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/SanitizerMetadata.cpp (original)
+++ cfe/trunk/lib/CodeGen/SanitizerMetadata.cpp Mon Aug 25 21:29:59 2014
@@ -67,6 +67,12 @@ void SanitizerMetadata::disableSanitizer
     reportGlobalToASan(GV, SourceLocation(), "", false, true);
 }
 
+void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) {
+  I->setMetadata(
+      CGM.getModule().getMDKindID("nosanitize"),
+      llvm::MDNode::get(CGM.getLLVMContext(), ArrayRef<llvm::Value *>()));
+}
+
 llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) {
   PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc);
   if (!PLoc.isValid())

Modified: cfe/trunk/lib/CodeGen/SanitizerMetadata.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/SanitizerMetadata.h?rev=216434&r1=216433&r2=216434&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/SanitizerMetadata.h (original)
+++ cfe/trunk/lib/CodeGen/SanitizerMetadata.h Mon Aug 25 21:29:59 2014
@@ -18,6 +18,7 @@
 
 namespace llvm {
 class GlobalVariable;
+class Instruction;
 class MDNode;
 }
 
@@ -41,6 +42,7 @@ public:
                           StringRef Name, bool IsDynInit = false,
                           bool IsBlacklisted = false);
   void disableSanitizerForGlobal(llvm::GlobalVariable *GV);
+  void disableSanitizerForInstruction(llvm::Instruction *I);
 private:
   llvm::MDNode *getLocationMetadata(SourceLocation Loc);
 };

Added: cfe/trunk/test/CodeGen/address-sanitizer-and-array-cookie.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/address-sanitizer-and-array-cookie.cpp?rev=216434&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/address-sanitizer-and-array-cookie.cpp (added)
+++ cfe/trunk/test/CodeGen/address-sanitizer-and-array-cookie.cpp Mon Aug 25 21:29:59 2014
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - %s | FileCheck %s -check-prefix=PLAIN
+// RUN: %clang_cc1 -triple x86_64-gnu-linux -emit-llvm -o - -fsanitize=address %s | FileCheck %s -check-prefix=ASAN
+
+typedef __typeof__(sizeof(0)) size_t;
+namespace std {
+  struct nothrow_t {};
+  std::nothrow_t nothrow;
+}
+void *operator new[](size_t, const std::nothrow_t &) throw();
+void *operator new[](size_t, char *);
+
+struct C {
+  int x;
+  ~C();
+};
+
+C *CallNew() {
+  return new C[10];
+}
+// PLAIN-LABEL: CallNew
+// PLAIN-NOT: nosanitize
+// PLAIN-NOT: __asan_poison_cxx_array_cookie
+// ASAN-LABEL: CallNew
+// ASAN: store{{.*}}nosanitize
+// ASAN-NOT: nosanitize
+// ASAN: call void @__asan_poison_cxx_array_cookie
+
+C *CallNewNoThrow() {
+  return new (std::nothrow) C[10];
+}
+// PLAIN-LABEL: CallNewNoThrow
+// PLAIN-NOT: nosanitize
+// PLAIN-NOT: __asan_poison_cxx_array_cookie
+// ASAN-LABEL: CallNewNoThrow
+// ASAN: store{{.*}}nosanitize
+// ASAN-NOT: nosanitize
+// ASAN: call void @__asan_poison_cxx_array_cookie
+
+void CallDelete(C *c) {
+  delete [] c;
+}
+
+// PLAIN-LABEL: CallDelete
+// PLAIN-NOT: nosanitize
+// ASAN-LABEL: CallDelete
+// ASAN: load{{.*}}!nosanitize
+// ASAN-NOT: nosanitize
+
+char Buffer[20];
+C *CallPlacementNew() {
+  return new (Buffer) C[20];
+}
+// ASAN-LABEL: CallPlacementNew
+// ASAN-NOT: __asan_poison_cxx_array_cookie





More information about the cfe-commits mailing list