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(bar); // static_cast on the null pointer value. + return; +}