summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2019-05-02 06:40:33 +0000
committerStephan Bergmann <sbergman@redhat.com>2019-05-02 06:40:33 +0000
commitd139bd8e458debdc7392d1042a74d0bc335ac856 (patch)
tree205a240147bea7739e19791fbaec68ca8facade5
parentfc6f4a6ed7e7a8a77d1592f1ec6948fbb3ca42fa (diff)
downloadcompiler-rt-d139bd8e458debdc7392d1042a74d0bc335ac856.tar.gz
Adapt -fsanitize=function to SANITIZER_NON_UNIQUE_TYPEINFO
This follows up after b7692bc3e9ad2691fc07261904b88fb15f30696b "[UBSan] Fix isDerivedFromAtOffset on iOS ARM64" fixed the RTTI comparison in isDerivedFromAtOffset on just one platform and then a25a2c7c9a7e1e328a5bd8274d2d86b1fadc4692 "Always compare C++ typeinfo (based on libstdc++ implementation)" extended that fix to more platforms. But there is another RTTI comparison for -fsanitize=function generated in clang's CodeGenFunction::EmitCall as just a pointer comparison. For SANITIZER_NON_UNIQUE_TYPEINFO platforms this needs to be extended to also do string comparison. For that, __ubsan_handle_function_type_mismatch[_abort] takes the two std::type_info pointers as additional parameters now, checks them internally for potential equivalence, and returns without reporting failure if they turn out to be equivalent after all. (NORETURN needed to be dropped from the _abort variant for that.) Also these functions depend on ABI-specific RTTI now, so needed to be moved from plain UBSAN_SOURCES (ubsan_handlers.h/cc) to UBSAN_CXXABI_SOURCES (ubsan_handlers_cxx.h/cc), but as -fsanitize=function is only supported in C++ mode that's not a problem. Differential Revision: https://reviews.llvm.org/D60760 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@359759 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/ubsan/ubsan_handlers.cc36
-rw-r--r--lib/ubsan/ubsan_handlers.h9
-rw-r--r--lib/ubsan/ubsan_handlers_cxx.cc45
-rw-r--r--lib/ubsan/ubsan_handlers_cxx.h15
-rw-r--r--lib/ubsan/ubsan_type_hash.h4
-rw-r--r--lib/ubsan/ubsan_type_hash_itanium.cc13
-rw-r--r--lib/ubsan/ubsan_type_hash_win.cc5
7 files changed, 79 insertions, 48 deletions
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index d4b8f13b7..938ac8975 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/lib/ubsan/ubsan_handlers.cc
@@ -598,42 +598,6 @@ void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) {
Die();
}
-static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
- ValueHandle Function,
- ReportOptions Opts) {
- SourceLocation CallLoc = Data->Loc.acquire();
- ErrorType ET = ErrorType::FunctionTypeMismatch;
-
- if (ignoreReport(CallLoc, Opts, ET))
- return;
-
- ScopedReport R(Opts, CallLoc, ET);
-
- SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
- const char *FName = FLoc.get()->info.function;
- if (!FName)
- FName = "(unknown)";
-
- Diag(CallLoc, DL_Error, ET,
- "call to function %0 through pointer to incorrect function type %1")
- << FName << Data->Type;
- Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;
-}
-
-void
-__ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
- ValueHandle Function) {
- GET_REPORT_OPTIONS(false);
- handleFunctionTypeMismatch(Data, Function, Opts);
-}
-
-void __ubsan::__ubsan_handle_function_type_mismatch_abort(
- FunctionTypeMismatchData *Data, ValueHandle Function) {
- GET_REPORT_OPTIONS(true);
- handleFunctionTypeMismatch(Data, Function, Opts);
- Die();
-}
-
static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
ReportOptions Opts, bool IsAttr) {
if (!LocPtr)
diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h
index 37a63c565..22ca96422 100644
--- a/lib/ubsan/ubsan_handlers.h
+++ b/lib/ubsan/ubsan_handlers.h
@@ -168,15 +168,6 @@ struct InvalidBuiltinData {
/// Handle a builtin called in an invalid way.
RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data)
-struct FunctionTypeMismatchData {
- SourceLocation Loc;
- const TypeDescriptor &Type;
-};
-
-RECOVERABLE(function_type_mismatch,
- FunctionTypeMismatchData *Data,
- ValueHandle Val)
-
struct NonNullReturnData {
SourceLocation AttrLoc;
};
diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc
index 56b5a9e9a..839bba369 100644
--- a/lib/ubsan/ubsan_handlers_cxx.cc
+++ b/lib/ubsan/ubsan_handlers_cxx.cc
@@ -156,6 +156,51 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1")
<< SrcModule << DstModule;
}
+
+static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
+ ValueHandle Function,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI, ReportOptions Opts) {
+ if (checkTypeInfoEquality(reinterpret_cast<void *>(calleeRTTI),
+ reinterpret_cast<void *>(fnRTTI)))
+ return false;
+
+ SourceLocation CallLoc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::FunctionTypeMismatch;
+
+ if (ignoreReport(CallLoc, Opts, ET))
+ return true;
+
+ ScopedReport R(Opts, CallLoc, ET);
+
+ SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
+ const char *FName = FLoc.get()->info.function;
+ if (!FName)
+ FName = "(unknown)";
+
+ Diag(CallLoc, DL_Error, ET,
+ "call to function %0 through pointer to incorrect function type %1")
+ << FName << Data->Type;
+ Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;
+ return true;
+}
+
+void __ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
+ ValueHandle Function,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI) {
+ GET_REPORT_OPTIONS(false);
+ handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts);
+}
+
+void __ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data,
+ ValueHandle Function,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI) {
+ GET_REPORT_OPTIONS(true);
+ if (handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts))
+ Die();
+}
} // namespace __ubsan
#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_handlers_cxx.h b/lib/ubsan/ubsan_handlers_cxx.h
index 8dd5f1a0f..be2345dc1 100644
--- a/lib/ubsan/ubsan_handlers_cxx.h
+++ b/lib/ubsan/ubsan_handlers_cxx.h
@@ -33,6 +33,21 @@ void __ubsan_handle_dynamic_type_cache_miss(
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void __ubsan_handle_dynamic_type_cache_miss_abort(
DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash);
+
+struct FunctionTypeMismatchData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+};
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
+ ValueHandle Val, ValueHandle calleeRTTI,
+ ValueHandle fnRTTI);
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data,
+ ValueHandle Val,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI);
}
#endif // UBSAN_HANDLERS_H
diff --git a/lib/ubsan/ubsan_type_hash.h b/lib/ubsan/ubsan_type_hash.h
index 811aeb83e..e42884b76 100644
--- a/lib/ubsan/ubsan_type_hash.h
+++ b/lib/ubsan/ubsan_type_hash.h
@@ -64,6 +64,10 @@ const int VptrMaxOffsetToTop = 1<<20;
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
HashValue __ubsan_vptr_type_cache[VptrTypeCacheSize];
+/// \brief Do whatever is required by the ABI to check for std::type_info
+/// equivalence beyond simple pointer comparison.
+bool checkTypeInfoEquality(const void *TypeInfo1, const void *TypeInfo2);
+
} // namespace __ubsan
#endif // UBSAN_TYPE_HASH_H
diff --git a/lib/ubsan/ubsan_type_hash_itanium.cc b/lib/ubsan/ubsan_type_hash_itanium.cc
index 3d5e536d3..c4b048f20 100644
--- a/lib/ubsan/ubsan_type_hash_itanium.cc
+++ b/lib/ubsan/ubsan_type_hash_itanium.cc
@@ -117,9 +117,7 @@ static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
const abi::__class_type_info *Base,
sptr Offset) {
if (Derived->__type_name == Base->__type_name ||
- (SANITIZER_NON_UNIQUE_TYPEINFO &&
- Derived->__type_name[0] != '*' &&
- !internal_strcmp(Derived->__type_name, Base->__type_name)))
+ __ubsan::checkTypeInfoEquality(Derived, Base))
return Offset == 0;
if (const abi::__si_class_type_info *SI =
@@ -258,4 +256,13 @@ __ubsan::getDynamicTypeInfoFromVtable(void *VtablePtr) {
ObjectType ? ObjectType->__type_name : "<unknown>");
}
+bool __ubsan::checkTypeInfoEquality(const void *TypeInfo1,
+ const void *TypeInfo2) {
+ auto TI1 = static_cast<const std::type_info *>(TypeInfo1);
+ auto TI2 = static_cast<const std::type_info *>(TypeInfo2);
+ return SANITIZER_NON_UNIQUE_TYPEINFO && TI1->__type_name[0] != '*' &&
+ TI2->__type_name[0] != '*' &&
+ !internal_strcmp(TI1->__type_name, TI2->__type_name);
+}
+
#endif // CAN_SANITIZE_UB && !SANITIZER_WINDOWS
diff --git a/lib/ubsan/ubsan_type_hash_win.cc b/lib/ubsan/ubsan_type_hash_win.cc
index f3035e121..21c51e328 100644
--- a/lib/ubsan/ubsan_type_hash_win.cc
+++ b/lib/ubsan/ubsan_type_hash_win.cc
@@ -77,4 +77,9 @@ __ubsan::getDynamicTypeInfoFromVtable(void *VtablePtr) {
"<unknown>");
}
+bool __ubsan::checkTypeInfoEquality(const std::type_info *,
+ const std::type_info *) {
+ return false;
+}
+
#endif // CAN_SANITIZE_UB && SANITIZER_WINDOWS