diff options
author | Alexey Samsonov <vonosmas@gmail.com> | 2014-07-10 22:34:19 +0000 |
---|---|---|
committer | Alexey Samsonov <vonosmas@gmail.com> | 2014-07-10 22:34:19 +0000 |
commit | 848560125db5a2d8924dfbfc19adb0234d080c13 (patch) | |
tree | ae6017631bf4fdd1b1a842bcb4df9fa15156d674 /clang/lib/CodeGen | |
parent | f34b454219d0c6e0bc18904136d3b80bd6691be3 (diff) | |
download | bcm5719-llvm-848560125db5a2d8924dfbfc19adb0234d080c13.tar.gz bcm5719-llvm-848560125db5a2d8924dfbfc19adb0234d080c13.zip |
[UBSan] Introduce type-based blacklisting.
Teach UBSan vptr checker to ignore technically invalud down-casts on
blacklisted types.
Based on http://reviews.llvm.org/D4407 by Byoungyoung Lee!
llvm-svn: 212770
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 80 | ||||
-rw-r--r-- | clang/lib/CodeGen/SanitizerBlacklist.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/SanitizerBlacklist.h | 1 |
3 files changed, 47 insertions, 38 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index c99e669f6ff..a43cf30da73 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -544,44 +544,48 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::raw_svector_ostream Out(MangledName); CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty.getUnqualifiedType(), Out); - llvm::hash_code TypeHash = hash_value(Out.str()); - - // Load the vptr, and compute hash_16_bytes(TypeHash, vptr). - llvm::Value *Low = llvm::ConstantInt::get(Int64Ty, TypeHash); - llvm::Type *VPtrTy = llvm::PointerType::get(IntPtrTy, 0); - llvm::Value *VPtrAddr = Builder.CreateBitCast(Address, VPtrTy); - llvm::Value *VPtrVal = Builder.CreateLoad(VPtrAddr); - llvm::Value *High = Builder.CreateZExt(VPtrVal, Int64Ty); - - llvm::Value *Hash = emitHash16Bytes(Builder, Low, High); - Hash = Builder.CreateTrunc(Hash, IntPtrTy); - - // Look the hash up in our cache. - const int CacheSize = 128; - llvm::Type *HashTable = llvm::ArrayType::get(IntPtrTy, CacheSize); - llvm::Value *Cache = CGM.CreateRuntimeVariable(HashTable, - "__ubsan_vptr_type_cache"); - llvm::Value *Slot = Builder.CreateAnd(Hash, - llvm::ConstantInt::get(IntPtrTy, - CacheSize-1)); - llvm::Value *Indices[] = { Builder.getInt32(0), Slot }; - llvm::Value *CacheVal = - Builder.CreateLoad(Builder.CreateInBoundsGEP(Cache, Indices)); - - // If the hash isn't in the cache, call a runtime handler to perform the - // hard work of checking whether the vptr is for an object of the right - // type. This will either fill in the cache and return, or produce a - // diagnostic. - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(Loc), - EmitCheckTypeDescriptor(Ty), - CGM.GetAddrOfRTTIDescriptor(Ty.getUnqualifiedType()), - llvm::ConstantInt::get(Int8Ty, TCK) - }; - llvm::Value *DynamicData[] = { Address, Hash }; - EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), - "dynamic_type_cache_miss", StaticData, DynamicData, - CRK_AlwaysRecoverable); + + // Blacklist based on the mangled type. + if (!CGM.getSanitizerBlacklist().isBlacklistedType(Out.str())) { + llvm::hash_code TypeHash = hash_value(Out.str()); + + // Load the vptr, and compute hash_16_bytes(TypeHash, vptr). + llvm::Value *Low = llvm::ConstantInt::get(Int64Ty, TypeHash); + llvm::Type *VPtrTy = llvm::PointerType::get(IntPtrTy, 0); + llvm::Value *VPtrAddr = Builder.CreateBitCast(Address, VPtrTy); + llvm::Value *VPtrVal = Builder.CreateLoad(VPtrAddr); + llvm::Value *High = Builder.CreateZExt(VPtrVal, Int64Ty); + + llvm::Value *Hash = emitHash16Bytes(Builder, Low, High); + Hash = Builder.CreateTrunc(Hash, IntPtrTy); + + // Look the hash up in our cache. + const int CacheSize = 128; + llvm::Type *HashTable = llvm::ArrayType::get(IntPtrTy, CacheSize); + llvm::Value *Cache = CGM.CreateRuntimeVariable(HashTable, + "__ubsan_vptr_type_cache"); + llvm::Value *Slot = Builder.CreateAnd(Hash, + llvm::ConstantInt::get(IntPtrTy, + CacheSize-1)); + llvm::Value *Indices[] = { Builder.getInt32(0), Slot }; + llvm::Value *CacheVal = + Builder.CreateLoad(Builder.CreateInBoundsGEP(Cache, Indices)); + + // If the hash isn't in the cache, call a runtime handler to perform the + // hard work of checking whether the vptr is for an object of the right + // type. This will either fill in the cache and return, or produce a + // diagnostic. + llvm::Constant *StaticData[] = { + EmitCheckSourceLocation(Loc), + EmitCheckTypeDescriptor(Ty), + CGM.GetAddrOfRTTIDescriptor(Ty.getUnqualifiedType()), + llvm::ConstantInt::get(Int8Ty, TCK) + }; + llvm::Value *DynamicData[] = { Address, Hash }; + EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), + "dynamic_type_cache_miss", StaticData, DynamicData, + CRK_AlwaysRecoverable); + } } if (Done) { diff --git a/clang/lib/CodeGen/SanitizerBlacklist.cpp b/clang/lib/CodeGen/SanitizerBlacklist.cpp index 60bdbe1d92e..9f1ddc8e7d7 100644 --- a/clang/lib/CodeGen/SanitizerBlacklist.cpp +++ b/clang/lib/CodeGen/SanitizerBlacklist.cpp @@ -46,3 +46,7 @@ bool SanitizerBlacklist::isIn(const llvm::GlobalVariable &G, SCL->inSection("global", G.getName(), Category) || SCL->inSection("type", GetGlobalTypeString(G), Category); } + +bool SanitizerBlacklist::isBlacklistedType(StringRef MangledTypeName) const { + return SCL->inSection("type", MangledTypeName); +} diff --git a/clang/lib/CodeGen/SanitizerBlacklist.h b/clang/lib/CodeGen/SanitizerBlacklist.h index b8c283ccf4f..659441dfe34 100644 --- a/clang/lib/CodeGen/SanitizerBlacklist.h +++ b/clang/lib/CodeGen/SanitizerBlacklist.h @@ -38,6 +38,7 @@ public: bool isIn(const llvm::Function &F) const; bool isIn(const llvm::GlobalVariable &G, const StringRef Category = StringRef()) const; + bool isBlacklistedType(StringRef MangledTypeName) const; }; } // end namespace CodeGen } // end namespace clang |