[compiler-rt] c54597b - [ubsan] Add support for -fsanitize=nullability-* suppressions
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 28 14:35:25 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 llvm-commits
mailing list