diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-13 21:18:23 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-13 21:18:23 +0000 |
| commit | 2c5868c334646d4cdc92589cea393a5012cdd813 (patch) | |
| tree | ac106767d283c9e5dc2c7204c7c179d48814faff /clang/lib/CodeGen/CGExpr.cpp | |
| parent | 6c95b97bf6fb2dc3ec1e36963742d952f5b3b30b (diff) | |
| download | bcm5719-llvm-2c5868c334646d4cdc92589cea393a5012cdd813.tar.gz bcm5719-llvm-2c5868c334646d4cdc92589cea393a5012cdd813.zip | |
ubsan: Add checking for invalid downcasts. Per [expr.static.cast]p2 and p11,
base-to-derived casts have undefined behavior if the object is not actually an
instance of the derived type.
llvm-svn: 175078
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 41518fb11bd..ba400b8a602 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -501,11 +501,22 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, return; llvm::Value *Cond = 0; + llvm::BasicBlock *Done = 0; if (SanOpts->Null) { // The glvalue must not be an empty glvalue. Cond = Builder.CreateICmpNE( Address, llvm::Constant::getNullValue(Address->getType())); + + if (TCK == TCK_DowncastPointer) { + // When performing a pointer downcast, it's OK if the value is null. + // Skip the remaining checks in that case. + Done = createBasicBlock("null"); + llvm::BasicBlock *Rest = createBasicBlock("not.null"); + Builder.CreateCondBr(Cond, Rest, Done); + EmitBlock(Rest); + Cond = 0; + } } if (SanOpts->ObjectSize && !Ty->isIncompleteType()) { @@ -561,7 +572,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, // or call a non-static member function CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); if (SanOpts->Vptr && - (TCK == TCK_MemberAccess || TCK == TCK_MemberCall) && + (TCK == TCK_MemberAccess || TCK == TCK_MemberCall || + TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference) && RD && RD->hasDefinition() && RD->isDynamicClass()) { // Compute a hash of the mangled name of the type. // @@ -611,6 +623,11 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, "dynamic_type_cache_miss", StaticData, DynamicData, CRK_AlwaysRecoverable); } + + if (Done) { + Builder.CreateBr(Done); + EmitBlock(Done); + } } @@ -2638,7 +2655,13 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { cast<CXXRecordDecl>(DerivedClassTy->getDecl()); LValue LV = EmitLValue(E->getSubExpr()); - + + // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is + // performed and the object is not of the derived type. + if (SanitizePerformTypeCheck) + EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), + LV.getAddress(), E->getType()); + // Perform the base-to-derived conversion llvm::Value *Derived = GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl, |

