[PATCH] [UBsan] Skip -fsanitize=vptr instrumentations when the pointer value is null

Byoungyoung Lee byoungyoung at chromium.org
Tue Jul 15 11:33:47 PDT 2014


Expanded a comment, and added a testcase. I'm not sure whether the checks in the testcase would be enough, so please let me know if it doesn't.

http://reviews.llvm.org/D4412

Files:
  lib/CodeGen/CGExpr.cpp
  test/CodeGen/ubsan-vptr-null.cpp

Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -547,6 +547,26 @@
 
     // Blacklist based on the mangled type.
     if (!CGM.getSanitizerBlacklist().isBlacklistedType(Out.str())) {
+      llvm::BasicBlock *VptrNullBlock = nullptr;
+      llvm::BasicBlock *VptrNotNullBlock = nullptr;
+
+      // Skip vptr checks when the pointer value is null. A null pointer here is
+      // undefined behavior, but if -fsanitize=null is not enabled, we don't
+      // want to change the behavior of code in that case, so that the user
+      // doesn't have to fix all their null pointer bugs before they can find
+      // their type mismatch bugs (which are likely to be more serious). This is
+      // redundant if -fsanitize=null is used.
+      if (TCK_DowncastPointer && !SanOpts->Null) {
+        Cond = Builder.CreateICmpNE(
+          Address, llvm::Constant::getNullValue(Address->getType()));
+
+        VptrNullBlock = createBasicBlock("vptr_null");
+        VptrNotNullBlock = createBasicBlock("not.vptr_null");
+
+        Builder.CreateCondBr(Cond, VptrNotNullBlock, VptrNullBlock);
+        EmitBlock(VptrNotNullBlock);
+      }
+
       llvm::hash_code TypeHash = hash_value(Out.str());
 
       // Load the vptr, and compute hash_16_bytes(TypeHash, vptr).
@@ -585,6 +605,11 @@
       EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash),
                 "dynamic_type_cache_miss", StaticData, DynamicData,
                 CRK_AlwaysRecoverable);
+
+      if (VptrNullBlock) {
+        Builder.CreateBr(VptrNullBlock);
+        EmitBlock(VptrNullBlock);
+      }
     }
   }
 
Index: test/CodeGen/ubsan-vptr-null.cpp
===================================================================
--- test/CodeGen/ubsan-vptr-null.cpp
+++ test/CodeGen/ubsan-vptr-null.cpp
@@ -0,0 +1,20 @@
+// Verify ubsan vptr skip null pointer value cases.
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=vptr -emit-llvm %s -o - | FileCheck %s
+
+class Bar {
+public:
+  virtual ~Bar() {}
+};
+class Foo : public Bar {};
+
+// CHECK-LABEL: @_Z7checkmev
+void checkme() {
+  // CHECK: [[CMP_RES:%.*]] = icmp ne %class.Foo* %{{[0-9]+}}, null
+  // CHECK: br {{.*}} [[CMP_RES]], label %not.vptr_null, label %vptr_null
+  // CHECK-LABEL: cont
+  // CHECK: br label %vptr_null
+
+  Bar *bar = 0;
+  Foo* foo = static_cast<Foo*>(bar); // static_cast on the null pointer value.
+  return;
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4412.11458.patch
Type: text/x-patch
Size: 2475 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140715/c2db6977/attachment.bin>


More information about the cfe-commits mailing list