forked from OSchip/llvm-project
Runtime support for the indirect function call checker.
Differential Revision: http://llvm-reviews.chandlerc.com/D1339 llvm-svn: 193060
This commit is contained in:
parent
b714e7e12a
commit
90a0876ae7
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// RUN: %clangxx -fsanitize=address,function %s -O3 -g -o %t
|
||||
// RUN: %t 2>&1 | FileCheck %s
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42);
|
||||
|
||||
// CHECK-NOT: runtime error: call to function g
|
||||
reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(g))(42);
|
||||
}
|
|
@ -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
|
|
@ -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']
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue