[clang] c54597b - [ubsan] Add support for -fsanitize=nullability-* suppressions

Vedant Kumar via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 28 14:35:26 PST 2020


Author: Vedant Kumar
Date: 2020-02-28T14:30:40-08:00
New Revision: c54597b99d6f6ea51616168a0c2ff3850c3869eb

URL: https://github.com/llvm/llvm-project/commit/c54597b99d6f6ea51616168a0c2ff3850c3869eb
DIFF: https://github.com/llvm/llvm-project/commit/c54597b99d6f6ea51616168a0c2ff3850c3869eb.diff

LOG: [ubsan] Add support for -fsanitize=nullability-* suppressions

rdar://59402904

Added: 
    

Modified: 
    clang/lib/CodeGen/CodeGenFunction.h
    compiler-rt/lib/ubsan/ubsan_checks.inc
    compiler-rt/lib/ubsan/ubsan_handlers.cpp
    compiler-rt/test/ubsan/TestCases/Misc/nullability.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index c3b2ae0fda09..14111713ccac 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2704,7 +2704,8 @@ class CodeGenFunction : public CodeGenTypeCache {
   Address EmitCXXUuidofExpr(const CXXUuidofExpr *E);
 
   /// Situations in which we might emit a check for the suitability of a
-  ///        pointer or glvalue.
+  /// pointer or glvalue. Needs to be kept in sync with ubsan_handlers.cpp in
+  /// compiler-rt.
   enum TypeCheckKind {
     /// Checking the operand of a load. Must be suitably sized and aligned.
     TCK_Load,

diff  --git a/compiler-rt/lib/ubsan/ubsan_checks.inc b/compiler-rt/lib/ubsan/ubsan_checks.inc
index 33a8dfcde026..2c1529a7d92c 100644
--- a/compiler-rt/lib/ubsan/ubsan_checks.inc
+++ b/compiler-rt/lib/ubsan/ubsan_checks.inc
@@ -18,6 +18,8 @@
 
 UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined")
 UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null")
+UBSAN_CHECK(NullPointerUseWithNullability, "null-pointer-use",
+            "nullability-assign")
 UBSAN_CHECK(NullptrWithOffset, "nullptr-with-offset", "pointer-overflow")
 UBSAN_CHECK(NullptrWithNonZeroOffset, "nullptr-with-nonzero-offset",
             "pointer-overflow")
@@ -59,6 +61,10 @@ UBSAN_CHECK(InvalidEnumLoad, "invalid-enum-load", "enum")
 UBSAN_CHECK(FunctionTypeMismatch, "function-type-mismatch", "function")
 UBSAN_CHECK(InvalidNullReturn, "invalid-null-return",
             "returns-nonnull-attribute")
+UBSAN_CHECK(InvalidNullReturnWithNullability, "invalid-null-return",
+            "nullability-return")
 UBSAN_CHECK(InvalidNullArgument, "invalid-null-argument", "nonnull-attribute")
+UBSAN_CHECK(InvalidNullArgumentWithNullability, "invalid-null-argument",
+            "nullability-arg")
 UBSAN_CHECK(DynamicTypeMismatch, "dynamic-type-mismatch", "vptr")
 UBSAN_CHECK(CFIBadType, "cfi-bad-type", "cfi")

diff  --git a/compiler-rt/lib/ubsan/ubsan_handlers.cpp b/compiler-rt/lib/ubsan/ubsan_handlers.cpp
index 3f9da75a12a8..7f6a46fb6cf0 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_handlers.cpp
@@ -36,6 +36,45 @@ bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
   return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
 }
 
+/// Situations in which we might emit a check for the suitability of a
+/// pointer or glvalue. Needs to be kept in sync with CodeGenFunction.h in
+/// clang.
+enum TypeCheckKind {
+  /// Checking the operand of a load. Must be suitably sized and aligned.
+  TCK_Load,
+  /// Checking the destination of a store. Must be suitably sized and aligned.
+  TCK_Store,
+  /// Checking the bound value in a reference binding. Must be suitably sized
+  /// and aligned, but is not required to refer to an object (until the
+  /// reference is used), per core issue 453.
+  TCK_ReferenceBinding,
+  /// Checking the object expression in a non-static data member access. Must
+  /// be an object within its lifetime.
+  TCK_MemberAccess,
+  /// Checking the 'this' pointer for a call to a non-static member function.
+  /// Must be an object within its lifetime.
+  TCK_MemberCall,
+  /// Checking the 'this' pointer for a constructor call.
+  TCK_ConstructorCall,
+  /// Checking the operand of a static_cast to a derived pointer type. Must be
+  /// null or an object within its lifetime.
+  TCK_DowncastPointer,
+  /// Checking the operand of a static_cast to a derived reference type. Must
+  /// be an object within its lifetime.
+  TCK_DowncastReference,
+  /// Checking the operand of a cast to a base object. Must be suitably sized
+  /// and aligned.
+  TCK_Upcast,
+  /// Checking the operand of a cast to a virtual base object. Must be an
+  /// object within its lifetime.
+  TCK_UpcastToVirtualBase,
+  /// Checking the value assigned to a _Nonnull pointer. Must not be null.
+  TCK_NonnullAssign,
+  /// Checking the operand of a dynamic_cast or a typeid expression.  Must be
+  /// null or an object within its lifetime.
+  TCK_DynamicOperation
+};
+
 const char *TypeCheckKinds[] = {
     "load of", "store to", "reference binding to", "member access within",
     "member call on", "constructor call on", "downcast of", "downcast of",
@@ -50,7 +89,9 @@ static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
   uptr Alignment = (uptr)1 << Data->LogAlignment;
   ErrorType ET;
   if (!Pointer)
-    ET = ErrorType::NullPointerUse;
+    ET = (Data->TypeCheckKind == TCK_NonnullAssign)
+             ? ErrorType::NullPointerUseWithNullability
+             : ErrorType::NullPointerUse;
   else if (Pointer & (Alignment - 1))
     ET = ErrorType::MisalignedPointerUse;
   else
@@ -71,6 +112,7 @@ static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
 
   switch (ET) {
   case ErrorType::NullPointerUse:
+  case ErrorType::NullPointerUseWithNullability:
     Diag(Loc, DL_Error, ET, "%0 null pointer of type %1")
         << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
     break;
@@ -604,7 +646,8 @@ static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
     UNREACHABLE("source location pointer is null!");
 
   SourceLocation Loc = LocPtr->acquire();
-  ErrorType ET = ErrorType::InvalidNullReturn;
+  ErrorType ET = IsAttr ? ErrorType::InvalidNullReturn
+                        : ErrorType::InvalidNullReturnWithNullability;
 
   if (ignoreReport(Loc, Opts, ET))
     return;
@@ -648,7 +691,8 @@ void __ubsan::__ubsan_handle_nullability_return_v1_abort(
 static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts,
                              bool IsAttr) {
   SourceLocation Loc = Data->Loc.acquire();
-  ErrorType ET = ErrorType::InvalidNullArgument;
+  ErrorType ET = IsAttr ? ErrorType::InvalidNullArgument
+                        : ErrorType::InvalidNullArgumentWithNullability;
 
   if (ignoreReport(Loc, Opts, ET))
     return;

diff  --git a/compiler-rt/test/ubsan/TestCases/Misc/nullability.c b/compiler-rt/test/ubsan/TestCases/Misc/nullability.c
index a6ddf0e2315b..94512ab4a408 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/nullability.c
+++ b/compiler-rt/test/ubsan/TestCases/Misc/nullability.c
@@ -2,6 +2,11 @@
 // RUN: %run %t foo 2>&1 | count 0
 // RUN: %run %t 2>&1 | FileCheck %s
 
+// RUN: echo "nullability-arg:nullability.c" > %t.supp
+// RUN: echo "nullability-return:nullability.c" >> %t.supp
+// RUN: echo "nullability-assign:nullability.c" >> %t.supp
+// RUN: UBSAN_OPTIONS=suppressions=%t.supp %run %t 2>&1 | count 0
+
 // CHECK: nullability.c:[[@LINE+2]]:41: runtime error: null pointer returned from function declared to never return null
 // CHECK-NEXT: nullability.c:[[@LINE+1]]:6: note: _Nonnull return type annotation specified here
 int *_Nonnull nonnull_retval1(int *p) { return p; }


        


More information about the cfe-commits mailing list