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