Skip to content

Commit c54597b

Browse files
committed
[ubsan] Add support for -fsanitize=nullability-* suppressions
rdar://59402904
1 parent 0368b42 commit c54597b

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2704,7 +2704,8 @@ class CodeGenFunction : public CodeGenTypeCache {
27042704
Address EmitCXXUuidofExpr(const CXXUuidofExpr *E);
27052705

27062706
/// Situations in which we might emit a check for the suitability of a
2707-
/// pointer or glvalue.
2707+
/// pointer or glvalue. Needs to be kept in sync with ubsan_handlers.cpp in
2708+
/// compiler-rt.
27082709
enum TypeCheckKind {
27092710
/// Checking the operand of a load. Must be suitably sized and aligned.
27102711
TCK_Load,

compiler-rt/lib/ubsan/ubsan_checks.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined")
2020
UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null")
21+
UBSAN_CHECK(NullPointerUseWithNullability, "null-pointer-use",
22+
"nullability-assign")
2123
UBSAN_CHECK(NullptrWithOffset, "nullptr-with-offset", "pointer-overflow")
2224
UBSAN_CHECK(NullptrWithNonZeroOffset, "nullptr-with-nonzero-offset",
2325
"pointer-overflow")
@@ -59,6 +61,10 @@ UBSAN_CHECK(InvalidEnumLoad, "invalid-enum-load", "enum")
5961
UBSAN_CHECK(FunctionTypeMismatch, "function-type-mismatch", "function")
6062
UBSAN_CHECK(InvalidNullReturn, "invalid-null-return",
6163
"returns-nonnull-attribute")
64+
UBSAN_CHECK(InvalidNullReturnWithNullability, "invalid-null-return",
65+
"nullability-return")
6266
UBSAN_CHECK(InvalidNullArgument, "invalid-null-argument", "nonnull-attribute")
67+
UBSAN_CHECK(InvalidNullArgumentWithNullability, "invalid-null-argument",
68+
"nullability-arg")
6369
UBSAN_CHECK(DynamicTypeMismatch, "dynamic-type-mismatch", "vptr")
6470
UBSAN_CHECK(CFIBadType, "cfi-bad-type", "cfi")

compiler-rt/lib/ubsan/ubsan_handlers.cpp

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,45 @@ bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
3636
return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
3737
}
3838

39+
/// Situations in which we might emit a check for the suitability of a
40+
/// pointer or glvalue. Needs to be kept in sync with CodeGenFunction.h in
41+
/// clang.
42+
enum TypeCheckKind {
43+
/// Checking the operand of a load. Must be suitably sized and aligned.
44+
TCK_Load,
45+
/// Checking the destination of a store. Must be suitably sized and aligned.
46+
TCK_Store,
47+
/// Checking the bound value in a reference binding. Must be suitably sized
48+
/// and aligned, but is not required to refer to an object (until the
49+
/// reference is used), per core issue 453.
50+
TCK_ReferenceBinding,
51+
/// Checking the object expression in a non-static data member access. Must
52+
/// be an object within its lifetime.
53+
TCK_MemberAccess,
54+
/// Checking the 'this' pointer for a call to a non-static member function.
55+
/// Must be an object within its lifetime.
56+
TCK_MemberCall,
57+
/// Checking the 'this' pointer for a constructor call.
58+
TCK_ConstructorCall,
59+
/// Checking the operand of a static_cast to a derived pointer type. Must be
60+
/// null or an object within its lifetime.
61+
TCK_DowncastPointer,
62+
/// Checking the operand of a static_cast to a derived reference type. Must
63+
/// be an object within its lifetime.
64+
TCK_DowncastReference,
65+
/// Checking the operand of a cast to a base object. Must be suitably sized
66+
/// and aligned.
67+
TCK_Upcast,
68+
/// Checking the operand of a cast to a virtual base object. Must be an
69+
/// object within its lifetime.
70+
TCK_UpcastToVirtualBase,
71+
/// Checking the value assigned to a _Nonnull pointer. Must not be null.
72+
TCK_NonnullAssign,
73+
/// Checking the operand of a dynamic_cast or a typeid expression. Must be
74+
/// null or an object within its lifetime.
75+
TCK_DynamicOperation
76+
};
77+
3978
const char *TypeCheckKinds[] = {
4079
"load of", "store to", "reference binding to", "member access within",
4180
"member call on", "constructor call on", "downcast of", "downcast of",
@@ -50,7 +89,9 @@ static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
5089
uptr Alignment = (uptr)1 << Data->LogAlignment;
5190
ErrorType ET;
5291
if (!Pointer)
53-
ET = ErrorType::NullPointerUse;
92+
ET = (Data->TypeCheckKind == TCK_NonnullAssign)
93+
? ErrorType::NullPointerUseWithNullability
94+
: ErrorType::NullPointerUse;
5495
else if (Pointer & (Alignment - 1))
5596
ET = ErrorType::MisalignedPointerUse;
5697
else
@@ -71,6 +112,7 @@ static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
71112

72113
switch (ET) {
73114
case ErrorType::NullPointerUse:
115+
case ErrorType::NullPointerUseWithNullability:
74116
Diag(Loc, DL_Error, ET, "%0 null pointer of type %1")
75117
<< TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
76118
break;
@@ -604,7 +646,8 @@ static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
604646
UNREACHABLE("source location pointer is null!");
605647

606648
SourceLocation Loc = LocPtr->acquire();
607-
ErrorType ET = ErrorType::InvalidNullReturn;
649+
ErrorType ET = IsAttr ? ErrorType::InvalidNullReturn
650+
: ErrorType::InvalidNullReturnWithNullability;
608651

609652
if (ignoreReport(Loc, Opts, ET))
610653
return;
@@ -648,7 +691,8 @@ void __ubsan::__ubsan_handle_nullability_return_v1_abort(
648691
static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts,
649692
bool IsAttr) {
650693
SourceLocation Loc = Data->Loc.acquire();
651-
ErrorType ET = ErrorType::InvalidNullArgument;
694+
ErrorType ET = IsAttr ? ErrorType::InvalidNullArgument
695+
: ErrorType::InvalidNullArgumentWithNullability;
652696

653697
if (ignoreReport(Loc, Opts, ET))
654698
return;

compiler-rt/test/ubsan/TestCases/Misc/nullability.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
// RUN: %run %t foo 2>&1 | count 0
33
// RUN: %run %t 2>&1 | FileCheck %s
44

5+
// RUN: echo "nullability-arg:nullability.c" > %t.supp
6+
// RUN: echo "nullability-return:nullability.c" >> %t.supp
7+
// RUN: echo "nullability-assign:nullability.c" >> %t.supp
8+
// RUN: UBSAN_OPTIONS=suppressions=%t.supp %run %t 2>&1 | count 0
9+
510
// CHECK: nullability.c:[[@LINE+2]]:41: runtime error: null pointer returned from function declared to never return null
611
// CHECK-NEXT: nullability.c:[[@LINE+1]]:6: note: _Nonnull return type annotation specified here
712
int *_Nonnull nonnull_retval1(int *p) { return p; }

0 commit comments

Comments
 (0)