Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -655,6 +655,9 @@ // and set IsWrite/Alignment. Otherwise return NULL. static Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite, unsigned *Alignment) { + // Skip memory accesses inserted by another instrumentation. + if (I->getMetadata("nosanitize")) + return nullptr; if (LoadInst *LI = dyn_cast(I)) { if (!ClInstrumentReads) return nullptr; *IsWrite = false; Index: test/Instrumentation/AddressSanitizer/ubsan.ll =================================================================== --- /dev/null +++ test/Instrumentation/AddressSanitizer/ubsan.ll @@ -0,0 +1,52 @@ +; ASan shouldn't instrument code added by UBSan. + +; RUN: opt < %s -asan -asan-module -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-unknown-linux-gnu" + +%struct.A = type { i32 (...)** } +declare void @__ubsan_handle_dynamic_type_cache_miss(i8*, i64, i64) uwtable +@__ubsan_vptr_type_cache = external global [128 x i64] +@.src = private unnamed_addr constant [19 x i8] c"tmp/ubsan/vptr.cpp\00", align 1 +@0 = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'A'\00" } +@_ZTI1A = external constant i8* +@1 = private unnamed_addr global { { [19 x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { { [19 x i8]*, i32, i32 } { [19 x i8]* @.src, i32 2, i32 18 }, { i16, i16, [4 x i8] }* @0, i8* bitcast (i8** @_ZTI1A to i8*), i8 4 } + +define void @_Z3BarP1A(%struct.A* %a) uwtable sanitize_address { +; CHECK-LABEL: define void @_Z3BarP1A +entry: + %0 = bitcast %struct.A* %a to void (%struct.A*)*** + %vtable = load void (%struct.A*)*** %0, align 8 +; CHECK: __asan_report_load8 + %1 = load void (%struct.A*)** %vtable, align 8 +; CHECK: __asan_report_load8 + %2 = ptrtoint void (%struct.A*)** %vtable to i64 + %3 = xor i64 %2, -303164226014115343, !nosanitize !0 + %4 = mul i64 %3, -7070675565921424023, !nosanitize !0 + %5 = lshr i64 %4, 47, !nosanitize !0 + %6 = xor i64 %4, %2, !nosanitize !0 + %7 = xor i64 %6, %5, !nosanitize !0 + %8 = mul i64 %7, -7070675565921424023, !nosanitize !0 + %9 = lshr i64 %8, 47, !nosanitize !0 + %10 = xor i64 %9, %8, !nosanitize !0 + %11 = mul i64 %10, -7070675565921424023, !nosanitize !0 + %12 = and i64 %11, 127, !nosanitize !0 + %13 = getelementptr inbounds [128 x i64]* @__ubsan_vptr_type_cache, i64 0, i64 %12, !nosanitize !0 +; CHECK-NOT: __asan_report_load8 + %14 = load i64* %13, align 8, !nosanitize !0 + %15 = icmp eq i64 %14, %11, !nosanitize !0 + br i1 %15, label %cont, label %handler.dynamic_type_cache_miss, !nosanitize !0 + +handler.dynamic_type_cache_miss: ; preds = %entry + %16 = ptrtoint %struct.A* %a to i64, !nosanitize !0 + tail call void @__ubsan_handle_dynamic_type_cache_miss(i8* bitcast ({ { [19 x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 }* @1 to i8*), i64 %16, i64 %11) #2, !nosanitize !0 + br label %cont, !nosanitize !0 + +cont: ; preds = %handler.dynamic_type_cache_miss, %entry + tail call void %1(%struct.A* %a) +; CHECK: ret void + ret void +} + +!0 = metadata !{} Index: tools/clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- tools/clang/lib/CodeGen/CGBuiltin.cpp +++ tools/clang/lib/CodeGen/CGBuiltin.cpp @@ -447,11 +447,12 @@ return RValue::get(Builder.CreateCall(F)); } case Builtin::BI__builtin_unreachable: { - if (SanOpts->Unreachable) + if (SanOpts->Unreachable) { + SanitizerScope SanScope(this); EmitCheck(Builder.getFalse(), "builtin_unreachable", EmitCheckSourceLocation(E->getExprLoc()), ArrayRef(), CRK_Unrecoverable); - else + } else Builder.CreateUnreachable(); // We do need to preserve an insertion point. Index: tools/clang/lib/CodeGen/CGExpr.cpp =================================================================== --- tools/clang/lib/CodeGen/CGExpr.cpp +++ tools/clang/lib/CodeGen/CGExpr.cpp @@ -458,6 +458,8 @@ if (Address->getType()->getPointerAddressSpace()) return; + SanitizerScope SanScope(this); + llvm::Value *Cond = nullptr; llvm::BasicBlock *Done = nullptr; @@ -654,6 +656,7 @@ bool Accessed) { assert(SanOpts->ArrayBounds && "should not be called unless adding bounds checks"); + SanitizerScope SanScope(this); QualType IndexedType; llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType); @@ -1129,6 +1132,7 @@ if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || (SanOpts->Enum && Ty->getAs())) { + SanitizerScope SanScope(this); llvm::APInt Min, End; if (getRangeForType(*this, Ty, Min, End, true)) { --End; @@ -2183,6 +2187,7 @@ ArrayRef DynamicArgs, CheckRecoverableKind RecoverKind) { assert(SanOpts != &SanitizerOptions::Disabled); + assert(IsSanitizerScope); if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) { assert (RecoverKind != CRK_AlwaysRecoverable && @@ -3231,6 +3236,7 @@ (!TargetDecl || !isa(TargetDecl))) { if (llvm::Constant *PrefixSig = CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { + SanitizerScope SanScope(this); llvm::Constant *FTRTTIConst = CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true); llvm::Type *PrefixStructTyElems[] = { Index: tools/clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- tools/clang/lib/CodeGen/CGExprScalar.cpp +++ tools/clang/lib/CodeGen/CGExprScalar.cpp @@ -554,6 +554,7 @@ Value *Src, QualType SrcType, QualType DstType, llvm::Type *DstTy) { + CodeGenFunction::SanitizerScope SanScope(&CGF); using llvm::APFloat; using llvm::APSInt; @@ -835,6 +836,7 @@ /// might actually be a unary increment which has been lowered to a binary /// operation). The check passes if \p Check, which is an \c i1, is \c true. void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) { + assert(CGF.IsSanitizerScope); StringRef CheckName; SmallVector StaticData; SmallVector DynamicData; @@ -2146,15 +2148,18 @@ } Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { - if ((CGF.SanOpts->IntegerDivideByZero || - CGF.SanOpts->SignedIntegerOverflow) && - Ops.Ty->isIntegerType()) { - llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); - } else if (CGF.SanOpts->FloatDivideByZero && - Ops.Ty->isRealFloatingType()) { - llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops); + { + CodeGenFunction::SanitizerScope SanScope(&CGF); + if ((CGF.SanOpts->IntegerDivideByZero || + CGF.SanOpts->SignedIntegerOverflow) && + Ops.Ty->isIntegerType()) { + llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); + EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); + } else if (CGF.SanOpts->FloatDivideByZero && + Ops.Ty->isRealFloatingType()) { + llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); + EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops); + } } if (Ops.LHS->getType()->isFPOrFPVectorTy()) { @@ -2178,6 +2183,7 @@ Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) { // Rem in C can't be a floating point type: C99 6.5.5p2. if (CGF.SanOpts->IntegerDivideByZero) { + CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); if (Ops.Ty->isIntegerType()) @@ -2235,9 +2241,10 @@ if (handlerName->empty()) { // If the signed-integer-overflow sanitizer is enabled, emit a call to its // runtime. Otherwise, this is a -ftrapv check, so just emit a trap. - if (!isSigned || CGF.SanOpts->SignedIntegerOverflow) + if (!isSigned || CGF.SanOpts->SignedIntegerOverflow) { + CodeGenFunction::SanitizerScope SanScope(&CGF); EmitBinOpCheck(Builder.CreateNot(overflow), Ops); - else + } else CGF.EmitTrapCheck(Builder.CreateNot(overflow)); return result; } @@ -2589,6 +2596,7 @@ if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL && isa(Ops.LHS->getType())) { + CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS); llvm::Value *Valid = Builder.CreateICmpULE(RHS, WidthMinusOne); @@ -2640,8 +2648,10 @@ RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL && - isa(Ops.LHS->getType())) + isa(Ops.LHS->getType())) { + CodeGenFunction::SanitizerScope SanScope(&CGF); EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops); + } // OpenCL 6.3j: shift values are effectively % word size of LHS. if (CGF.getLangOpts().OpenCL) Index: tools/clang/lib/CodeGen/CodeGenFunction.h =================================================================== --- tools/clang/lib/CodeGen/CodeGenFunction.h +++ tools/clang/lib/CodeGen/CodeGenFunction.h @@ -247,6 +247,17 @@ /// \brief Sanitizer options to use for this function. const SanitizerOptions *SanOpts; + /// \brief True if CodeGen currently emits code implementing sanitizer checks. + bool IsSanitizerScope; + + /// \brief RAII object to set/unset CodeGenFunction::IsSanitizerScope. + class SanitizerScope { + CodeGenFunction *CGF; + public: + SanitizerScope(CodeGenFunction *CGF); + ~SanitizerScope(); + }; + /// In ARC, whether we should autorelease the return value. bool AutoreleaseResult; Index: tools/clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ tools/clang/lib/CodeGen/CodeGenFunction.cpp @@ -36,8 +36,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm.getModule().getContext(), llvm::ConstantFolder(), - CGBuilderInserterTy(this)), CapturedStmtInfo(nullptr), - SanOpts(&CGM.getLangOpts().Sanitize), AutoreleaseResult(false), BlockInfo(nullptr), + CGBuilderInserterTy(this)), + CapturedStmtInfo(nullptr), SanOpts(&CGM.getLangOpts().Sanitize), + IsSanitizerScope(false), AutoreleaseResult(false), BlockInfo(nullptr), BlockPointer(nullptr), LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), @@ -843,11 +844,12 @@ // function call is used by the caller, the behavior is undefined. if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) { - if (SanOpts->Return) + if (SanOpts->Return) { + SanitizerScope SanScope(this); EmitCheck(Builder.getFalse(), "missing_return", EmitCheckSourceLocation(FD->getLocation()), ArrayRef(), CRK_Unrecoverable); - else if (CGM.getCodeGenOpts().OptimizationLevel == 0) + } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap)); Builder.CreateUnreachable(); Builder.ClearInsertionPoint(); @@ -1499,6 +1501,7 @@ // greater than zero. if (SanOpts->VLABound && size->getType()->isSignedIntegerType()) { + SanitizerScope SanScope(this); llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType()); llvm::Constant *StaticArgs[] = { EmitCheckSourceLocation(size->getLocStart()), @@ -1637,11 +1640,26 @@ CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { } +CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF) + : CGF(CGF) { + assert(!CGF->IsSanitizerScope); + CGF->IsSanitizerScope = true; +} + +CodeGenFunction::SanitizerScope::~SanitizerScope() { + CGF->IsSanitizerScope = false; +} + void CodeGenFunction::InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, 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())); + } } template Index: tools/clang/test/CodeGen/catch-undef-behavior.c =================================================================== --- tools/clang/test/CodeGen/catch-undef-behavior.c +++ tools/clang/test/CodeGen/catch-undef-behavior.c @@ -49,7 +49,7 @@ // CHECK-TRAP-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0 // CHECK: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] - // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]] + // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize // CHECK-TRAP: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] // CHECK-TRAP-NEXT: br i1 %[[OK]], {{.*}} @@ -311,7 +311,7 @@ // CHECK: %[[LE:.*]] = fcmp olt x86_fp80 %[[F]], 0xK401E8000000000000000 // CHECK: and i1 %[[GE]], %[[LE]] - // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]] + // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]], !nosanitize // CHECK: %[[ARG:.*]] = ptrtoint x86_fp80* %[[ALLOCA]] to i64 // CHECK: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]]