From 9b5f95f5fe1a24be4dfb7436b64cb0e0f8c00535 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Sun, 20 Oct 2013 21:29:46 +0000 Subject: Runtime support for the indirect function call checker. Differential Revision: http://llvm-reviews.chandlerc.com/D1339 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@193060 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/CMakeLists.txt | 2 ++ lib/ubsan/lit_tests/CMakeLists.txt | 1 + lib/ubsan/lit_tests/TypeCheck/Function/function.cpp | 17 +++++++++++++++++ lib/ubsan/lit_tests/TypeCheck/Function/lit.local.cfg | 3 +++ lib/ubsan/lit_tests/lit.cfg | 3 +++ lib/ubsan/ubsan_diag.cc | 9 +++++++++ lib/ubsan/ubsan_diag.h | 6 ++++++ lib/ubsan/ubsan_handlers.cc | 20 ++++++++++++++++++++ lib/ubsan/ubsan_handlers.h | 9 +++++++++ 9 files changed, 70 insertions(+) create mode 100644 lib/ubsan/lit_tests/TypeCheck/Function/function.cpp create mode 100644 lib/ubsan/lit_tests/TypeCheck/Function/lit.local.cfg diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt index 17552b3a..7a54f96f 100644 --- a/lib/asan/CMakeLists.txt +++ b/lib/asan/CMakeLists.txt @@ -137,6 +137,8 @@ endif() add_compiler_rt_resource_file(asan_blacklist asan_blacklist.txt) +add_custom_target(asan DEPENDS asan_blacklist ${ASAN_RUNTIME_LIBRARIES}) + if(LLVM_INCLUDE_TESTS) add_subdirectory(tests) endif() diff --git a/lib/ubsan/lit_tests/CMakeLists.txt b/lib/ubsan/lit_tests/CMakeLists.txt index 7e1a13c7..6abc8a01 100644 --- a/lib/ubsan/lit_tests/CMakeLists.txt +++ b/lib/ubsan/lit_tests/CMakeLists.txt @@ -8,6 +8,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS) # working binaries. set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} + asan ${UBSAN_RUNTIME_LIBRARIES}) set(UBSAN_TEST_PARAMS ubsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg diff --git a/lib/ubsan/lit_tests/TypeCheck/Function/function.cpp b/lib/ubsan/lit_tests/TypeCheck/Function/function.cpp new file mode 100644 index 00000000..feff0f5a --- /dev/null +++ b/lib/ubsan/lit_tests/TypeCheck/Function/function.cpp @@ -0,0 +1,17 @@ +// RUN: %clangxx -fsanitize=address,function %s -O3 -g -o %t +// RUN: %t 2>&1 | FileCheck %s + +#include + +void f() {} + +void g(int x) {} + +int main(void) { + // CHECK: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)' + // CHECK-NEXT: function.cpp:6: note: f() defined here + reinterpret_cast(reinterpret_cast(f))(42); + + // CHECK-NOT: runtime error: call to function g + reinterpret_cast(reinterpret_cast(g))(42); +} diff --git a/lib/ubsan/lit_tests/TypeCheck/Function/lit.local.cfg b/lib/ubsan/lit_tests/TypeCheck/Function/lit.local.cfg new file mode 100644 index 00000000..27c61a34 --- /dev/null +++ b/lib/ubsan/lit_tests/TypeCheck/Function/lit.local.cfg @@ -0,0 +1,3 @@ +# The function type checker is only supported on x86 and x86_64 for now. +if config.root.host_arch not in ['x86', 'x86_64']: + config.unsupported = True diff --git a/lib/ubsan/lit_tests/lit.cfg b/lib/ubsan/lit_tests/lit.cfg index 4a5bc237..d96912fe 100644 --- a/lib/ubsan/lit_tests/lit.cfg +++ b/lib/ubsan/lit_tests/lit.cfg @@ -54,6 +54,9 @@ config.substitutions.append( ("%clang ", (" " + config.clang + " ")) ) config.substitutions.append( ("%clangxx ", (" " + config.clang + " --driver-mode=g++ ")) ) +# Setup path to external LLVM symbolizer. +config.environment['ASAN_SYMBOLIZER_PATH'] = config.llvm_symbolizer_path + # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc index e4ca4e4a..968e7790 100644 --- a/lib/ubsan/ubsan_diag.cc +++ b/lib/ubsan/ubsan_diag.cc @@ -26,12 +26,21 @@ Location __ubsan::getCallerLocation(uptr CallerLoc) { return Location(); uptr Loc = StackTrace::GetPreviousInstructionPc(CallerLoc); + return getFunctionLocation(Loc, 0); +} + +Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) { + if (!Loc) + return Location(); AddressInfo Info; if (!getSymbolizer()->SymbolizeCode(Loc, &Info, 1) || !Info.module || !*Info.module) return Location(Loc); + if (FName && Info.function) + *FName = Info.function; + if (!Info.file) return ModuleLocation(Info.module, Info.module_offset); diff --git a/lib/ubsan/ubsan_diag.h b/lib/ubsan/ubsan_diag.h index 16afffdb..54d15a0c 100644 --- a/lib/ubsan/ubsan_diag.h +++ b/lib/ubsan/ubsan_diag.h @@ -80,6 +80,12 @@ public: /// an invalid location or a module location for the caller. Location getCallerLocation(uptr CallerLoc = GET_CALLER_PC()); +/// Try to obtain a location for the given function pointer. This might fail, +/// and produce either an invalid location or a module location for the caller. +/// If FName is non-null and the name of the function is known, set *FName to +/// the function name, otherwise *FName is unchanged. +Location getFunctionLocation(uptr Loc, const char **FName); + /// A diagnostic severity level. enum DiagLevel { DL_Error, ///< An error. diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 5ed0d592..d5564314 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -259,3 +259,23 @@ void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data, __ubsan_handle_load_invalid_value(Data, Val); Die(); } + +void __ubsan::__ubsan_handle_function_type_mismatch( + FunctionTypeMismatchData *Data, + ValueHandle Function) { + const char *FName = "(unknown)"; + + Location Loc = getFunctionLocation(Function, &FName); + + Diag(Data->Loc, DL_Error, + "call to function %0 through pointer to incorrect function type %1") + << FName << Data->Type; + Diag(Loc, DL_Note, "%0 defined here") << FName; +} + +void __ubsan::__ubsan_handle_function_type_mismatch_abort( + FunctionTypeMismatchData *Data, + ValueHandle Function) { + __ubsan_handle_function_type_mismatch(Data, Function); + Die(); +} diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 9406207f..14e6f04c 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -112,6 +112,15 @@ struct InvalidValueData { /// \brief Handle a load of an invalid value for the type. RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val) +struct FunctionTypeMismatchData { + SourceLocation Loc; + const TypeDescriptor &Type; +}; + +RECOVERABLE(function_type_mismatch, + FunctionTypeMismatchData *Data, + ValueHandle Val) + } #endif // UBSAN_HANDLERS_H -- cgit v1.2.3