Index: lib/ubsan/ubsan_handlers.h =================================================================== --- lib/ubsan/ubsan_handlers.h +++ lib/ubsan/ubsan_handlers.h @@ -132,14 +132,13 @@ ValueHandle Val) struct NonNullReturnData { - SourceLocation Loc; SourceLocation AttrLoc; }; /// \brief Handle returning null from function with the returns_nonnull /// attribute, or a return type annotated with _Nonnull. -RECOVERABLE(nonnull_return, NonNullReturnData *Data) -RECOVERABLE(nullability_return, NonNullReturnData *Data) +RECOVERABLE(nonnull_return_v1, NonNullReturnData *Data, SourceLocation *Loc) +RECOVERABLE(nullability_return_v1, NonNullReturnData *Data, SourceLocation *Loc) struct NonNullArgData { SourceLocation Loc; Index: lib/ubsan/ubsan_handlers.cc =================================================================== --- lib/ubsan/ubsan_handlers.cc +++ lib/ubsan/ubsan_handlers.cc @@ -473,9 +473,12 @@ Die(); } -static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts, - bool IsAttr) { - SourceLocation Loc = Data->Loc.acquire(); +static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr, + ReportOptions Opts, bool IsAttr) { + if (!LocPtr) + return; + + SourceLocation Loc = LocPtr->acquire(); ErrorType ET = ErrorType::InvalidNullReturn; if (ignoreReport(Loc, Opts, ET)) @@ -491,25 +494,29 @@ : "_Nonnull return type annotation"); } -void __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) { +void __ubsan::__ubsan_handle_nonnull_return_v1(NonNullReturnData *Data, + SourceLocation *LocPtr) { GET_REPORT_OPTIONS(false); - handleNonNullReturn(Data, Opts, true); + handleNonNullReturn(Data, LocPtr, Opts, true); } -void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) { +void __ubsan::__ubsan_handle_nonnull_return_v1_abort(NonNullReturnData *Data, + SourceLocation *LocPtr) { GET_REPORT_OPTIONS(true); - handleNonNullReturn(Data, Opts, true); + handleNonNullReturn(Data, LocPtr, Opts, true); Die(); } -void __ubsan::__ubsan_handle_nullability_return(NonNullReturnData *Data) { +void __ubsan::__ubsan_handle_nullability_return_v1(NonNullReturnData *Data, + SourceLocation *LocPtr) { GET_REPORT_OPTIONS(false); - handleNonNullReturn(Data, Opts, false); + handleNonNullReturn(Data, LocPtr, Opts, false); } -void __ubsan::__ubsan_handle_nullability_return_abort(NonNullReturnData *Data) { +void __ubsan::__ubsan_handle_nullability_return_v1_abort( + NonNullReturnData *Data, SourceLocation *LocPtr) { GET_REPORT_OPTIONS(true); - handleNonNullReturn(Data, Opts, false); + handleNonNullReturn(Data, LocPtr, Opts, false); Die(); } Index: lib/ubsan/ubsan_interface.inc =================================================================== --- lib/ubsan/ubsan_interface.inc +++ lib/ubsan/ubsan_interface.inc @@ -28,12 +28,12 @@ INTERFACE_FUNCTION(__ubsan_handle_negate_overflow_abort) INTERFACE_FUNCTION(__ubsan_handle_nonnull_arg) INTERFACE_FUNCTION(__ubsan_handle_nonnull_arg_abort) -INTERFACE_FUNCTION(__ubsan_handle_nonnull_return) -INTERFACE_FUNCTION(__ubsan_handle_nonnull_return_abort) +INTERFACE_FUNCTION(__ubsan_handle_nonnull_return_v1) +INTERFACE_FUNCTION(__ubsan_handle_nonnull_return_v1_abort) INTERFACE_FUNCTION(__ubsan_handle_nullability_arg) INTERFACE_FUNCTION(__ubsan_handle_nullability_arg_abort) -INTERFACE_FUNCTION(__ubsan_handle_nullability_return) -INTERFACE_FUNCTION(__ubsan_handle_nullability_return_abort) +INTERFACE_FUNCTION(__ubsan_handle_nullability_return_v1) +INTERFACE_FUNCTION(__ubsan_handle_nullability_return_v1_abort) INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds) INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds_abort) INTERFACE_FUNCTION(__ubsan_handle_pointer_overflow) Index: test/ubsan/TestCases/Misc/nonnull.cpp =================================================================== --- test/ubsan/TestCases/Misc/nonnull.cpp +++ test/ubsan/TestCases/Misc/nonnull.cpp @@ -1,15 +1,42 @@ // RUN: %clangxx -fsanitize=returns-nonnull-attribute %s -O3 -o %t -// RUN: %run %t foo +// RUN: %run %t foo 2>&1 | count 0 // RUN: %run %t 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=returns-nonnull-attribute -fno-sanitize-recover=returns-nonnull-attribute %s -O3 -o %t.abort +// RUN: not %run %t.abort &> /dev/null __attribute__((returns_nonnull)) char *foo(char *a); char *foo(char *a) { + // CHECK: nonnull.cpp:[[@LINE+2]]:3: runtime error: null pointer returned from function declared to never return null + // CHECK-NEXT: nonnull.cpp:[[@LINE-4]]:16: note: returns_nonnull attribute specified here return a; - // CHECK: nonnull.cpp:[[@LINE+2]]:1: runtime error: null pointer returned from function declared to never return null - // CHECK-NEXT: nonnull.cpp:[[@LINE-5]]:16: note: returns_nonnull attribute specified here +} + +__attribute__((returns_nonnull)) char *bar(int x, char *a) { + if (x > 10) { + // CHECK: nonnull.cpp:[[@LINE+2]]:5: runtime error: null pointer returned from function declared to never return null + // CHECK-NEXT: nonnull.cpp:[[@LINE-3]]:16: note: returns_nonnull attribute specified here + return a; + } else { + // CHECK: nonnull.cpp:[[@LINE+2]]:5: runtime error: null pointer returned from function declared to never return null + // CHECK-NEXT: nonnull.cpp:[[@LINE-7]]:16: note: returns_nonnull attribute specified here + return a; + } } int main(int argc, char **argv) { - return foo(argv[1]) == 0; + char *a = argv[1]; + + foo(a); + + bar(20, a); + + // We expect to see a runtime error the first time we cover the "else"... + bar(5, a); + + // ... but not a second time. + // CHECK-NOT: runtime error + bar(5, a); + + return 0; } Index: test/ubsan/TestCases/Misc/nullability.c =================================================================== --- test/ubsan/TestCases/Misc/nullability.c +++ test/ubsan/TestCases/Misc/nullability.c @@ -2,7 +2,7 @@ // RUN: %run %t foo 2>&1 | count 0 // RUN: %run %t 2>&1 | FileCheck %s -// CHECK: nullability.c:[[@LINE+2]]:51: runtime error: null pointer returned from function declared to never return null +// 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; }