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; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits