Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -1683,11 +1683,8 @@ 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())); - } + if (IsSanitizerScope) + CGM.getSanitizerMetadata()->disableSanitizerForInstruction(I); } template Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -1473,10 +1473,19 @@ 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. @@ -1499,7 +1508,10 @@ 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) { Index: lib/CodeGen/SanitizerMetadata.h =================================================================== --- lib/CodeGen/SanitizerMetadata.h +++ lib/CodeGen/SanitizerMetadata.h @@ -18,6 +18,7 @@ namespace llvm { class GlobalVariable; +class Instruction; class MDNode; } @@ -41,6 +42,7 @@ StringRef Name, bool IsDynInit = false, bool IsBlacklisted = false); void disableSanitizerForGlobal(llvm::GlobalVariable *GV); + void disableSanitizerForInstruction(llvm::Instruction *I); private: llvm::MDNode *getLocationMetadata(SourceLocation Loc); }; Index: lib/CodeGen/SanitizerMetadata.cpp =================================================================== --- lib/CodeGen/SanitizerMetadata.cpp +++ lib/CodeGen/SanitizerMetadata.cpp @@ -67,6 +67,12 @@ reportGlobalToASan(GV, SourceLocation(), "", false, true); } +void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) { + I->setMetadata( + CGM.getModule().getMDKindID("nosanitize"), + llvm::MDNode::get(CGM.getLLVMContext(), ArrayRef())); +} + llvm::MDNode *SanitizerMetadata::getLocationMetadata(SourceLocation Loc) { PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc); if (!PLoc.isValid()) Index: test/CodeGen/address-sanitizer-and-array-cookie.cpp =================================================================== --- /dev/null +++ test/CodeGen/address-sanitizer-and-array-cookie.cpp @@ -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