diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp | 66 |
1 files changed, 44 insertions, 22 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp index cd75da2..1d2b787 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp @@ -370,25 +370,25 @@ namespace { /// A visitor which checks whether an initializer uses 'this' in a /// way which requires the vtable to be properly set. - struct DynamicThisUseChecker : EvaluatedExprVisitor<DynamicThisUseChecker> { - typedef EvaluatedExprVisitor<DynamicThisUseChecker> super; + struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> { + typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super; bool UsesThis; - DynamicThisUseChecker(ASTContext &C) : super(C), UsesThis(false) {} + DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {} // Black-list all explicit and implicit references to 'this'. // // Do we need to worry about external references to 'this' derived // from arbitrary code? If so, then anything which runs arbitrary // external code might potentially access the vtable. - void VisitCXXThisExpr(CXXThisExpr *E) { UsesThis = true; } + void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; } }; } static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) { DynamicThisUseChecker Checker(C); - Checker.Visit(const_cast<Expr*>(Init)); + Checker.Visit(Init); return Checker.UsesThis; } @@ -2134,17 +2134,21 @@ LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) { } void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXMethodDecl *MD, - llvm::Value *VTable) { + llvm::Value *VTable, + CFITypeCheckKind TCK, + SourceLocation Loc) { const CXXRecordDecl *ClassDecl = MD->getParent(); if (!SanOpts.has(SanitizerKind::CFICastStrict)) ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl); - EmitVTablePtrCheck(ClassDecl, VTable); + EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc); } void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, llvm::Value *Derived, - bool MayBeNull) { + bool MayBeNull, + CFITypeCheckKind TCK, + SourceLocation Loc) { if (!getLangOpts().CPlusPlus) return; @@ -2184,7 +2188,7 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, } llvm::Value *VTable = GetVTablePtr(Derived, Int8PtrTy); - EmitVTablePtrCheck(ClassDecl, VTable); + EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc); if (MayBeNull) { Builder.CreateBr(ContBlock); @@ -2193,11 +2197,15 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, } void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, - llvm::Value *VTable) { + llvm::Value *VTable, + CFITypeCheckKind TCK, + SourceLocation Loc) { // FIXME: Add blacklisting scheme. if (RD->isInStdNamespace()) return; + SanitizerScope SanScope(this); + std::string OutName; llvm::raw_string_ostream Out(OutName); CGM.getCXXABI().getMangleContext().mangleCXXVTableBitSet(RD, Out); @@ -2205,20 +2213,34 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *BitSetName = llvm::MetadataAsValue::get( getLLVMContext(), llvm::MDString::get(getLLVMContext(), Out.str())); - llvm::Value *BitSetTest = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::bitset_test), - {Builder.CreateBitCast(VTable, CGM.Int8PtrTy), BitSetName}); + llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); + llvm::Value *BitSetTest = + Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test), + {CastedVTable, BitSetName}); - llvm::BasicBlock *ContBlock = createBasicBlock("vtable.check.cont"); - llvm::BasicBlock *TrapBlock = createBasicBlock("vtable.check.trap"); - - Builder.CreateCondBr(BitSetTest, ContBlock, TrapBlock); - - EmitBlock(TrapBlock); - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap), {}); - Builder.CreateUnreachable(); + SanitizerMask M; + switch (TCK) { + case CFITCK_VCall: + M = SanitizerKind::CFIVCall; + break; + case CFITCK_NVCall: + M = SanitizerKind::CFINVCall; + break; + case CFITCK_DerivedCast: + M = SanitizerKind::CFIDerivedCast; + break; + case CFITCK_UnrelatedCast: + M = SanitizerKind::CFIUnrelatedCast; + break; + } - EmitBlock(ContBlock); + llvm::Constant *StaticData[] = { + EmitCheckSourceLocation(Loc), + EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)), + llvm::ConstantInt::get(Int8Ty, TCK), + }; + EmitCheck(std::make_pair(BitSetTest, M), "cfi_bad_type", StaticData, + CastedVTable); } // FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do |