summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2019-07-16 06:23:27 +0000
committerStephan Bergmann <sbergman@redhat.com>2019-07-16 06:23:27 +0000
commitc8b473540c276b551708f80ae23e8bd8c1c1746e (patch)
tree7ddf13a0ee01da5300d25c97678ba0c9099a8064
parent0959e2ed27d2932fbfd294f4e87e79ec9c88594a (diff)
downloadcompiler-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.cc15
-rw-r--r--lib/ubsan/ubsan_handlers_cxx.h15
-rw-r--r--lib/ubsan/ubsan_interface.inc4
-rw-r--r--test/ubsan/TestCases/TypeCheck/Function/function.cpp67
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