diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2019-07-16 06:23:27 +0000 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2019-07-16 06:23:27 +0000 |
commit | c8b473540c276b551708f80ae23e8bd8c1c1746e (patch) | |
tree | 7ddf13a0ee01da5300d25c97678ba0c9099a8064 | |
parent | 0959e2ed27d2932fbfd294f4e87e79ec9c88594a (diff) | |
download | compiler-rt-c8b473540c276b551708f80ae23e8bd8c1c1746e.tar.gz |
Finish "Adapt -fsanitize=function to SANITIZER_NON_UNIQUE_TYPEINFO"
i.e., recent 5745eccef54ddd3caca278d1d292a88b2281528b:
* Bump the function_type_mismatch handler version, as its signature has changed.
* The function_type_mismatch handler can return successfully now, so
SanitizerKind::Function must be AlwaysRecoverable (like for
SanitizerKind::Vptr).
* But the minimal runtime would still unconditionally treat a call to the
function_type_mismatch handler as failure, so disallow -fsanitize=function in
combination with -fsanitize-minimal-runtime (like it was already done for
-fsanitize=vptr).
* Add tests.
Differential Revision: https://reviews.llvm.org/D61479
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@366186 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.cc | 15 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.h | 15 | ||||
-rw-r--r-- | lib/ubsan/ubsan_interface.inc | 4 | ||||
-rw-r--r-- | test/ubsan/TestCases/TypeCheck/Function/function.cpp | 67 |
4 files changed, 81 insertions, 20 deletions
diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc index 839bba369..9c324cc19 100644 --- a/lib/ubsan/ubsan_handlers_cxx.cc +++ b/lib/ubsan/ubsan_handlers_cxx.cc @@ -185,18 +185,17 @@ static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, return true; } -void __ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, - ValueHandle Function, - ValueHandle calleeRTTI, - ValueHandle fnRTTI) { +void __ubsan_handle_function_type_mismatch_v1(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) { +void __ubsan_handle_function_type_mismatch_v1_abort( + FunctionTypeMismatchData *Data, ValueHandle Function, + ValueHandle calleeRTTI, ValueHandle fnRTTI) { GET_REPORT_OPTIONS(true); if (handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts)) Die(); diff --git a/lib/ubsan/ubsan_handlers_cxx.h b/lib/ubsan/ubsan_handlers_cxx.h index be2345dc1..f7b9fc54f 100644 --- a/lib/ubsan/ubsan_handlers_cxx.h +++ b/lib/ubsan/ubsan_handlers_cxx.h @@ -40,14 +40,15 @@ struct FunctionTypeMismatchData { }; extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, - ValueHandle Val, ValueHandle calleeRTTI, - ValueHandle fnRTTI); +__ubsan_handle_function_type_mismatch_v1(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); +__ubsan_handle_function_type_mismatch_v1_abort(FunctionTypeMismatchData *Data, + ValueHandle Val, + ValueHandle calleeRTTI, + ValueHandle fnRTTI); } #endif // UBSAN_HANDLERS_H diff --git a/lib/ubsan/ubsan_interface.inc b/lib/ubsan/ubsan_interface.inc index 3eb07b7b9..1e44bc217 100644 --- a/lib/ubsan/ubsan_interface.inc +++ b/lib/ubsan/ubsan_interface.inc @@ -21,8 +21,8 @@ INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss) INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss_abort) INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow) INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort) -INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch) -INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort) +INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1) +INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1_abort) INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion) INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion_abort) INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin) diff --git a/test/ubsan/TestCases/TypeCheck/Function/function.cpp b/test/ubsan/TestCases/TypeCheck/Function/function.cpp index 31baa2af8..07402fdcd 100644 --- a/test/ubsan/TestCases/TypeCheck/Function/function.cpp +++ b/test/ubsan/TestCases/TypeCheck/Function/function.cpp @@ -1,11 +1,53 @@ -// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t -// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %clangxx -DDETERMINE_UNIQUE %s -o %t-unique +// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -DSHARED_LIB -fPIC -shared -o %t-so.so +// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t %t-so.so +// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK $(%run %t-unique UNIQUE) // Verify that we can disable symbolization if needed: -// RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM +// RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM $(%run %t-unique NOSYM-UNIQUE) // XFAIL: windows-msvc // Unsupported function flag // UNSUPPORTED: openbsd +#ifdef DETERMINE_UNIQUE + +#include <iostream> + +#include "../../../../../lib/sanitizer_common/sanitizer_platform.h" + +int main(int, char **argv) { + if (!SANITIZER_NON_UNIQUE_TYPEINFO) + std::cout << "--check-prefix=" << argv[1]; +} + +#else + +struct Shared {}; +using FnShared = void (*)(Shared *); +FnShared getShared(); + +struct __attribute__((visibility("hidden"))) Hidden {}; +using FnHidden = void (*)(Hidden *); +FnHidden getHidden(); + +namespace { +struct Private {}; +} // namespace +using FnPrivate = void (*)(void *); +FnPrivate getPrivate(); + +#ifdef SHARED_LIB + +void fnShared(Shared *) {} +FnShared getShared() { return fnShared; } + +void fnHidden(Hidden *) {} +FnHidden getHidden() { return fnHidden; } + +void fnPrivate(Private *) {} +FnPrivate getPrivate() { return reinterpret_cast<FnPrivate>(fnPrivate); } + +#else + #include <stdint.h> void f() {} @@ -64,12 +106,31 @@ void check_noexcept_calls() { p2(0); } +void check_cross_dso() { + getShared()(nullptr); + + // UNIQUE: function.cpp:[[@LINE+2]]:3: runtime error: call to function fnHidden(Hidden*) through pointer to incorrect function type 'void (*)(Hidden *)' + // NOSYM-UNIQUE: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(Hidden *)' + getHidden()(nullptr); + + // TODO: Unlike GCC, Clang fails to prefix the typeinfo name for the function + // type with "*", so this erroneously only fails for "*UNIQUE": + // UNIQUE: function.cpp:[[@LINE+2]]:3: runtime error: call to function fnPrivate((anonymous namespace)::Private*) through pointer to incorrect function type 'void (*)((anonymous namespace)::Private *)' + // NOSYM-UNIQUE: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)((anonymous namespace)::Private *)' + reinterpret_cast<void (*)(Private *)>(getPrivate())(nullptr); +} + int main(void) { make_valid_call(); make_invalid_call(); check_noexcept_calls(); + check_cross_dso(); // Check that no more errors will be printed. // CHECK-NOT: runtime error: call to function // NOSYM-NOT: runtime error: call to function make_invalid_call(); } + +#endif + +#endif |