From 34b1fd6aaaf7e31ddcf65437ba8e274fe79bb7d2 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Fri, 17 Feb 2017 23:22:59 +0000 Subject: Retry^2: [ubsan] Reduce null checking of C++ object pointers (PR27581) This patch teaches ubsan to insert exactly one null check for the 'this' pointer per method/lambda. Previously, given a load of a member variable from an instance method ('this->x'), ubsan would insert a null check for 'this', and another null check for '&this->x', before allowing the load to occur. Similarly, given a call to a method from another method bound to the same instance ('this->foo()'), ubsan would a redundant null check for 'this'. There is also a redundant null check in the case where the object pointer is a reference ('Ref.foo()'). This patch teaches ubsan to remove the redundant null checks identified above. Testing: check-clang, check-ubsan, and a stage2 ubsan build. I also compiled X86FastISel.cpp with -fsanitize=null using patched/unpatched clangs based on r293572. Here are the number of null checks emitted: ------------------------------------- | Setup | # of null checks | ------------------------------------- | unpatched, -O0 | 21767 | | patched, -O0 | 10758 | ------------------------------------- Changes since the initial commit: - Don't introduce any unintentional object-size or alignment checks. - Don't rely on IRGen of C labels in the test. Differential Revision: https://reviews.llvm.org/D29530 llvm-svn: 295515 --- clang/lib/CodeGen/CodeGenFunction.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp') diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 00d5b5f..1ebfd79 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -948,6 +948,15 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, // fast register allocator would be happier... CXXThisValue = CXXABIThisValue; } + + // Null-check the 'this' pointer once per function, if it's available. + if (CXXThisValue) { + SanitizerSet SkippedChecks; + SkippedChecks.set(SanitizerKind::Alignment, true); + SkippedChecks.set(SanitizerKind::ObjectSize, true); + EmitTypeCheck(TCK_Load, Loc, CXXThisValue, MD->getThisType(getContext()), + /*Alignment=*/CharUnits::Zero(), SkippedChecks); + } } // If any of the arguments have a variably modified type, make sure to -- cgit v1.1