forked from OSchip/llvm-project
				
			[ubsan] Improve diagnostics for return value checks (compiler-rt)
Differential Revision: https://reviews.llvm.org/D34298 llvm-svn: 306164
This commit is contained in:
		
							parent
							
								
									c34d343f15
								
							
						
					
					
						commit
						d1c3780cf6
					
				| 
						 | 
				
			
			@ -473,9 +473,12 @@ void __ubsan::__ubsan_handle_function_type_mismatch_abort(
 | 
			
		|||
  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 @@ static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts,
 | 
			
		|||
                   : "_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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,14 +132,13 @@ RECOVERABLE(function_type_mismatch,
 | 
			
		|||
            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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,12 +28,12 @@ INTERFACE_FUNCTION(__ubsan_handle_negate_overflow)
 | 
			
		|||
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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue