[compiler-rt] r217542 - [UBSan] Add noinline attribute to handlers that should never return.

Alexey Samsonov vonosmas at gmail.com
Wed Sep 10 13:43:36 PDT 2014


Author: samsonov
Date: Wed Sep 10 15:43:36 2014
New Revision: 217542

URL: http://llvm.org/viewvc/llvm-project?rev=217542&view=rev
Log:
[UBSan] Add noinline attribute to handlers that should never return.

FIx a problem reported by Jakub Jelinek: don't do early-exit from fatal
UBSan handlers: even if source location is disabled (i.e. acquired by
some other thread), we should continue the execution to make sure that:
a) some thread will print the error report before calling Die().
b) handler marked as noreturn will indeed not return.

Explicitly add "Die()" calls at the end of all fatal handlers to be
sure UBSan handlers don't introduce UB themselves.

Modified:
    compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
    compiler-rt/trunk/lib/ubsan/ubsan_handlers.h

Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc?rev=217542&r1=217541&r2=217542&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc Wed Sep 10 15:43:36 2014
@@ -19,6 +19,16 @@
 using namespace __sanitizer;
 using namespace __ubsan;
 
+static bool ignoreReport(SourceLocation SLoc, ReportOptions Opts) {
+  // If source location is already acquired, we don't need to print an error
+  // report for the second time. However, if we're in an unrecoverable handler,
+  // it's possible that location was required by concurrently running thread.
+  // In this case, we should continue the execution to ensure that any of
+  // threads will grab the report mutex and print the report before
+  // crashing the program.
+  return SLoc.isDisabled() && !Opts.DieAfterReport;
+}
+
 namespace __ubsan {
   const char *TypeCheckKinds[] = {
     "load of", "store to", "reference binding to", "member access within",
@@ -30,7 +40,7 @@ static void handleTypeMismatchImpl(TypeM
                                    Location FallbackLoc, ReportOptions Opts) {
   Location Loc = Data->Loc.acquire();
   // Use the SourceLocation from Data to track deduplication, even if 'invalid'
-  if (Loc.getSourceLocation().isDisabled())
+  if (ignoreReport(Loc.getSourceLocation(), Opts))
     return;
 
   ScopedReport R(Opts);
@@ -63,6 +73,7 @@ void __ubsan::__ubsan_handle_type_mismat
                                                  ValueHandle Pointer) {
   GET_REPORT_OPTIONS(true);
   handleTypeMismatchImpl(Data, Pointer, getCallerLocation(), Opts);
+  Die();
 }
 
 /// \brief Common diagnostic emission for various forms of integer overflow.
@@ -71,7 +82,7 @@ static void handleIntegerOverflowImpl(Ov
                                       const char *Operator, T RHS,
                                       ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -87,6 +98,7 @@ static void handleIntegerOverflowImpl(Ov
                              ValueHandle RHS) {                                \
     GET_REPORT_OPTIONS(abort);                                                 \
     handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts);    \
+    if (abort) Die();                                                          \
   }
 
 UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
@@ -99,7 +111,7 @@ UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mu
 static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
                                      ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -124,12 +136,13 @@ void __ubsan::__ubsan_handle_negate_over
                                                     ValueHandle OldVal) {
   GET_REPORT_OPTIONS(true);
   handleNegateOverflowImpl(Data, OldVal, Opts);
+  Die();
 }
 
 static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
                                      ValueHandle RHS, ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -154,13 +167,14 @@ void __ubsan::__ubsan_handle_divrem_over
                                                     ValueHandle RHS) {
   GET_REPORT_OPTIONS(true);
   handleDivremOverflowImpl(Data, LHS, RHS, Opts);
+  Die();
 }
 
 static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
                                        ValueHandle LHS, ValueHandle RHS,
                                        ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -193,12 +207,13 @@ void __ubsan::__ubsan_handle_shift_out_o
                                                      ValueHandle RHS) {
   GET_REPORT_OPTIONS(true);
   handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
+  Die();
 }
 
 static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
                                   ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -217,26 +232,38 @@ void __ubsan::__ubsan_handle_out_of_boun
                                                  ValueHandle Index) {
   GET_REPORT_OPTIONS(true);
   handleOutOfBoundsImpl(Data, Index, Opts);
+  Die();
 }
 
-void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
-  GET_REPORT_OPTIONS(true);
+static void handleBuiltinUnreachableImpl(UnreachableData *Data,
+                                         ReportOptions Opts) {
   ScopedReport R(Opts);
   Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
 }
 
-void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
+void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
   GET_REPORT_OPTIONS(true);
+  handleBuiltinUnreachableImpl(Data, Opts);
+  Die();
+}
+
+static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
   ScopedReport R(Opts);
   Diag(Data->Loc, DL_Error,
        "execution reached the end of a value-returning function "
        "without returning a value");
 }
 
+void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
+  GET_REPORT_OPTIONS(true);
+  handleMissingReturnImpl(Data, Opts);
+  Die();
+}
+
 static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
                                       ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -255,6 +282,7 @@ void __ubsan::__ubsan_handle_vla_bound_n
                                                           ValueHandle Bound) {
   GET_REPORT_OPTIONS(true);
   handleVLABoundNotPositive(Data, Bound, Opts);
+  Die();
 }
 
 static void handleFloatCastOverflow(FloatCastOverflowData *Data,
@@ -277,12 +305,13 @@ __ubsan::__ubsan_handle_float_cast_overf
                                                   ValueHandle From) {
   GET_REPORT_OPTIONS(true);
   handleFloatCastOverflow(Data, From, Opts);
+  Die();
 }
 
 static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
                                    ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -301,6 +330,7 @@ void __ubsan::__ubsan_handle_load_invali
                                                       ValueHandle Val) {
   GET_REPORT_OPTIONS(true);
   handleLoadInvalidValue(Data, Val, Opts);
+  Die();
 }
 
 static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
@@ -329,11 +359,12 @@ void __ubsan::__ubsan_handle_function_ty
     FunctionTypeMismatchData *Data, ValueHandle Function) {
   GET_REPORT_OPTIONS(true);
   handleFunctionTypeMismatch(Data, Function, Opts);
+  Die();
 }
 
 static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -352,11 +383,12 @@ void __ubsan::__ubsan_handle_nonnull_ret
 void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) {
   GET_REPORT_OPTIONS(true);
   handleNonNullReturn(Data, Opts);
+  Die();
 }
 
 static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) {
   SourceLocation Loc = Data->Loc.acquire();
-  if (Loc.isDisabled())
+  if (ignoreReport(Loc, Opts))
     return;
 
   ScopedReport R(Opts);
@@ -375,4 +407,5 @@ void __ubsan::__ubsan_handle_nonnull_arg
 void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
   GET_REPORT_OPTIONS(true);
   handleNonNullArg(Data, Opts);
+  Die();
 }

Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.h?rev=217542&r1=217541&r2=217542&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.h Wed Sep 10 15:43:36 2014
@@ -25,13 +25,13 @@ struct TypeMismatchData {
 };
 
 #define UNRECOVERABLE(checkname, ...) \
-  extern "C" SANITIZER_INTERFACE_ATTRIBUTE \
+  extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \
     void __ubsan_handle_ ## checkname( __VA_ARGS__ );
 
 #define RECOVERABLE(checkname, ...) \
   extern "C" SANITIZER_INTERFACE_ATTRIBUTE \
     void __ubsan_handle_ ## checkname( __VA_ARGS__ ); \
-  extern "C" SANITIZER_INTERFACE_ATTRIBUTE \
+  extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \
     void __ubsan_handle_ ## checkname ## _abort( __VA_ARGS__ );
 
 /// \brief Handle a runtime type check failure, caused by either a misaligned





More information about the llvm-commits mailing list