r212770 - [UBSan] Introduce type-based blacklisting.
Alexey Samsonov
vonosmas at gmail.com
Thu Jul 10 15:34:20 PDT 2014
Author: samsonov
Date: Thu Jul 10 17:34:19 2014
New Revision: 212770
URL: http://llvm.org/viewvc/llvm-project?rev=212770&view=rev
Log:
[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!
Added:
cfe/trunk/test/CodeGen/ubsan-type-blacklist.cpp
Modified:
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/SanitizerBlacklist.cpp
cfe/trunk/lib/CodeGen/SanitizerBlacklist.h
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=212770&r1=212769&r2=212770&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jul 10 17:34:19 2014
@@ -544,44 +544,48 @@ void CodeGenFunction::EmitTypeCheck(Type
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) {
Modified: cfe/trunk/lib/CodeGen/SanitizerBlacklist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/SanitizerBlacklist.cpp?rev=212770&r1=212769&r2=212770&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/SanitizerBlacklist.cpp (original)
+++ cfe/trunk/lib/CodeGen/SanitizerBlacklist.cpp Thu Jul 10 17:34:19 2014
@@ -46,3 +46,7 @@ bool SanitizerBlacklist::isIn(const llvm
SCL->inSection("global", G.getName(), Category) ||
SCL->inSection("type", GetGlobalTypeString(G), Category);
}
+
+bool SanitizerBlacklist::isBlacklistedType(StringRef MangledTypeName) const {
+ return SCL->inSection("type", MangledTypeName);
+}
Modified: cfe/trunk/lib/CodeGen/SanitizerBlacklist.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/SanitizerBlacklist.h?rev=212770&r1=212769&r2=212770&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/SanitizerBlacklist.h (original)
+++ cfe/trunk/lib/CodeGen/SanitizerBlacklist.h Thu Jul 10 17:34:19 2014
@@ -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
Added: cfe/trunk/test/CodeGen/ubsan-type-blacklist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ubsan-type-blacklist.cpp?rev=212770&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/ubsan-type-blacklist.cpp (added)
+++ cfe/trunk/test/CodeGen/ubsan-type-blacklist.cpp Thu Jul 10 17:34:19 2014
@@ -0,0 +1,25 @@
+// Verify ubsan vptr does not check down-casts on blacklisted types.
+// RUN: echo "type:_ZTI3Foo" > %t-type.blacklist
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -fsanitize-blacklist=%t-type.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=TYPE
+
+// REQUIRES: shell
+
+class Bar {
+public:
+ virtual ~Bar() {}
+};
+class Foo : public Bar {};
+
+Bar bar;
+
+// DEFAULT: @_Z7checkmev
+// TYPE: @_Z7checkmev
+void checkme() {
+// DEFAULT: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}} (%class.Bar* @bar to
+// TYPE-NOT: @__ubsan_handle_dynamic_type_cache_miss
+ Foo* foo = static_cast<Foo*>(&bar); // down-casting
+// DEFAULT: ret void
+// TYPE: ret void
+ return;
+}
More information about the cfe-commits
mailing list