[ubsan] Improve diagnostics for return value checks (compiler-rt)
Differential Revision: https://reviews.llvm.org/D34298
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index 8f18755..75a4490 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/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)
+ UNREACHABLE("source location pointer is null!");
+
+ 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();
}
diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h
index 483c18c..796321b 100644
--- a/lib/ubsan/ubsan_handlers.h
+++ b/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;
diff --git a/lib/ubsan/ubsan_interface.inc b/lib/ubsan/ubsan_interface.inc
index 681476b..a69ca57 100644
--- a/lib/ubsan/ubsan_interface.inc
+++ b/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)
diff --git a/test/ubsan/TestCases/Misc/nonnull.cpp b/test/ubsan/TestCases/Misc/nonnull.cpp
index c3ab49c..d5cd2bf 100644
--- a/test/ubsan/TestCases/Misc/nonnull.cpp
+++ b/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: %clangxx -fsanitize=returns-nonnull-attribute -w %s -O3 -o %t
+// 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 -w %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;
}
diff --git a/test/ubsan/TestCases/Misc/nullability.c b/test/ubsan/TestCases/Misc/nullability.c
index 37b8ddc..b228b24 100644
--- a/test/ubsan/TestCases/Misc/nullability.c
+++ b/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; }