diff options
Diffstat (limited to 'lib/ubsan')
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 56 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.h | 3 |
2 files changed, 50 insertions, 9 deletions
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 1112ce1cc..064d9b78c 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -18,6 +18,9 @@ #include "sanitizer_common/sanitizer_common.h" +#include <cstring> +#include <typeinfo> + using namespace __sanitizer; using namespace __ubsan; @@ -461,14 +464,50 @@ void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) { Die(); } -static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, - ValueHandle Function, +// Check that TI2 represents the same function type as TI1, except that TI2 has +// "noexcept" and TI1 does not. +static bool checkForAddedNoexcept(const std::type_info *TI1, + const std::type_info *TI2) { + const char *Mangled1 = TI1->name(); + const char *Mangled2 = TI2->name(); + + // Skip <CV-qualifiers>. + if (*Mangled1 == 'V') { + if (*Mangled2 != 'V') + return false; + ++Mangled1; + ++Mangled2; + } + if (*Mangled1 == 'K') { + if (*Mangled2 != 'K') + return false; + ++Mangled1; + ++Mangled2; + } + + // Check for "Do" <exception-spec>. + if (*Mangled2++ != 'D' || *Mangled2++ != 'o') + return false; + + // Check remainder is identical. + return std::strcmp(Mangled1, Mangled2) == 0; +} + +static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, + ValueHandle Function, ValueHandle RTTI, ReportOptions Opts) { + if (Data->NonNoexceptRTTI && + checkForAddedNoexcept( + reinterpret_cast<std::type_info *>(Data->NonNoexceptRTTI), + reinterpret_cast<std::type_info *>(RTTI))) { + return false; + } + SourceLocation CallLoc = Data->Loc.acquire(); ErrorType ET = ErrorType::FunctionTypeMismatch; if (ignoreReport(CallLoc, Opts, ET)) - return; + return true; ScopedReport R(Opts, CallLoc, ET); @@ -481,20 +520,21 @@ static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, "call to function %0 through pointer to incorrect function type %1") << FName << Data->Type; Diag(FLoc, DL_Note, "%0 defined here") << FName; + return true; } void __ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, - ValueHandle Function) { + ValueHandle Function, ValueHandle RTTI) { GET_REPORT_OPTIONS(false); - handleFunctionTypeMismatch(Data, Function, Opts); + handleFunctionTypeMismatch(Data, Function, RTTI, Opts); } void __ubsan::__ubsan_handle_function_type_mismatch_abort( - FunctionTypeMismatchData *Data, ValueHandle Function) { + FunctionTypeMismatchData *Data, ValueHandle Function, ValueHandle RTTI) { GET_REPORT_OPTIONS(true); - handleFunctionTypeMismatch(Data, Function, Opts); - Die(); + if (handleFunctionTypeMismatch(Data, Function, RTTI, Opts)) + Die(); } static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr, diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 311776b9f..4ec2592e3 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -140,11 +140,12 @@ RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data) struct FunctionTypeMismatchData { SourceLocation Loc; const TypeDescriptor &Type; + ValueHandle NonNoexceptRTTI; }; RECOVERABLE(function_type_mismatch, FunctionTypeMismatchData *Data, - ValueHandle Val) + ValueHandle Val, ValueHandle RTTI) struct NonNullReturnData { SourceLocation AttrLoc; |