mirror of git://gcc.gnu.org/git/gcc.git
libsanitizer: Apply local patches
This patch just reapplies local patches (will be noted in LOCAL_PATCHES).
This commit is contained in:
parent
fa321004f3
commit
b53f7de3e6
|
@ -226,25 +226,6 @@ static void CheckODRViolationViaIndicator(const Global *g)
|
||||||
AddGlobalToList(relevant_globals, g);
|
AddGlobalToList(relevant_globals, g);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check ODR violation for given global G by checking if it's already poisoned.
|
|
||||||
// We use this method in case compiler doesn't use private aliases for global
|
|
||||||
// variables.
|
|
||||||
static void CheckODRViolationViaPoisoning(const Global *g)
|
|
||||||
SANITIZER_REQUIRES(mu_for_globals) {
|
|
||||||
if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
|
|
||||||
// This check may not be enough: if the first global is much larger
|
|
||||||
// the entire redzone of the second global may be within the first global.
|
|
||||||
for (const auto &l : list_of_all_globals) {
|
|
||||||
if (g->beg == l.g->beg &&
|
|
||||||
(flags()->detect_odr_violation >= 2 || g->size != l.g->size) &&
|
|
||||||
!IsODRViolationSuppressed(g->name)) {
|
|
||||||
ReportODRViolation(g, FindRegistrationSite(g), l.g,
|
|
||||||
FindRegistrationSite(l.g));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clang provides two different ways for global variables protection:
|
// Clang provides two different ways for global variables protection:
|
||||||
// it can poison the global itself or its private alias. In former
|
// it can poison the global itself or its private alias. In former
|
||||||
// case we may poison same symbol multiple times, that can help us to
|
// case we may poison same symbol multiple times, that can help us to
|
||||||
|
@ -290,8 +271,6 @@ static void RegisterGlobal(const Global *g) SANITIZER_REQUIRES(mu_for_globals) {
|
||||||
// where two globals with the same name are defined in different modules.
|
// where two globals with the same name are defined in different modules.
|
||||||
if (UseODRIndicator(g))
|
if (UseODRIndicator(g))
|
||||||
CheckODRViolationViaIndicator(g);
|
CheckODRViolationViaIndicator(g);
|
||||||
else
|
|
||||||
CheckODRViolationViaPoisoning(g);
|
|
||||||
}
|
}
|
||||||
if (CanPoisonMemory())
|
if (CanPoisonMemory())
|
||||||
PoisonRedZones(*g);
|
PoisonRedZones(*g);
|
||||||
|
|
|
@ -71,7 +71,12 @@ void InitializePlatformInterceptors();
|
||||||
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_SOLARIS && !SANITIZER_NETBSD && \
|
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_SOLARIS && !SANITIZER_NETBSD && \
|
||||||
(!SANITIZER_WINDOWS || (defined(__MINGW32__) && defined(__i386__)))
|
(!SANITIZER_WINDOWS || (defined(__MINGW32__) && defined(__i386__)))
|
||||||
# define ASAN_INTERCEPT___CXA_THROW 1
|
# define ASAN_INTERCEPT___CXA_THROW 1
|
||||||
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
|
# if ! defined(ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION) \
|
||||||
|
|| ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION
|
||||||
|
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
|
||||||
|
# else
|
||||||
|
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
|
||||||
|
# endif
|
||||||
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
|
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
|
||||||
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
|
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
|
||||||
# else
|
# else
|
||||||
|
|
|
@ -193,7 +193,7 @@
|
||||||
# elif defined(__aarch64__)
|
# elif defined(__aarch64__)
|
||||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
|
# define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
|
||||||
# elif defined(__powerpc64__)
|
# elif defined(__powerpc64__)
|
||||||
# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
|
# define ASAN_SHADOW_OFFSET_CONST 0x0000020000000000
|
||||||
# elif defined(__s390x__)
|
# elif defined(__s390x__)
|
||||||
# define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000
|
# define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000
|
||||||
# elif SANITIZER_FREEBSD
|
# elif SANITIZER_FREEBSD
|
||||||
|
|
|
@ -901,9 +901,13 @@ u32 GetNumberOfCPUs() {
|
||||||
# elif SANITIZER_SOLARIS
|
# elif SANITIZER_SOLARIS
|
||||||
return sysconf(_SC_NPROCESSORS_ONLN);
|
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
# else
|
# else
|
||||||
|
# if defined(CPU_COUNT)
|
||||||
cpu_set_t CPUs;
|
cpu_set_t CPUs;
|
||||||
CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
|
CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
|
||||||
return CPU_COUNT(&CPUs);
|
return CPU_COUNT(&CPUs);
|
||||||
|
# else
|
||||||
|
return 1;
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(__has_include) && __has_include(<os/trace.h>)
|
# if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__)
|
||||||
# define SANITIZER_OS_TRACE 1
|
# define SANITIZER_OS_TRACE 1
|
||||||
# include <os/trace.h>
|
# include <os/trace.h>
|
||||||
# else
|
# else
|
||||||
|
@ -71,7 +71,15 @@ extern char ***_NSGetArgv(void);
|
||||||
# include <mach/mach_time.h>
|
# include <mach/mach_time.h>
|
||||||
# include <mach/vm_statistics.h>
|
# include <mach/vm_statistics.h>
|
||||||
# include <malloc/malloc.h>
|
# include <malloc/malloc.h>
|
||||||
# include <os/log.h>
|
# if defined(__has_builtin) && __has_builtin(__builtin_os_log_format)
|
||||||
|
# include <os/log.h>
|
||||||
|
# else
|
||||||
|
/* Without support for __builtin_os_log_format, fall back to the older
|
||||||
|
method. */
|
||||||
|
# define OS_LOG_DEFAULT 0
|
||||||
|
# define os_log_error(A,B,C) \
|
||||||
|
asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", (C));
|
||||||
|
# endif
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
# include <pthread/introspection.h>
|
# include <pthread/introspection.h>
|
||||||
# include <sched.h>
|
# include <sched.h>
|
||||||
|
|
|
@ -14,6 +14,26 @@
|
||||||
|
|
||||||
#include "sanitizer_common.h"
|
#include "sanitizer_common.h"
|
||||||
#include "sanitizer_platform.h"
|
#include "sanitizer_platform.h"
|
||||||
|
|
||||||
|
/* TARGET_OS_OSX is not present in SDKs before Darwin16 (macOS 10.12) use
|
||||||
|
TARGET_OS_MAC (we have no support for iOS in any form for these versions,
|
||||||
|
so there's no ambiguity). */
|
||||||
|
#if !defined(TARGET_OS_OSX) && TARGET_OS_MAC
|
||||||
|
# define TARGET_OS_OSX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Other TARGET_OS_xxx are not present on earlier versions, define them to
|
||||||
|
0 (we have no support for them; they are not valid targets anyway). */
|
||||||
|
#ifndef TARGET_OS_IOS
|
||||||
|
#define TARGET_OS_IOS 0
|
||||||
|
#endif
|
||||||
|
#ifndef TARGET_OS_TV
|
||||||
|
#define TARGET_OS_TV 0
|
||||||
|
#endif
|
||||||
|
#ifndef TARGET_OS_WATCH
|
||||||
|
#define TARGET_OS_WATCH 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_APPLE
|
#if SANITIZER_APPLE
|
||||||
#include "sanitizer_posix.h"
|
#include "sanitizer_posix.h"
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,10 @@
|
||||||
|
|
||||||
// With old kernels (and even new kernels on powerpc) asm/stat.h uses types that
|
// With old kernels (and even new kernels on powerpc) asm/stat.h uses types that
|
||||||
// are not defined anywhere in userspace headers. Fake them. This seems to work
|
// are not defined anywhere in userspace headers. Fake them. This seems to work
|
||||||
// fine with newer headers, too.
|
// fine with newer headers, too. Beware that with <sys/stat.h>, struct stat
|
||||||
|
// takes the form of struct stat64 on 32-bit platforms if _FILE_OFFSET_BITS=64.
|
||||||
|
// Also, for some platforms (e.g. mips) there are additional members in the
|
||||||
|
// <sys/stat.h> struct stat:s.
|
||||||
#include <linux/posix_types.h>
|
#include <linux/posix_types.h>
|
||||||
# if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__)
|
# if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__)
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
|
|
|
@ -146,8 +146,13 @@ static bool IsDyldHdr(const mach_header *hdr) {
|
||||||
// until we hit a Mach header matching dyld instead. These recurse
|
// until we hit a Mach header matching dyld instead. These recurse
|
||||||
// calls are expensive, but the first memory map generation occurs
|
// calls are expensive, but the first memory map generation occurs
|
||||||
// early in the process, when dyld is one of the only images loaded,
|
// early in the process, when dyld is one of the only images loaded,
|
||||||
// so it will be hit after only a few iterations. These assumptions don't hold
|
// so it will be hit after only a few iterations. These assumptions don't
|
||||||
// on macOS 13+ anymore (dyld itself has moved into the shared cache).
|
// hold on macOS 13+ anymore (dyld itself has moved into the shared cache).
|
||||||
|
|
||||||
|
// FIXME: Unfortunately, the upstream revised version to deal with macOS 13+
|
||||||
|
// is incompatible with GCC and also uses APIs not available on earlier
|
||||||
|
// systems which we support; backed out for now.
|
||||||
|
|
||||||
static mach_header *GetDyldImageHeaderViaVMRegion() {
|
static mach_header *GetDyldImageHeaderViaVMRegion() {
|
||||||
vm_address_t address = 0;
|
vm_address_t address = 0;
|
||||||
|
|
||||||
|
@ -171,64 +176,17 @@ static mach_header *GetDyldImageHeaderViaVMRegion() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
struct dyld_shared_cache_dylib_text_info {
|
|
||||||
uint64_t version; // current version 2
|
|
||||||
// following fields all exist in version 1
|
|
||||||
uint64_t loadAddressUnslid;
|
|
||||||
uint64_t textSegmentSize;
|
|
||||||
uuid_t dylibUuid;
|
|
||||||
const char *path; // pointer invalid at end of iterations
|
|
||||||
// following fields all exist in version 2
|
|
||||||
uint64_t textSegmentOffset; // offset from start of cache
|
|
||||||
};
|
|
||||||
typedef struct dyld_shared_cache_dylib_text_info
|
|
||||||
dyld_shared_cache_dylib_text_info;
|
|
||||||
|
|
||||||
extern bool _dyld_get_shared_cache_uuid(uuid_t uuid);
|
|
||||||
extern const void *_dyld_get_shared_cache_range(size_t *length);
|
|
||||||
extern int dyld_shared_cache_iterate_text(
|
|
||||||
const uuid_t cacheUuid,
|
|
||||||
void (^callback)(const dyld_shared_cache_dylib_text_info *info));
|
|
||||||
} // extern "C"
|
|
||||||
|
|
||||||
static mach_header *GetDyldImageHeaderViaSharedCache() {
|
|
||||||
uuid_t uuid;
|
|
||||||
bool hasCache = _dyld_get_shared_cache_uuid(uuid);
|
|
||||||
if (!hasCache)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
size_t cacheLength;
|
|
||||||
__block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
|
|
||||||
CHECK(cacheStart && cacheLength);
|
|
||||||
|
|
||||||
__block mach_header *dyldHdr = nullptr;
|
|
||||||
int res = dyld_shared_cache_iterate_text(
|
|
||||||
uuid, ^(const dyld_shared_cache_dylib_text_info *info) {
|
|
||||||
CHECK_GE(info->version, 2);
|
|
||||||
mach_header *hdr =
|
|
||||||
(mach_header *)(cacheStart + info->textSegmentOffset);
|
|
||||||
if (IsDyldHdr(hdr))
|
|
||||||
dyldHdr = hdr;
|
|
||||||
});
|
|
||||||
CHECK_EQ(res, 0);
|
|
||||||
|
|
||||||
return dyldHdr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mach_header *get_dyld_hdr() {
|
const mach_header *get_dyld_hdr() {
|
||||||
if (!dyld_hdr) {
|
if (!dyld_hdr) {
|
||||||
// On macOS 13+, dyld itself has moved into the shared cache. Looking it up
|
// On macOS 13+, dyld itself has moved into the shared cache. Looking it up
|
||||||
// via vm_region_recurse_64() causes spins/hangs/crashes.
|
// via vm_region_recurse_64() causes spins/hangs/crashes.
|
||||||
|
// FIXME: find a way to do this compatible with GCC.
|
||||||
if (GetMacosAlignedVersion() >= MacosVersion(13, 0)) {
|
if (GetMacosAlignedVersion() >= MacosVersion(13, 0)) {
|
||||||
dyld_hdr = GetDyldImageHeaderViaSharedCache();
|
|
||||||
if (!dyld_hdr) {
|
|
||||||
VReport(1,
|
VReport(1,
|
||||||
"Failed to lookup the dyld image header in the shared cache on "
|
"looking up the dyld image header in the shared cache on "
|
||||||
"macOS 13+ (or no shared cache in use). Falling back to "
|
"macOS 13+ is not yet supported. Falling back to "
|
||||||
"lookup via vm_region_recurse_64().\n");
|
"lookup via vm_region_recurse_64().\n");
|
||||||
dyld_hdr = GetDyldImageHeaderViaVMRegion();
|
dyld_hdr = GetDyldImageHeaderViaVMRegion();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dyld_hdr = GetDyldImageHeaderViaVMRegion();
|
dyld_hdr = GetDyldImageHeaderViaVMRegion();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
# define SANITIZER_REDEFINE_BUILTINS_H
|
# define SANITIZER_REDEFINE_BUILTINS_H
|
||||||
|
|
||||||
// The asm hack only works with GCC and Clang.
|
// The asm hack only works with GCC and Clang.
|
||||||
# if !defined(_WIN32)
|
# if !defined(_WIN32) && defined(HAVE_AS_SYM_ASSIGN)
|
||||||
|
|
||||||
asm(R"(
|
asm(R"(
|
||||||
.set memcpy, __sanitizer_internal_memcpy
|
.set memcpy, __sanitizer_internal_memcpy
|
||||||
|
@ -52,7 +52,7 @@ using vector = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
# endif // __cpluplus
|
# endif // __cpluplus
|
||||||
# endif // !_WIN32
|
# endif // !_WIN32 && HAVE_AS_SYM_ASSIGN
|
||||||
|
|
||||||
# endif // SANITIZER_REDEFINE_BUILTINS_H
|
# endif // SANITIZER_REDEFINE_BUILTINS_H
|
||||||
#endif // SANITIZER_COMMON_NO_REDEFINE_BUILTINS
|
#endif // SANITIZER_COMMON_NO_REDEFINE_BUILTINS
|
||||||
|
|
|
@ -87,8 +87,8 @@ static inline uhwptr *GetCanonicFrame(uptr bp,
|
||||||
// Nope, this does not look right either. This means the frame after next does
|
// Nope, this does not look right either. This means the frame after next does
|
||||||
// not have a valid frame pointer, but we can still extract the caller PC.
|
// not have a valid frame pointer, but we can still extract the caller PC.
|
||||||
// Unfortunately, there is no way to decide between GCC and LLVM frame
|
// Unfortunately, there is no way to decide between GCC and LLVM frame
|
||||||
// layouts. Assume LLVM.
|
// layouts. Assume GCC.
|
||||||
return bp_prev;
|
return bp_prev - 1;
|
||||||
#else
|
#else
|
||||||
return (uhwptr*)bp;
|
return (uhwptr*)bp;
|
||||||
#endif
|
#endif
|
||||||
|
@ -111,14 +111,21 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
|
||||||
IsAligned((uptr)frame, sizeof(*frame)) &&
|
IsAligned((uptr)frame, sizeof(*frame)) &&
|
||||||
size < max_depth) {
|
size < max_depth) {
|
||||||
#ifdef __powerpc__
|
#ifdef __powerpc__
|
||||||
// PowerPC ABIs specify that the return address is saved at offset
|
// PowerPC ABIs specify that the return address is saved on the
|
||||||
// 16 of the *caller's* stack frame. Thus we must dereference the
|
// *caller's* stack frame. Thus we must dereference the back chain
|
||||||
// back chain to find the caller frame before extracting it.
|
// to find the caller frame before extracting it.
|
||||||
uhwptr *caller_frame = (uhwptr*)frame[0];
|
uhwptr *caller_frame = (uhwptr*)frame[0];
|
||||||
if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) ||
|
if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) ||
|
||||||
!IsAligned((uptr)caller_frame, sizeof(uhwptr)))
|
!IsAligned((uptr)caller_frame, sizeof(uhwptr)))
|
||||||
break;
|
break;
|
||||||
|
// For most ABIs the offset where the return address is saved is two
|
||||||
|
// register sizes. The exception is the SVR4 ABI, which uses an
|
||||||
|
// offset of only one register size.
|
||||||
|
#ifdef _CALL_SYSV
|
||||||
|
uhwptr pc1 = caller_frame[1];
|
||||||
|
#else
|
||||||
uhwptr pc1 = caller_frame[2];
|
uhwptr pc1 = caller_frame[2];
|
||||||
|
#endif
|
||||||
#elif defined(__s390__)
|
#elif defined(__s390__)
|
||||||
uhwptr pc1 = frame[14];
|
uhwptr pc1 = frame[14];
|
||||||
#elif defined(__loongarch__) || defined(__riscv)
|
#elif defined(__loongarch__) || defined(__riscv)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "tsan_ppc_regs.h"
|
#include "tsan_ppc_regs.h"
|
||||||
|
|
||||||
|
.machine altivec
|
||||||
.section .text
|
.section .text
|
||||||
.hidden __tsan_setjmp
|
.hidden __tsan_setjmp
|
||||||
.globl _setjmp
|
.globl _setjmp
|
||||||
|
|
|
@ -50,6 +50,7 @@ void InitializeFlags() {
|
||||||
{
|
{
|
||||||
CommonFlags cf;
|
CommonFlags cf;
|
||||||
cf.CopyFrom(*common_flags());
|
cf.CopyFrom(*common_flags());
|
||||||
|
cf.print_summary = false;
|
||||||
cf.external_symbolizer_path = GetFlag("UBSAN_SYMBOLIZER_PATH");
|
cf.external_symbolizer_path = GetFlag("UBSAN_SYMBOLIZER_PATH");
|
||||||
OverrideCommonFlags(cf);
|
OverrideCommonFlags(cf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -904,6 +904,21 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
|
||||||
|
|
||||||
} // namespace __ubsan
|
} // namespace __ubsan
|
||||||
|
|
||||||
|
void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *CallData,
|
||||||
|
ValueHandle Function) {
|
||||||
|
GET_REPORT_OPTIONS(false);
|
||||||
|
CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
|
||||||
|
handleCFIBadIcall(&Data, Function, Opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *CallData,
|
||||||
|
ValueHandle Function) {
|
||||||
|
GET_REPORT_OPTIONS(true);
|
||||||
|
CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
|
||||||
|
handleCFIBadIcall(&Data, Function, Opts);
|
||||||
|
Die();
|
||||||
|
}
|
||||||
|
|
||||||
void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
|
void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
|
||||||
ValueHandle Value,
|
ValueHandle Value,
|
||||||
uptr ValidVtable) {
|
uptr ValidVtable) {
|
||||||
|
|
|
@ -217,12 +217,20 @@ enum CFITypeCheckKind : unsigned char {
|
||||||
CFITCK_VMFCall,
|
CFITCK_VMFCall,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CFIBadIcallData {
|
||||||
|
SourceLocation Loc;
|
||||||
|
const TypeDescriptor &Type;
|
||||||
|
};
|
||||||
|
|
||||||
struct CFICheckFailData {
|
struct CFICheckFailData {
|
||||||
CFITypeCheckKind CheckKind;
|
CFITypeCheckKind CheckKind;
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
const TypeDescriptor &Type;
|
const TypeDescriptor &Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Handle control flow integrity failure for indirect function calls.
|
||||||
|
RECOVERABLE(cfi_bad_icall, CFIBadIcallData *Data, ValueHandle Function)
|
||||||
|
|
||||||
/// \brief Handle control flow integrity failures.
|
/// \brief Handle control flow integrity failures.
|
||||||
RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function,
|
RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function,
|
||||||
uptr VtableIsValid)
|
uptr VtableIsValid)
|
||||||
|
|
|
@ -156,6 +156,50 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
|
||||||
Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1")
|
Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1")
|
||||||
<< SrcModule << DstModule;
|
<< 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_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_v1_abort(
|
||||||
|
FunctionTypeMismatchData *Data, ValueHandle Function,
|
||||||
|
ValueHandle calleeRTTI, ValueHandle fnRTTI) {
|
||||||
|
GET_REPORT_OPTIONS(true);
|
||||||
|
if (handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts))
|
||||||
|
Die();
|
||||||
|
}
|
||||||
} // namespace __ubsan
|
} // namespace __ubsan
|
||||||
|
|
||||||
#endif // CAN_SANITIZE_UB
|
#endif // CAN_SANITIZE_UB
|
||||||
|
|
|
@ -33,6 +33,19 @@ void __ubsan_handle_dynamic_type_cache_miss(
|
||||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
void __ubsan_handle_dynamic_type_cache_miss_abort(
|
void __ubsan_handle_dynamic_type_cache_miss_abort(
|
||||||
DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash);
|
DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash);
|
||||||
|
|
||||||
|
struct FunctionTypeMismatchData;
|
||||||
|
|
||||||
|
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
|
||||||
|
__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_v1_abort(FunctionTypeMismatchData *Data,
|
||||||
|
ValueHandle Val,
|
||||||
|
ValueHandle calleeRTTI,
|
||||||
|
ValueHandle fnRTTI);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UBSAN_HANDLERS_CXX_H
|
#endif // UBSAN_HANDLERS_CXX_H
|
||||||
|
|
|
@ -21,6 +21,8 @@ INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss)
|
||||||
INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss_abort)
|
INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss_abort)
|
||||||
INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow)
|
INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow)
|
||||||
INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort)
|
INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort)
|
||||||
|
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1)
|
||||||
|
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1_abort)
|
||||||
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch)
|
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch)
|
||||||
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort)
|
INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort)
|
||||||
INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion)
|
INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion)
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#ifndef UBSAN_PLATFORM_H
|
#ifndef UBSAN_PLATFORM_H
|
||||||
#define UBSAN_PLATFORM_H
|
#define UBSAN_PLATFORM_H
|
||||||
|
|
||||||
|
#ifndef CAN_SANITIZE_UB
|
||||||
// Other platforms should be easy to add, and probably work as-is.
|
// Other platforms should be easy to add, and probably work as-is.
|
||||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
|
||||||
defined(__NetBSD__) || defined(__DragonFly__) || \
|
defined(__NetBSD__) || defined(__DragonFly__) || \
|
||||||
|
@ -21,5 +22,6 @@
|
||||||
#else
|
#else
|
||||||
# define CAN_SANITIZE_UB 0
|
# define CAN_SANITIZE_UB 0
|
||||||
#endif
|
#endif
|
||||||
|
#endif //CAN_SANITIZE_UB
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue