Libsanitizer: merge from trunk with merge.sh.

2019-11-05  Martin Liska  <mliska@suse.cz>

	* all source files: Merge from upstream r375507.

From-SVN: r277834
This commit is contained in:
Martin Liska 2019-11-05 14:54:57 +01:00 committed by Martin Liska
parent 9bae89924a
commit 3ca75cd550
126 changed files with 2696 additions and 2154 deletions

View File

@ -1,3 +1,7 @@
2019-11-05 Martin Liska <mliska@suse.cz>
* all source files: Merge from upstream r375507.
2019-10-22 Tamar Christina <tamar.christina@arm.com> 2019-10-22 Tamar Christina <tamar.christina@arm.com>
PR sanitizer/92154 PR sanitizer/92154

View File

@ -1,4 +1,4 @@
368656 375507
The first line of this file holds the svn revision number of the The first line of this file holds the svn revision number of the
last merge done from the master library sources. last merge done from the master library sources.

View File

@ -1075,7 +1075,7 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
} // namespace __lsan } // namespace __lsan
// ---------------------- Interface ---------------- {{{1 // ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
// ASan allocator doesn't reserve extra bytes, so normally we would // ASan allocator doesn't reserve extra bytes, so normally we would
// just return "size". We don't want to expose our redzone sizes, etc here. // just return "size". We don't want to expose our redzone sizes, etc here.

View File

@ -25,7 +25,7 @@ using namespace __asan;
static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset, static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
char *name, uptr name_size, char *name, uptr name_size,
uptr &region_address, uptr &region_size) { uptr *region_address, uptr *region_size) {
InternalMmapVector<StackVarDescr> vars; InternalMmapVector<StackVarDescr> vars;
vars.reserve(16); vars.reserve(16);
if (!ParseFrameDescription(frame_descr, &vars)) { if (!ParseFrameDescription(frame_descr, &vars)) {
@ -39,8 +39,8 @@ static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
// the whole name and then terminate with '\0'. // the whole name and then terminate with '\0'.
internal_strlcpy(name, vars[i].name_pos, internal_strlcpy(name, vars[i].name_pos,
Min(name_size, vars[i].name_len + 1)); Min(name_size, vars[i].name_len + 1));
region_address = addr - (offset - vars[i].beg); *region_address = addr - (offset - vars[i].beg);
region_size = vars[i].size; *region_size = vars[i].size;
return; return;
} }
} }
@ -108,7 +108,7 @@ const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
// region_{address,size} are already 0 // region_{address,size} are already 0
} else { } else {
FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name, FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name,
name_size, region_address, region_size); name_size, &region_address, &region_size);
} }
} else if (auto global = descr.AsGlobal()) { } else if (auto global = descr.AsGlobal()) {
region_kind = "global"; region_kind = "global";

View File

@ -203,7 +203,7 @@ class AddressDescription {
AddressDescription() = default; AddressDescription() = default;
// shouldLockThreadRegistry allows us to skip locking if we're sure we already // shouldLockThreadRegistry allows us to skip locking if we're sure we already
// have done it. // have done it.
AddressDescription(uptr addr, bool shouldLockThreadRegistry = true) explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
: AddressDescription(addr, 1, shouldLockThreadRegistry) {} : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
AddressDescription(uptr addr, uptr access_size, AddressDescription(uptr addr, uptr access_size,
bool shouldLockThreadRegistry = true); bool shouldLockThreadRegistry = true);

View File

@ -35,7 +35,8 @@ static void OnStackUnwind(const SignalContext &sig,
// corresponding code in the sanitizer_common and we use this callback to // corresponding code in the sanitizer_common and we use this callback to
// print it. // print it.
static_cast<const ScarinessScoreBase *>(callback_context)->Print(); static_cast<const ScarinessScoreBase *>(callback_context)->Print();
stack->Unwind(sig.pc, sig.bp, sig.context, fast); stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
fast);
} }
void ErrorDeadlySignal::Print() { void ErrorDeadlySignal::Print() {
@ -244,7 +245,7 @@ void ErrorInvalidPosixMemalignAlignment::Print() {
"ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: " "ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
"%zd, alignment must be a power of two and a multiple of sizeof(void*) " "%zd, alignment must be a power of two and a multiple of sizeof(void*) "
"== %zd (thread %s)\n", "== %zd (thread %s)\n",
alignment, sizeof(void*), AsanThreadIdAndName(tid).c_str()); // NOLINT alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str());
Printf("%s", d.Default()); Printf("%s", d.Default());
stack->Print(); stack->Print();
PrintHintAllocatorCannotReturnNull(); PrintHintAllocatorCannotReturnNull();

View File

@ -48,7 +48,8 @@ struct ErrorDeadlySignal : ErrorBase {
scariness.Scare(10, "stack-overflow"); scariness.Scare(10, "stack-overflow");
} else if (!signal.is_memory_access) { } else if (!signal.is_memory_access) {
scariness.Scare(10, "signal"); scariness.Scare(10, "signal");
} else if (signal.addr < GetPageSizeCached()) { } else if (signal.is_true_faulting_addr &&
signal.addr < GetPageSizeCached()) {
scariness.Scare(10, "null-deref"); scariness.Scare(10, "null-deref");
} else if (signal.addr == signal.pc) { } else if (signal.addr == signal.pc) {
scariness.Scare(60, "wild-jump"); scariness.Scare(60, "wild-jump");

View File

@ -139,10 +139,10 @@ ASAN_FLAG(
"If >= 2, detect operations like <, <=, >, >= and - on invalid pointer " "If >= 2, detect operations like <, <=, >, >= and - on invalid pointer "
"pairs (e.g. when pointers belong to different objects); " "pairs (e.g. when pointers belong to different objects); "
"If == 1, detect invalid operations only when both pointers are non-null.") "If == 1, detect invalid operations only when both pointers are non-null.")
ASAN_FLAG( ASAN_FLAG(bool, detect_container_overflow, true,
bool, detect_container_overflow, true, "If true, honor the container overflow annotations. See "
"If true, honor the container overflow annotations. See " "https://github.com/google/sanitizers/wiki/"
"https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow") "AddressSanitizerContainerOverflow")
ASAN_FLAG(int, detect_odr_violation, 2, ASAN_FLAG(int, detect_odr_violation, 2,
"If >=2, detect violation of One-Definition-Rule (ODR); " "If >=2, detect violation of One-Definition-Rule (ODR); "
"If ==1, detect ODR-violation only if the two variables " "If ==1, detect ODR-violation only if the two variables "
@ -158,5 +158,6 @@ ASAN_FLAG(bool, allocator_frees_and_returns_null_on_realloc_zero, true,
ASAN_FLAG(bool, verify_asan_link_order, true, ASAN_FLAG(bool, verify_asan_link_order, true,
"Check position of ASan runtime in library list (needs to be disabled" "Check position of ASan runtime in library list (needs to be disabled"
" when other library has to be preloaded system-wide)") " when other library has to be preloaded system-wide)")
ASAN_FLAG(bool, windows_hook_rtl_allocators, false, ASAN_FLAG(
"(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.") bool, windows_hook_rtl_allocators, false,
"(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")

View File

@ -154,6 +154,23 @@ static void CheckODRViolationViaIndicator(const Global *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) {
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 (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
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
@ -199,6 +216,8 @@ static void RegisterGlobal(const Global *g) {
// 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);
@ -208,8 +227,7 @@ static void RegisterGlobal(const Global *g) {
list_of_all_globals = l; list_of_all_globals = l;
if (g->has_dynamic_init) { if (g->has_dynamic_init) {
if (!dynamic_init_globals) { if (!dynamic_init_globals) {
dynamic_init_globals = dynamic_init_globals = new (allocator_for_globals) VectorOfGlobals;
new (allocator_for_globals) VectorOfGlobals; // NOLINT
dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity); dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity);
} }
DynInitGlobal dyn_global = { *g, false }; DynInitGlobal dyn_global = { *g, false };
@ -296,8 +314,7 @@ void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
} // namespace __asan } // namespace __asan
// ---------------------- Interface ---------------- {{{1 // ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
// Apply __asan_register_globals to all globals found in the same loaded // Apply __asan_register_globals to all globals found in the same loaded
// executable or shared library as `flag'. The flag tracks whether globals have // executable or shared library as `flag'. The flag tracks whether globals have
@ -345,7 +362,7 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
BlockingMutexLock lock(&mu_for_globals); BlockingMutexLock lock(&mu_for_globals);
if (!global_registration_site_vector) { if (!global_registration_site_vector) {
global_registration_site_vector = global_registration_site_vector =
new (allocator_for_globals) GlobalRegistrationSiteVector; // NOLINT new (allocator_for_globals) GlobalRegistrationSiteVector;
global_registration_site_vector->reserve(128); global_registration_site_vector->reserve(128);
} }
GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]}; GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};

View File

@ -15,8 +15,8 @@
namespace __asan { namespace __asan {
#pragma section(".ASAN$GA", read, write) // NOLINT #pragma section(".ASAN$GA", read, write)
#pragma section(".ASAN$GZ", read, write) // NOLINT #pragma section(".ASAN$GZ", read, write)
extern "C" __declspec(allocate(".ASAN$GA")) extern "C" __declspec(allocate(".ASAN$GA"))
ALIGNED(sizeof(__asan_global)) __asan_global __asan_globals_start = {}; ALIGNED(sizeof(__asan_global)) __asan_global __asan_globals_start = {};
extern "C" __declspec(allocate(".ASAN$GZ")) extern "C" __declspec(allocate(".ASAN$GZ"))
@ -49,8 +49,8 @@ static void unregister_dso_globals() {
} }
// Register globals // Register globals
#pragma section(".CRT$XCU", long, read) // NOLINT #pragma section(".CRT$XCU", long, read)
#pragma section(".CRT$XTX", long, read) // NOLINT #pragma section(".CRT$XTX", long, read)
extern "C" __declspec(allocate(".CRT$XCU")) extern "C" __declspec(allocate(".CRT$XCU"))
void (*const __asan_dso_reg_hook)() = &register_dso_globals; void (*const __asan_dso_reg_hook)() = &register_dso_globals;
extern "C" __declspec(allocate(".CRT$XTX")) extern "C" __declspec(allocate(".CRT$XTX"))

View File

@ -79,7 +79,7 @@ int OnExit() {
} // namespace __asan } // namespace __asan
// ---------------------- Wrappers ---------------- {{{1 // ---------------------- Wrappers ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
@ -164,6 +164,11 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
ASAN_MEMSET_IMPL(ctx, block, c, size); \ ASAN_MEMSET_IMPL(ctx, block, c, size); \
} while (false) } while (false)
#if CAN_SANITIZE_LEAKS
#define COMMON_INTERCEPTOR_STRERROR() \
__lsan::ScopedInterceptorDisabler disabler
#endif
#include "sanitizer_common/sanitizer_common_interceptors.inc" #include "sanitizer_common/sanitizer_common_interceptors.inc"
#include "sanitizer_common/sanitizer_signal_interceptors.inc" #include "sanitizer_common/sanitizer_signal_interceptors.inc"
@ -373,26 +378,26 @@ DEFINE_REAL(char*, index, const char *string, int c)
// For both strcat() and strncat() we need to check the validity of |to| // For both strcat() and strncat() we need to check the validity of |to|
// argument irrespective of the |from| length. // argument irrespective of the |from| length.
INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT INTERCEPTOR(char *, strcat, char *to, const char *from) {
void *ctx; void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT ASAN_INTERCEPTOR_ENTER(ctx, strcat);
ENSURE_ASAN_INITED(); ENSURE_ASAN_INITED();
if (flags()->replace_str) { if (flags()->replace_str) {
uptr from_length = REAL(strlen)(from); uptr from_length = REAL(strlen)(from);
ASAN_READ_RANGE(ctx, from, from_length + 1); ASAN_READ_RANGE(ctx, from, from_length + 1);
uptr to_length = REAL(strlen)(to); uptr to_length = REAL(strlen)(to);
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
// If the copying actually happens, the |from| string should not overlap // If the copying actually happens, the |from| string should not overlap
// with the resulting string starting at |to|, which has a length of // with the resulting string starting at |to|, which has a length of
// to_length + from_length + 1. // to_length + from_length + 1.
if (from_length > 0) { if (from_length > 0) {
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
from, from_length + 1); from_length + 1);
}
} }
return REAL(strcat)(to, from);
} }
return REAL(strcat)(to, from); // NOLINT
}
INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
void *ctx; void *ctx;
@ -413,16 +418,17 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
return REAL(strncat)(to, from, size); return REAL(strncat)(to, from, size);
} }
INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT INTERCEPTOR(char *, strcpy, char *to, const char *from) {
void *ctx; void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
#if SANITIZER_MAC #if SANITIZER_MAC
if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT if (UNLIKELY(!asan_inited))
return REAL(strcpy)(to, from);
#endif #endif
// strcpy is called from malloc_default_purgeable_zone() // strcpy is called from malloc_default_purgeable_zone()
// in __asan::ReplaceSystemAlloc() on Mac. // in __asan::ReplaceSystemAlloc() on Mac.
if (asan_init_is_running) { if (asan_init_is_running) {
return REAL(strcpy)(to, from); // NOLINT return REAL(strcpy)(to, from);
} }
ENSURE_ASAN_INITED(); ENSURE_ASAN_INITED();
if (flags()->replace_str) { if (flags()->replace_str) {
@ -431,7 +437,7 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
ASAN_READ_RANGE(ctx, from, from_size); ASAN_READ_RANGE(ctx, from, from_size);
ASAN_WRITE_RANGE(ctx, to, from_size); ASAN_WRITE_RANGE(ctx, to, from_size);
} }
return REAL(strcpy)(to, from); // NOLINT return REAL(strcpy)(to, from);
} }
INTERCEPTOR(char*, strdup, const char *s) { INTERCEPTOR(char*, strdup, const char *s) {
@ -479,8 +485,7 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
return REAL(strncpy)(to, from, size); return REAL(strncpy)(to, from, size);
} }
INTERCEPTOR(long, strtol, const char *nptr, // NOLINT INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
char **endptr, int base) {
void *ctx; void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtol); ASAN_INTERCEPTOR_ENTER(ctx, strtol);
ENSURE_ASAN_INITED(); ENSURE_ASAN_INITED();
@ -488,7 +493,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
return REAL(strtol)(nptr, endptr, base); return REAL(strtol)(nptr, endptr, base);
} }
char *real_endptr; char *real_endptr;
long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT long result = REAL(strtol)(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return result; return result;
} }
@ -514,7 +519,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
return result; return result;
} }
INTERCEPTOR(long, atol, const char *nptr) { // NOLINT INTERCEPTOR(long, atol, const char *nptr) {
void *ctx; void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atol); ASAN_INTERCEPTOR_ENTER(ctx, atol);
#if SANITIZER_MAC #if SANITIZER_MAC
@ -525,15 +530,14 @@ INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
return REAL(atol)(nptr); return REAL(atol)(nptr);
} }
char *real_endptr; char *real_endptr;
long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT long result = REAL(strtol)(nptr, &real_endptr, 10);
FixRealStrtolEndptr(nptr, &real_endptr); FixRealStrtolEndptr(nptr, &real_endptr);
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
return result; return result;
} }
#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
char **endptr, int base) {
void *ctx; void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtoll); ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
ENSURE_ASAN_INITED(); ENSURE_ASAN_INITED();
@ -541,12 +545,12 @@ INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
return REAL(strtoll)(nptr, endptr, base); return REAL(strtoll)(nptr, endptr, base);
} }
char *real_endptr; char *real_endptr;
long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT long long result = REAL(strtoll)(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return result; return result;
} }
INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT INTERCEPTOR(long long, atoll, const char *nptr) {
void *ctx; void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atoll); ASAN_INTERCEPTOR_ENTER(ctx, atoll);
ENSURE_ASAN_INITED(); ENSURE_ASAN_INITED();
@ -554,31 +558,66 @@ INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
return REAL(atoll)(nptr); return REAL(atoll)(nptr);
} }
char *real_endptr; char *real_endptr;
long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT long long result = REAL(strtoll)(nptr, &real_endptr, 10);
FixRealStrtolEndptr(nptr, &real_endptr); FixRealStrtolEndptr(nptr, &real_endptr);
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
return result; return result;
} }
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
#if ASAN_INTERCEPT___CXA_ATEXIT #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
static void AtCxaAtexit(void *unused) { static void AtCxaAtexit(void *unused) {
(void)unused; (void)unused;
StopInitOrderChecking(); StopInitOrderChecking();
} }
#endif
#if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
void *dso_handle) { void *dso_handle) {
#if SANITIZER_MAC #if SANITIZER_MAC
if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
#endif #endif
ENSURE_ASAN_INITED(); ENSURE_ASAN_INITED();
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
int res = REAL(__cxa_atexit)(func, arg, dso_handle); int res = REAL(__cxa_atexit)(func, arg, dso_handle);
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
return res; return res;
} }
#endif // ASAN_INTERCEPT___CXA_ATEXIT #endif // ASAN_INTERCEPT___CXA_ATEXIT
#if ASAN_INTERCEPT_ATEXIT
INTERCEPTOR(int, atexit, void (*func)()) {
ENSURE_ASAN_INITED();
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
// Avoid calling real atexit as it is unrechable on at least on Linux.
int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
return res;
}
#endif
#if ASAN_INTERCEPT_PTHREAD_ATFORK
extern "C" {
extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
void (*child)());
};
INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
void (*child)()) {
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
// REAL(pthread_atfork) cannot be called due to symbol indirections at least
// on NetBSD
return _pthread_atfork(prepare, parent, child);
}
#endif
#if ASAN_INTERCEPT_VFORK #if ASAN_INTERCEPT_VFORK
DEFINE_REAL(int, vfork) DEFINE_REAL(int, vfork)
DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
@ -594,8 +633,8 @@ void InitializeAsanInterceptors() {
InitializeSignalInterceptors(); InitializeSignalInterceptors();
// Intercept str* functions. // Intercept str* functions.
ASAN_INTERCEPT_FUNC(strcat); // NOLINT ASAN_INTERCEPT_FUNC(strcat);
ASAN_INTERCEPT_FUNC(strcpy); // NOLINT ASAN_INTERCEPT_FUNC(strcpy);
ASAN_INTERCEPT_FUNC(strncat); ASAN_INTERCEPT_FUNC(strncat);
ASAN_INTERCEPT_FUNC(strncpy); ASAN_INTERCEPT_FUNC(strncpy);
ASAN_INTERCEPT_FUNC(strdup); ASAN_INTERCEPT_FUNC(strdup);
@ -661,6 +700,14 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(__cxa_atexit); ASAN_INTERCEPT_FUNC(__cxa_atexit);
#endif #endif
#if ASAN_INTERCEPT_ATEXIT
ASAN_INTERCEPT_FUNC(atexit);
#endif
#if ASAN_INTERCEPT_PTHREAD_ATFORK
ASAN_INTERCEPT_FUNC(pthread_atfork);
#endif
#if ASAN_INTERCEPT_VFORK #if ASAN_INTERCEPT_VFORK
ASAN_INTERCEPT_FUNC(vfork); ASAN_INTERCEPT_FUNC(vfork);
#endif #endif

View File

@ -80,12 +80,7 @@ void InitializePlatformInterceptors();
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \ #if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
!SANITIZER_NETBSD !SANITIZER_NETBSD
# define ASAN_INTERCEPT___CXA_THROW 1 # define ASAN_INTERCEPT___CXA_THROW 1
# if ! defined(ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION) \ # define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
|| 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
@ -104,6 +99,12 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT___CXA_ATEXIT 0 # define ASAN_INTERCEPT___CXA_ATEXIT 0
#endif #endif
#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_ATEXIT 1
#else
# define ASAN_INTERCEPT_ATEXIT 0
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID #if SANITIZER_LINUX && !SANITIZER_ANDROID
# define ASAN_INTERCEPT___STRDUP 1 # define ASAN_INTERCEPT___STRDUP 1
#else #else
@ -117,6 +118,12 @@ void InitializePlatformInterceptors();
# define ASAN_INTERCEPT_VFORK 0 # define ASAN_INTERCEPT_VFORK 0
#endif #endif
#if SANITIZER_NETBSD
# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
#else
# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
#endif
DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size) DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(char*, strchr, const char *str, int c)
DECLARE_REAL(SIZE_T, strlen, const char *s) DECLARE_REAL(SIZE_T, strlen, const char *s)

View File

@ -16,7 +16,7 @@
#include "asan_stack.h" #include "asan_stack.h"
#include "asan_suppressions.h" #include "asan_suppressions.h"
using namespace __asan; // NOLINT using namespace __asan;
void *__asan_memcpy(void *to, const void *from, uptr size) { void *__asan_memcpy(void *to, const void *from, uptr size) {
ASAN_MEMCPY_IMPL(nullptr, to, from, size); ASAN_MEMCPY_IMPL(nullptr, to, from, size);

View File

@ -205,7 +205,7 @@ void asan_dispatch_call_block_and_release(void *block) {
} // namespace __asan } // namespace __asan
using namespace __asan; // NOLINT using namespace __asan;
// Wrap |ctxt| and |func| into an asan_block_context_t. // Wrap |ctxt| and |func| into an asan_block_context_t.
// The caller retains control of the allocated context. // The caller retains control of the allocated context.

View File

@ -27,7 +27,7 @@
#include "asan_stack.h" #include "asan_stack.h"
// ---------------------- Replacement functions ---------------- {{{1 // ---------------------- Replacement functions ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
static uptr allocated_for_dlsym; static uptr allocated_for_dlsym;
static uptr last_dlsym_alloc_size_in_words; static uptr last_dlsym_alloc_size_in_words;

View File

@ -54,7 +54,7 @@ size_t WINAPI HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
} }
using namespace __asan; // NOLINT using namespace __asan;
// MT: Simply defining functions with the same signature in *.obj // MT: Simply defining functions with the same signature in *.obj
// files overrides the standard functions in the CRT. // files overrides the standard functions in the CRT.
@ -528,10 +528,11 @@ void ReplaceSystemMalloc() {
(uptr)WRAP(RtlAllocateHeap), (uptr)WRAP(RtlAllocateHeap),
(uptr *)&REAL(RtlAllocateHeap)); (uptr *)&REAL(RtlAllocateHeap));
} else { } else {
#define INTERCEPT_UCRT_FUNCTION(func) \ #define INTERCEPT_UCRT_FUNCTION(func) \
if (!INTERCEPT_FUNCTION_DLLIMPORT("ucrtbase.dll", \ if (!INTERCEPT_FUNCTION_DLLIMPORT( \
"api-ms-win-core-heap-l1-1-0.dll", func)) \ "ucrtbase.dll", "api-ms-win-core-heap-l1-1-0.dll", func)) { \
VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); \
}
INTERCEPT_UCRT_FUNCTION(HeapAlloc); INTERCEPT_UCRT_FUNCTION(HeapAlloc);
INTERCEPT_UCRT_FUNCTION(HeapFree); INTERCEPT_UCRT_FUNCTION(HeapFree);
INTERCEPT_UCRT_FUNCTION(HeapReAlloc); INTERCEPT_UCRT_FUNCTION(HeapReAlloc);

View File

@ -163,7 +163,7 @@ static const u64 kDefaultShort64bitShadowOffset =
static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37;
static const u64 kPPC64_ShadowOffset64 = 1ULL << 41; static const u64 kPPC64_ShadowOffset64 = 1ULL << 44;
static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52; static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000 static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000
static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000

View File

@ -48,7 +48,7 @@ COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[]
#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE #define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
#endif #endif
using namespace __asan; // NOLINT using namespace __asan;
// FreeBSD prior v9.2 have wrong definition of 'size_t'. // FreeBSD prior v9.2 have wrong definition of 'size_t'.
// http://svnweb.freebsd.org/base?view=revision&revision=232261 // http://svnweb.freebsd.org/base?view=revision&revision=232261

View File

@ -92,7 +92,7 @@ void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
} // namespace __asan } // namespace __asan
// ---------------------- Interface ---------------- {{{1 // ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
// Current implementation of __asan_(un)poison_memory_region doesn't check // Current implementation of __asan_(un)poison_memory_region doesn't check
// that user program (un)poisons the memory it owns. It poisons memory // that user program (un)poisons the memory it owns. It poisons memory

View File

@ -410,8 +410,12 @@ static bool IsInvalidPointerPair(uptr a1, uptr a2) {
static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
switch (flags()->detect_invalid_pointer_pairs) { switch (flags()->detect_invalid_pointer_pairs) {
case 0 : return; case 0:
case 1 : if (p1 == nullptr || p2 == nullptr) return; break; return;
case 1:
if (p1 == nullptr || p2 == nullptr)
return;
break;
} }
uptr a1 = reinterpret_cast<uptr>(p1); uptr a1 = reinterpret_cast<uptr>(p1);
@ -472,7 +476,7 @@ void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
} // namespace __asan } // namespace __asan
// --------------------------- Interface --------------------- {{{1 // --------------------------- Interface --------------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
uptr access_size, u32 exp) { uptr access_size, u32 exp) {

View File

@ -181,11 +181,11 @@ static void ThreadStartHook(void *hook, uptr os_id) {
asanThreadRegistry().GetThreadLocked(thread->tid())->status; asanThreadRegistry().GetThreadLocked(thread->tid())->status;
DCHECK(status == ThreadStatusCreated || status == ThreadStatusRunning); DCHECK(status == ThreadStatusCreated || status == ThreadStatusRunning);
// Determine whether we are starting or restarting the thread. // Determine whether we are starting or restarting the thread.
if (status == ThreadStatusCreated) if (status == ThreadStatusCreated) {
// In lieu of AsanThread::ThreadStart. // In lieu of AsanThread::ThreadStart.
asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular, asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular,
nullptr); nullptr);
else { } else {
// In a thread restart, a thread may resume execution at an // In a thread restart, a thread may resume execution at an
// arbitrary function entry point, with its stack and TLS state // arbitrary function entry point, with its stack and TLS state
// reset. We unpoison the stack in that case. // reset. We unpoison the stack in that case.

View File

@ -402,7 +402,6 @@ static void AsanInitInternal() {
asan_init_is_running = true; asan_init_is_running = true;
CacheBinaryName(); CacheBinaryName();
CheckASLR();
// Initialize flags. This must be done early, because most of the // Initialize flags. This must be done early, because most of the
// initialization steps look at flags(). // initialization steps look at flags().
@ -450,6 +449,7 @@ static void AsanInitInternal() {
SetLowLevelAllocateCallback(OnLowLevelAllocate); SetLowLevelAllocateCallback(OnLowLevelAllocate);
InitializeAsanInterceptors(); InitializeAsanInterceptors();
CheckASLR();
// Enable system log ("adb logcat") on Android. // Enable system log ("adb logcat") on Android.
// Doing this before interceptors are initialized crashes in: // Doing this before interceptors are initialized crashes in:
@ -542,7 +542,7 @@ void AsanInitFromRtl() {
// (and thus normal initializers from .preinit_array or modules haven't run). // (and thus normal initializers from .preinit_array or modules haven't run).
class AsanInitializer { class AsanInitializer {
public: // NOLINT public:
AsanInitializer() { AsanInitializer() {
AsanInitFromRtl(); AsanInitFromRtl();
} }
@ -554,7 +554,7 @@ static AsanInitializer asan_initializer;
} // namespace __asan } // namespace __asan
// ---------------------- Interface ---------------- {{{1 // ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
void NOINLINE __asan_handle_no_return() { void NOINLINE __asan_handle_no_return() {
if (asan_init_is_running) if (asan_init_is_running)

View File

@ -43,7 +43,7 @@ struct ScarinessScoreBase {
internal_strlcat(descr, "-", sizeof(descr)); internal_strlcat(descr, "-", sizeof(descr));
internal_strlcat(descr, reason, sizeof(descr)); internal_strlcat(descr, reason, sizeof(descr));
score += add_to_score; score += add_to_score;
}; }
int GetScore() const { return score; } int GetScore() const { return score; }
const char *GetDescription() const { return descr; } const char *GetDescription() const { return descr; }
void Print() const { void Print() const {

View File

@ -30,14 +30,13 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
CHECK_EQ(((end + 1) % GetMmapGranularity()), 0); CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
uptr size = end - beg + 1; uptr size = end - beg + 1;
DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb. DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
if (!MmapFixedNoReserve(beg, size, name)) { if (!MmapFixedSuperNoReserve(beg, size, name)) {
Report( Report(
"ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. " "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
"Perhaps you're using ulimit -v\n", "Perhaps you're using ulimit -v\n",
size); size);
Abort(); Abort();
} }
SetShadowRegionHugePageMode(beg, size);
if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size); if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
} }

View File

@ -133,7 +133,7 @@ static void PrintAccumulatedStats() {
} // namespace __asan } // namespace __asan
// ---------------------- Interface ---------------- {{{1 // ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
uptr __sanitizer_get_current_allocated_bytes() { uptr __sanitizer_get_current_allocated_bytes() {
AsanStats stats; AsanStats stats;

View File

@ -36,7 +36,7 @@ SANITIZER_INTERFACE_WEAK_DEF(const char *, __asan_default_suppressions, void) {
void InitializeSuppressions() { void InitializeSuppressions() {
CHECK_EQ(nullptr, suppression_ctx); CHECK_EQ(nullptr, suppression_ctx);
suppression_ctx = new (suppression_placeholder) // NOLINT suppression_ctx = new (suppression_placeholder)
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
suppression_ctx->ParseFromFile(flags()->suppressions); suppression_ctx->ParseFromFile(flags()->suppressions);
if (&__asan_default_suppressions) if (&__asan_default_suppressions)

View File

@ -367,8 +367,9 @@ uptr AsanThread::GetStackVariableShadowStart(uptr addr) {
} else if (has_fake_stack()) { } else if (has_fake_stack()) {
bottom = fake_stack()->AddrIsInFakeStack(addr); bottom = fake_stack()->AddrIsInFakeStack(addr);
CHECK(bottom); CHECK(bottom);
} else } else {
return 0; return 0;
}
uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr. uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
@ -505,7 +506,7 @@ void EnsureMainThreadIDIsCorrect() {
} // namespace __lsan } // namespace __lsan
// ---------------------- Interface ---------------- {{{1 // ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT using namespace __asan;
extern "C" { extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE

View File

@ -29,7 +29,7 @@
#include "sanitizer_common/sanitizer_win.h" #include "sanitizer_common/sanitizer_win.h"
#include "sanitizer_common/sanitizer_win_defs.h" #include "sanitizer_common/sanitizer_win_defs.h"
using namespace __asan; // NOLINT using namespace __asan;
extern "C" { extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
@ -106,7 +106,7 @@ INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
INTERCEPTOR_WINAPI(EXCEPTION_DISPOSITION, __C_specific_handler, INTERCEPTOR_WINAPI(EXCEPTION_DISPOSITION, __C_specific_handler,
_EXCEPTION_RECORD *a, void *b, _CONTEXT *c, _EXCEPTION_RECORD *a, void *b, _CONTEXT *c,
_DISPATCHER_CONTEXT *d) { // NOLINT _DISPATCHER_CONTEXT *d) {
CHECK(REAL(__C_specific_handler)); CHECK(REAL(__C_specific_handler));
__asan_handle_no_return(); __asan_handle_no_return();
return REAL(__C_specific_handler)(a, b, c, d); return REAL(__C_specific_handler)(a, b, c, d);
@ -362,7 +362,7 @@ bool HandleDlopenInit() {
// beginning of C++ initialization. We set our priority to XCAB to run // beginning of C++ initialization. We set our priority to XCAB to run
// immediately after the CRT runs. This way, our exception filter is called // immediately after the CRT runs. This way, our exception filter is called
// first and we can delegate to their filter if appropriate. // first and we can delegate to their filter if appropriate.
#pragma section(".CRT$XCAB", long, read) // NOLINT #pragma section(".CRT$XCAB", long, read)
__declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() = __declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() =
__asan_set_seh_filter; __asan_set_seh_filter;
@ -375,7 +375,7 @@ static void NTAPI asan_thread_init(void *module, DWORD reason, void *reserved) {
__asan_init(); __asan_init();
} }
#pragma section(".CRT$XLAB", long, read) // NOLINT #pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)( __declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)(
void *, unsigned long, void *) = asan_thread_init; void *, unsigned long, void *) = asan_thread_init;
#endif #endif
@ -389,7 +389,7 @@ static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
} }
} }
#pragma section(".CRT$XLY", long, read) // NOLINT #pragma section(".CRT$XLY", long, read)
__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)( __declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)(
void *, unsigned long, void *) = asan_thread_exit; void *, unsigned long, void *) = asan_thread_exit;

View File

@ -67,10 +67,10 @@ INTERCEPT_LIBRARY_FUNCTION(memcmp);
INTERCEPT_LIBRARY_FUNCTION(memcpy); INTERCEPT_LIBRARY_FUNCTION(memcpy);
INTERCEPT_LIBRARY_FUNCTION(memmove); INTERCEPT_LIBRARY_FUNCTION(memmove);
INTERCEPT_LIBRARY_FUNCTION(memset); INTERCEPT_LIBRARY_FUNCTION(memset);
INTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT INTERCEPT_LIBRARY_FUNCTION(strcat);
INTERCEPT_LIBRARY_FUNCTION(strchr); INTERCEPT_LIBRARY_FUNCTION(strchr);
INTERCEPT_LIBRARY_FUNCTION(strcmp); INTERCEPT_LIBRARY_FUNCTION(strcmp);
INTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT INTERCEPT_LIBRARY_FUNCTION(strcpy);
INTERCEPT_LIBRARY_FUNCTION(strcspn); INTERCEPT_LIBRARY_FUNCTION(strcspn);
INTERCEPT_LIBRARY_FUNCTION(strdup); INTERCEPT_LIBRARY_FUNCTION(strdup);
INTERCEPT_LIBRARY_FUNCTION(strlen); INTERCEPT_LIBRARY_FUNCTION(strlen);
@ -135,7 +135,7 @@ static int asan_dll_thunk_init() {
return 0; return 0;
} }
#pragma section(".CRT$XIB", long, read) // NOLINT #pragma section(".CRT$XIB", long, read)
__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init; __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
static void WINAPI asan_thread_init(void *mod, unsigned long reason, static void WINAPI asan_thread_init(void *mod, unsigned long reason,
@ -143,7 +143,7 @@ static void WINAPI asan_thread_init(void *mod, unsigned long reason,
if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init(); if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
} }
#pragma section(".CRT$XLAB", long, read) // NOLINT #pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *, __declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
unsigned long, void *) = asan_thread_init; unsigned long, void *) = asan_thread_init;

View File

@ -32,12 +32,12 @@
#include "asan_interface.inc" #include "asan_interface.inc"
// First, declare CRT sections we'll be using in this file // First, declare CRT sections we'll be using in this file
#pragma section(".CRT$XIB", long, read) // NOLINT #pragma section(".CRT$XIB", long, read)
#pragma section(".CRT$XID", long, read) // NOLINT #pragma section(".CRT$XID", long, read)
#pragma section(".CRT$XCAB", long, read) // NOLINT #pragma section(".CRT$XCAB", long, read)
#pragma section(".CRT$XTW", long, read) // NOLINT #pragma section(".CRT$XTW", long, read)
#pragma section(".CRT$XTY", long, read) // NOLINT #pragma section(".CRT$XTY", long, read)
#pragma section(".CRT$XLAB", long, read) // NOLINT #pragma section(".CRT$XLAB", long, read)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Define a copy of __asan_option_detect_stack_use_after_return that should be // Define a copy of __asan_option_detect_stack_use_after_return that should be

View File

@ -112,7 +112,7 @@ void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
} // extern "C" } // extern "C"
template <typename T> template <typename T>
void dfsan_set_label(dfsan_label label, T &data) { // NOLINT void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
dfsan_set_label(label, (void *)&data, sizeof(T)); dfsan_set_label(label, (void *)&data, sizeof(T));
} }

View File

@ -17,10 +17,10 @@
extern "C" { extern "C" {
#endif #endif
typedef char __tsan_atomic8; typedef char __tsan_atomic8;
typedef short __tsan_atomic16; // NOLINT typedef short __tsan_atomic16;
typedef int __tsan_atomic32; typedef int __tsan_atomic32;
typedef long __tsan_atomic64; // NOLINT typedef long __tsan_atomic64;
#if defined(__SIZEOF_INT128__) \ #if defined(__SIZEOF_INT128__) \
|| (__clang_major__ * 100 + __clang_minor__ >= 302) || (__clang_major__ * 100 + __clang_minor__ >= 302)
__extension__ typedef __int128 __tsan_atomic128; __extension__ typedef __int128 __tsan_atomic128;

View File

@ -0,0 +1,32 @@
//===-- sanitizer/ubsan_interface.h -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of UBSanitizer (UBSan).
//
// Public interface header.
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_UBSAN_INTERFACE_H
#define SANITIZER_UBSAN_INTERFACE_H
#ifdef __cplusplus
extern "C" {
#endif
/// User-provided default option settings.
///
/// You can provide your own implementation of this function to return a string
/// containing UBSan runtime options (for example,
/// <c>verbosity=1:halt_on_error=0</c>).
///
/// \returns Default options string.
const char* __ubsan_default_options(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // SANITIZER_UBSAN_INTERFACE_H

View File

@ -272,9 +272,9 @@ const interpose_substitution substitution_##func_name[] \
// INTERCEPT_FUNCTION macro, only its name. // INTERCEPT_FUNCTION macro, only its name.
namespace __interception { namespace __interception {
#if defined(_WIN64) #if defined(_WIN64)
typedef unsigned long long uptr; // NOLINT typedef unsigned long long uptr;
#else #else
typedef unsigned long uptr; // NOLINT typedef unsigned long uptr;
#endif // _WIN64 #endif // _WIN64
} // namespace __interception } // namespace __interception

View File

@ -883,8 +883,8 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
// Check that the module header is full and present. // Check that the module header is full and present.
RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0); RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew); RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ" if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0" headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
headers->FileHeader.SizeOfOptionalHeader < headers->FileHeader.SizeOfOptionalHeader <
sizeof(IMAGE_OPTIONAL_HEADER)) { sizeof(IMAGE_OPTIONAL_HEADER)) {
return 0; return 0;
@ -963,8 +963,8 @@ bool OverrideImportedFunction(const char *module_to_patch,
// Check that the module header is full and present. // Check that the module header is full and present.
RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0); RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew); RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ" if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0" headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
headers->FileHeader.SizeOfOptionalHeader < headers->FileHeader.SizeOfOptionalHeader <
sizeof(IMAGE_OPTIONAL_HEADER)) { sizeof(IMAGE_OPTIONAL_HEADER)) {
return false; return false;

View File

@ -50,7 +50,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(
} }
} }
using namespace __lsan; // NOLINT using namespace __lsan;
static void InitializeFlags() { static void InitializeFlags() {
// Set all the default values. // Set all the default values.
@ -89,7 +89,7 @@ static void InitializeFlags() {
static void OnStackUnwind(const SignalContext &sig, const void *, static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) { BufferedStackTrace *stack) {
stack->Unwind(sig.pc, sig.bp, sig.context, stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
common_flags()->fast_unwind_on_fatal); common_flags()->fast_unwind_on_fatal);
} }

View File

@ -84,7 +84,7 @@ static const char kStdSuppressions[] =
void InitializeSuppressions() { void InitializeSuppressions() {
CHECK_EQ(nullptr, suppression_ctx); CHECK_EQ(nullptr, suppression_ctx);
suppression_ctx = new (suppression_placeholder) // NOLINT suppression_ctx = new (suppression_placeholder)
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
suppression_ctx->ParseFromFile(flags()->suppressions); suppression_ctx->ParseFromFile(flags()->suppressions);
if (&__lsan_default_suppressions) if (&__lsan_default_suppressions)
@ -104,7 +104,7 @@ InternalMmapVector<RootRegion> const *GetRootRegions() { return root_regions; }
void InitializeRootRegions() { void InitializeRootRegions() {
CHECK(!root_regions); CHECK(!root_regions);
ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)]; ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)];
root_regions = new (placeholder) InternalMmapVector<RootRegion>(); // NOLINT root_regions = new (placeholder) InternalMmapVector<RootRegion>();
} }
const char *MaybeCallLsanDefaultOptions() { const char *MaybeCallLsanDefaultOptions() {
@ -162,7 +162,7 @@ void ScanRangeForPointers(uptr begin, uptr end,
uptr pp = begin; uptr pp = begin;
if (pp % alignment) if (pp % alignment)
pp = pp + alignment - pp % alignment; pp = pp + alignment - pp % alignment;
for (; pp + sizeof(void *) <= end; pp += alignment) { // NOLINT for (; pp + sizeof(void *) <= end; pp += alignment) {
void *p = *reinterpret_cast<void **>(pp); void *p = *reinterpret_cast<void **>(pp);
if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue; if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
uptr chunk = PointsIntoChunk(p); uptr chunk = PointsIntoChunk(p);
@ -535,7 +535,7 @@ static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) {
if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id) if (i >= suspended_threads.size() || suspended_threads[i] != tctx->os_id)
Report("Running thread %d was not suspended. False leaks are possible.\n", Report("Running thread %d was not suspended. False leaks are possible.\n",
tctx->os_id); tctx->os_id);
}; }
} }
static void ReportUnsuspendedThreads( static void ReportUnsuspendedThreads(
@ -570,11 +570,7 @@ static bool CheckForLeaks() {
EnsureMainThreadIDIsCorrect(); EnsureMainThreadIDIsCorrect();
CheckForLeaksParam param; CheckForLeaksParam param;
param.success = false; param.success = false;
LockThreadRegistry(); LockStuffAndStopTheWorld(CheckForLeaksCallback, &param);
LockAllocator();
DoStopTheWorld(CheckForLeaksCallback, &param);
UnlockAllocator();
UnlockThreadRegistry();
if (!param.success) { if (!param.success) {
Report("LeakSanitizer has encountered a fatal error.\n"); Report("LeakSanitizer has encountered a fatal error.\n");
@ -794,7 +790,7 @@ void EnableInThisThread() { }
} }
#endif // CAN_SANITIZE_LEAKS #endif // CAN_SANITIZE_LEAKS
using namespace __lsan; // NOLINT using namespace __lsan;
extern "C" { extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE

View File

@ -129,8 +129,9 @@ struct RootRegion {
InternalMmapVector<RootRegion> const *GetRootRegions(); InternalMmapVector<RootRegion> const *GetRootRegions();
void ScanRootRegion(Frontier *frontier, RootRegion const &region, void ScanRootRegion(Frontier *frontier, RootRegion const &region,
uptr region_begin, uptr region_end, bool is_readable); uptr region_begin, uptr region_end, bool is_readable);
// Run stoptheworld while holding any platform-specific locks. // Run stoptheworld while holding any platform-specific locks, as well as the
void DoStopTheWorld(StopTheWorldCallback callback, void* argument); // allocator and thread registry locks.
void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void* argument);
void ScanRangeForPointers(uptr begin, uptr end, void ScanRangeForPointers(uptr begin, uptr end,
Frontier *frontier, Frontier *frontier,

View File

@ -115,10 +115,14 @@ void HandleLeaks() {
if (common_flags()->exitcode) Die(); if (common_flags()->exitcode) Die();
} }
static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size, static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
void *data) { size_t size, void *data) {
LockThreadRegistry();
LockAllocator();
DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data); DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
StopTheWorld(param->callback, param->argument); StopTheWorld(param->callback, param->argument);
UnlockAllocator();
UnlockThreadRegistry();
return 1; return 1;
} }
@ -130,9 +134,9 @@ static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
// while holding the libdl lock in the parent thread, we can safely reenter it // while holding the libdl lock in the parent thread, we can safely reenter it
// in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr() // in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr()
// callback in the parent thread. // callback in the parent thread.
void DoStopTheWorld(StopTheWorldCallback callback, void *argument) { void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
DoStopTheWorldParam param = {callback, argument}; DoStopTheWorldParam param = {callback, argument};
dl_iterate_phdr(DoStopTheWorldCallback, &param); dl_iterate_phdr(LockStuffAndStopTheWorldCallback, &param);
} }
} // namespace __lsan } // namespace __lsan

View File

@ -193,8 +193,12 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {
// causes rare race conditions. // causes rare race conditions.
void HandleLeaks() {} void HandleLeaks() {}
void DoStopTheWorld(StopTheWorldCallback callback, void *argument) { void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
LockThreadRegistry();
LockAllocator();
StopTheWorld(callback, argument); StopTheWorld(callback, argument);
UnlockAllocator();
UnlockThreadRegistry();
} }
} // namespace __lsan } // namespace __lsan

View File

@ -345,6 +345,55 @@ INTERCEPTOR(void, thr_exit, tid_t *state) {
#define LSAN_MAYBE_INTERCEPT_THR_EXIT #define LSAN_MAYBE_INTERCEPT_THR_EXIT
#endif #endif
#if SANITIZER_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
void *dso_handle) {
__lsan::ScopedInterceptorDisabler disabler;
return REAL(__cxa_atexit)(func, arg, dso_handle);
}
#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
#else
#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
#endif
#if SANITIZER_INTERCEPT_ATEXIT
INTERCEPTOR(int, atexit, void (*f)()) {
__lsan::ScopedInterceptorDisabler disabler;
return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0);
}
#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
#else
#define LSAN_MAYBE_INTERCEPT_ATEXIT
#endif
#if SANITIZER_INTERCEPT_PTHREAD_ATFORK
extern "C" {
extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
void (*child)());
};
INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
void (*child)()) {
__lsan::ScopedInterceptorDisabler disabler;
// REAL(pthread_atfork) cannot be called due to symbol indirections at least
// on NetBSD
return _pthread_atfork(prepare, parent, child);
}
#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
#else
#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
#endif
#if SANITIZER_INTERCEPT_STRERROR
INTERCEPTOR(char *, strerror, int errnum) {
__lsan::ScopedInterceptorDisabler disabler;
return REAL(strerror)(errnum);
}
#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
#else
#define LSAN_MAYBE_INTERCEPT_STRERROR
#endif
struct ThreadParam { struct ThreadParam {
void *(*callback)(void *arg); void *(*callback)(void *arg);
void *param; void *param;
@ -454,6 +503,12 @@ void InitializeInterceptors() {
LSAN_MAYBE_INTERCEPT__LWP_EXIT; LSAN_MAYBE_INTERCEPT__LWP_EXIT;
LSAN_MAYBE_INTERCEPT_THR_EXIT; LSAN_MAYBE_INTERCEPT_THR_EXIT;
LSAN_MAYBE_INTERCEPT___CXA_ATEXIT;
LSAN_MAYBE_INTERCEPT_ATEXIT;
LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
LSAN_MAYBE_INTERCEPT_STRERROR;
#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
Report("LeakSanitizer: failed to create thread key.\n"); Report("LeakSanitizer: failed to create thread key.\n");

View File

@ -90,7 +90,7 @@ extern "C" void lsan_dispatch_call_block_and_release(void *block) {
} // namespace __lsan } // namespace __lsan
using namespace __lsan; // NOLINT using namespace __lsan;
// Wrap |ctxt| and |func| into an lsan_block_context_t. // Wrap |ctxt| and |func| into an lsan_block_context_t.
// The caller retains control of the allocated context. // The caller retains control of the allocated context.

View File

@ -74,7 +74,6 @@ merge lib/tsan/rtl tsan
merge lib/sanitizer_common sanitizer_common merge lib/sanitizer_common sanitizer_common
merge lib/interception interception merge lib/interception interception
merge lib/ubsan ubsan merge lib/ubsan ubsan
merge lib/BlocksRuntime/ BlocksRuntime
# Need to merge lib/builtins/assembly.h file: # Need to merge lib/builtins/assembly.h file:
mkdir -p builtins mkdir -p builtins

View File

@ -54,7 +54,7 @@ INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
// and a multiple of sizeof(void *). // and a multiple of sizeof(void *).
INLINE bool CheckPosixMemalignAlignment(uptr alignment) { INLINE bool CheckPosixMemalignAlignment(uptr alignment) {
return alignment != 0 && IsPowerOfTwo(alignment) && return alignment != 0 && IsPowerOfTwo(alignment) &&
(alignment % sizeof(void *)) == 0; // NOLINT (alignment % sizeof(void *)) == 0;
} }
// Returns true if calloc(size, n) call overflows on size*n calculation. // Returns true if calloc(size, n) call overflows on size*n calculation.

View File

@ -106,10 +106,11 @@ void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment,
{ {
ScopedAllocatorErrorReport report("invalid-posix-memalign-alignment", ScopedAllocatorErrorReport report("invalid-posix-memalign-alignment",
stack); stack);
Report("ERROR: %s: invalid alignment requested in " Report(
"posix_memalign: %zd, alignment must be a power of two and a " "ERROR: %s: invalid alignment requested in "
"multiple of sizeof(void*) == %zd\n", SanitizerToolName, alignment, "posix_memalign: %zd, alignment must be a power of two and a "
sizeof(void*)); // NOLINT "multiple of sizeof(void*) == %zd\n",
SanitizerToolName, alignment, sizeof(void *));
} }
Die(); Die();
} }

View File

@ -60,7 +60,9 @@
#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \ #if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
defined(__Fuchsia__) || defined(__linux__)) defined(__Fuchsia__) || defined(__linux__))
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT // clang-format off
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT
// clang-format on
#else #else
#define NO_EXEC_STACK_DIRECTIVE #define NO_EXEC_STACK_DIRECTIVE
#endif #endif

View File

@ -20,44 +20,35 @@ extern "C" void _mm_mfence();
#pragma intrinsic(_mm_mfence) #pragma intrinsic(_mm_mfence)
extern "C" void _mm_pause(); extern "C" void _mm_pause();
#pragma intrinsic(_mm_pause) #pragma intrinsic(_mm_pause)
extern "C" char _InterlockedExchange8( // NOLINT extern "C" char _InterlockedExchange8(char volatile *Addend, char Value);
char volatile *Addend, char Value); // NOLINT
#pragma intrinsic(_InterlockedExchange8) #pragma intrinsic(_InterlockedExchange8)
extern "C" short _InterlockedExchange16( // NOLINT extern "C" short _InterlockedExchange16(short volatile *Addend, short Value);
short volatile *Addend, short Value); // NOLINT
#pragma intrinsic(_InterlockedExchange16) #pragma intrinsic(_InterlockedExchange16)
extern "C" long _InterlockedExchange( // NOLINT extern "C" long _InterlockedExchange(long volatile *Addend, long Value);
long volatile *Addend, long Value); // NOLINT
#pragma intrinsic(_InterlockedExchange) #pragma intrinsic(_InterlockedExchange)
extern "C" long _InterlockedExchangeAdd( // NOLINT extern "C" long _InterlockedExchangeAdd(long volatile *Addend, long Value);
long volatile * Addend, long Value); // NOLINT
#pragma intrinsic(_InterlockedExchangeAdd) #pragma intrinsic(_InterlockedExchangeAdd)
extern "C" char _InterlockedCompareExchange8( // NOLINT extern "C" char _InterlockedCompareExchange8(char volatile *Destination,
char volatile *Destination, // NOLINT char Exchange, char Comparand);
char Exchange, char Comparand); // NOLINT
#pragma intrinsic(_InterlockedCompareExchange8) #pragma intrinsic(_InterlockedCompareExchange8)
extern "C" short _InterlockedCompareExchange16( // NOLINT extern "C" short _InterlockedCompareExchange16(short volatile *Destination,
short volatile *Destination, // NOLINT short Exchange, short Comparand);
short Exchange, short Comparand); // NOLINT
#pragma intrinsic(_InterlockedCompareExchange16) #pragma intrinsic(_InterlockedCompareExchange16)
extern "C" extern "C" long long _InterlockedCompareExchange64(
long long _InterlockedCompareExchange64( // NOLINT long long volatile *Destination, long long Exchange, long long Comparand);
long long volatile *Destination, // NOLINT
long long Exchange, long long Comparand); // NOLINT
#pragma intrinsic(_InterlockedCompareExchange64) #pragma intrinsic(_InterlockedCompareExchange64)
extern "C" void *_InterlockedCompareExchangePointer( extern "C" void *_InterlockedCompareExchangePointer(
void *volatile *Destination, void *volatile *Destination,
void *Exchange, void *Comparand); void *Exchange, void *Comparand);
#pragma intrinsic(_InterlockedCompareExchangePointer) #pragma intrinsic(_InterlockedCompareExchangePointer)
extern "C" extern "C" long __cdecl _InterlockedCompareExchange(long volatile *Destination,
long __cdecl _InterlockedCompareExchange( // NOLINT long Exchange,
long volatile *Destination, // NOLINT long Comparand);
long Exchange, long Comparand); // NOLINT
#pragma intrinsic(_InterlockedCompareExchange) #pragma intrinsic(_InterlockedCompareExchange)
#ifdef _WIN64 #ifdef _WIN64
extern "C" long long _InterlockedExchangeAdd64( // NOLINT extern "C" long long _InterlockedExchangeAdd64(long long volatile *Addend,
long long volatile * Addend, long long Value); // NOLINT long long Value);
#pragma intrinsic(_InterlockedExchangeAdd64) #pragma intrinsic(_InterlockedExchangeAdd64)
#endif #endif
@ -115,8 +106,8 @@ INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a,
u32 v, memory_order mo) { u32 v, memory_order mo) {
(void)mo; (void)mo;
DCHECK(!((uptr)a % sizeof(*a))); DCHECK(!((uptr)a % sizeof(*a)));
return (u32)_InterlockedExchangeAdd( return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
(volatile long*)&a->val_dont_use, (long)v); // NOLINT (long)v);
} }
INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a, INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
@ -124,11 +115,11 @@ INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
(void)mo; (void)mo;
DCHECK(!((uptr)a % sizeof(*a))); DCHECK(!((uptr)a % sizeof(*a)));
#ifdef _WIN64 #ifdef _WIN64
return (uptr)_InterlockedExchangeAdd64( return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
(volatile long long*)&a->val_dont_use, (long long)v); // NOLINT (long long)v);
#else #else
return (uptr)_InterlockedExchangeAdd( return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
(volatile long*)&a->val_dont_use, (long)v); // NOLINT (long)v);
#endif #endif
} }
@ -136,8 +127,8 @@ INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a,
u32 v, memory_order mo) { u32 v, memory_order mo) {
(void)mo; (void)mo;
DCHECK(!((uptr)a % sizeof(*a))); DCHECK(!((uptr)a % sizeof(*a)));
return (u32)_InterlockedExchangeAdd( return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
(volatile long*)&a->val_dont_use, -(long)v); // NOLINT -(long)v);
} }
INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a, INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
@ -145,11 +136,11 @@ INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
(void)mo; (void)mo;
DCHECK(!((uptr)a % sizeof(*a))); DCHECK(!((uptr)a % sizeof(*a)));
#ifdef _WIN64 #ifdef _WIN64
return (uptr)_InterlockedExchangeAdd64( return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
(volatile long long*)&a->val_dont_use, -(long long)v); // NOLINT -(long long)v);
#else #else
return (uptr)_InterlockedExchangeAdd( return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
(volatile long*)&a->val_dont_use, -(long)v); // NOLINT -(long)v);
#endif #endif
} }

View File

@ -323,7 +323,7 @@ static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
} // namespace __sanitizer } // namespace __sanitizer
using namespace __sanitizer; // NOLINT using namespace __sanitizer;
extern "C" { extern "C" {
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary, SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,

View File

@ -100,6 +100,8 @@ void UnmapOrDie(void *addr, uptr size);
void *MmapOrDieOnFatalError(uptr size, const char *mem_type); void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr) bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
WARN_UNUSED_RESULT; WARN_UNUSED_RESULT;
bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size,
const char *name = nullptr) WARN_UNUSED_RESULT;
void *MmapNoReserveOrDie(uptr size, const char *mem_type); void *MmapNoReserveOrDie(uptr size, const char *mem_type);
void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr); void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in // Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
@ -337,18 +339,18 @@ void ReportMmapWriteExec(int prot);
// Math // Math
#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__) #if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
extern "C" { extern "C" {
unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
#if defined(_WIN64) #if defined(_WIN64)
unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);
unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); // NOLINT unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
#endif #endif
} }
#endif #endif
INLINE uptr MostSignificantSetBitIndex(uptr x) { INLINE uptr MostSignificantSetBitIndex(uptr x) {
CHECK_NE(x, 0U); CHECK_NE(x, 0U);
unsigned long up; // NOLINT unsigned long up;
#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
# ifdef _WIN64 # ifdef _WIN64
up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x); up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
@ -365,7 +367,7 @@ INLINE uptr MostSignificantSetBitIndex(uptr x) {
INLINE uptr LeastSignificantSetBitIndex(uptr x) { INLINE uptr LeastSignificantSetBitIndex(uptr x) {
CHECK_NE(x, 0U); CHECK_NE(x, 0U);
unsigned long up; // NOLINT unsigned long up;
#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__) #if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
# ifdef _WIN64 # ifdef _WIN64
up = __builtin_ctzll(x); up = __builtin_ctzll(x);
@ -879,6 +881,11 @@ struct SignalContext {
bool is_memory_access; bool is_memory_access;
enum WriteFlag { UNKNOWN, READ, WRITE } write_flag; enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
// In some cases the kernel cannot provide the true faulting address; `addr`
// will be zero then. This field allows to distinguish between these cases
// and dereferences of null.
bool is_true_faulting_addr;
// VS2013 doesn't implement unrestricted unions, so we need a trivial default // VS2013 doesn't implement unrestricted unions, so we need a trivial default
// constructor // constructor
SignalContext() = default; SignalContext() = default;
@ -891,7 +898,8 @@ struct SignalContext {
context(context), context(context),
addr(GetAddress()), addr(GetAddress()),
is_memory_access(IsMemoryAccess()), is_memory_access(IsMemoryAccess()),
write_flag(GetWriteFlag()) { write_flag(GetWriteFlag()),
is_true_faulting_addr(IsTrueFaultingAddress()) {
InitPcSpBp(); InitPcSpBp();
} }
@ -912,6 +920,7 @@ struct SignalContext {
uptr GetAddress() const; uptr GetAddress() const;
WriteFlag GetWriteFlag() const; WriteFlag GetWriteFlag() const;
bool IsMemoryAccess() const; bool IsMemoryAccess() const;
bool IsTrueFaultingAddress() const;
}; };
void InitializePlatformEarly(); void InitializePlatformEarly();
@ -971,7 +980,7 @@ INLINE u32 GetNumberOfCPUsCached() {
} // namespace __sanitizer } // namespace __sanitizer
inline void *operator new(__sanitizer::operator_new_size_type size, inline void *operator new(__sanitizer::operator_new_size_type size,
__sanitizer::LowLevelAllocator &alloc) { __sanitizer::LowLevelAllocator &alloc) { // NOLINT
return alloc.Allocate(size); return alloc.Allocate(size);
} }

View File

@ -36,6 +36,7 @@
// COMMON_INTERCEPTOR_MMAP_IMPL // COMMON_INTERCEPTOR_MMAP_IMPL
// COMMON_INTERCEPTOR_COPY_STRING // COMMON_INTERCEPTOR_COPY_STRING
// COMMON_INTERCEPTOR_STRNDUP_IMPL // COMMON_INTERCEPTOR_STRNDUP_IMPL
// COMMON_INTERCEPTOR_STRERROR
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "interception/interception.h" #include "interception/interception.h"
@ -301,6 +302,10 @@ bool PlatformHasDifferentMemcpyAndMemmove();
return new_mem; return new_mem;
#endif #endif
#ifndef COMMON_INTERCEPTOR_STRERROR
#define COMMON_INTERCEPTOR_STRERROR() {}
#endif
struct FileMetadata { struct FileMetadata {
// For open_memstream(). // For open_memstream().
char **addr; char **addr;
@ -1267,9 +1272,8 @@ INTERCEPTOR(int, puts, char *s) {
#endif #endif
#if SANITIZER_INTERCEPT_PRCTL #if SANITIZER_INTERCEPT_PRCTL
INTERCEPTOR(int, prctl, int option, unsigned long arg2, INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
unsigned long arg3, // NOLINT unsigned long arg4, unsigned long arg5) {
unsigned long arg4, unsigned long arg5) { // NOLINT
void *ctx; void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5); COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
static const int PR_SET_NAME = 15; static const int PR_SET_NAME = 15;
@ -1701,13 +1705,13 @@ INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format) FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
#endif #endif
INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
#if SANITIZER_INTERCEPT___PRINTF_CHK #if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to, INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
const char *format, ...) // NOLINT const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
#endif #endif
INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...) INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
@ -1715,8 +1719,8 @@ FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
#if SANITIZER_INTERCEPT___PRINTF_CHK #if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag, INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
SIZE_T size_to, const char *format, ...) // NOLINT SIZE_T size_to, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
#endif #endif
INTERCEPTOR(int, asprintf, char **strp, const char *format, ...) INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
@ -3071,13 +3075,14 @@ INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
} }
int res = REAL(sendmmsg)(fd, msgvec, vlen, flags); int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
if (res >= 0 && msgvec) if (res >= 0 && msgvec) {
for (int i = 0; i < res; ++i) { for (int i = 0; i < res; ++i) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len, COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
sizeof(msgvec[i].msg_len)); sizeof(msgvec[i].msg_len));
if (common_flags()->intercept_send) if (common_flags()->intercept_send)
read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len); read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
} }
}
return res; return res;
} }
#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg); #define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
@ -3208,20 +3213,21 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
__sanitizer_iovec local_iovec; __sanitizer_iovec local_iovec;
if (data) { if (data) {
if (request == ptrace_setregs) if (request == ptrace_setregs) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz); COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
else if (request == ptrace_setfpregs) } else if (request == ptrace_setfpregs) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz); COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
else if (request == ptrace_setfpxregs) } else if (request == ptrace_setfpxregs) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz); COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
else if (request == ptrace_setvfpregs) } else if (request == ptrace_setvfpregs) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz); COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
else if (request == ptrace_setsiginfo) } else if (request == ptrace_setsiginfo) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz); COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
// Some kernel might zero the iovec::iov_base in case of invalid // Some kernel might zero the iovec::iov_base in case of invalid
// write access. In this case copy the invalid address for further // write access. In this case copy the invalid address for further
// inspection. // inspection.
else if (request == ptrace_setregset || request == ptrace_getregset) { } else if (request == ptrace_setregset || request == ptrace_getregset) {
__sanitizer_iovec *iovec = (__sanitizer_iovec*)data; __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec)); COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
local_iovec = *iovec; local_iovec = *iovec;
@ -3238,19 +3244,19 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
if (!res && data) { if (!res && data) {
// Note that PEEK* requests assign different meaning to the return value. // Note that PEEK* requests assign different meaning to the return value.
// This function does not handle them (nor does it need to). // This function does not handle them (nor does it need to).
if (request == ptrace_getregs) if (request == ptrace_getregs) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
else if (request == ptrace_getfpregs) } else if (request == ptrace_getfpregs) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
else if (request == ptrace_getfpxregs) } else if (request == ptrace_getfpxregs) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
else if (request == ptrace_getvfpregs) } else if (request == ptrace_getvfpregs) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
else if (request == ptrace_getsiginfo) } else if (request == ptrace_getsiginfo) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
else if (request == ptrace_geteventmsg) } else if (request == ptrace_geteventmsg) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long)); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
else if (request == ptrace_getregset) { } else if (request == ptrace_getregset) {
__sanitizer_iovec *iovec = (__sanitizer_iovec*)data; __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec)); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base, COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
@ -3676,6 +3682,7 @@ INTERCEPTOR(int, sched_getparam, int pid, void *param) {
INTERCEPTOR(char *, strerror, int errnum) { INTERCEPTOR(char *, strerror, int errnum) {
void *ctx; void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum); COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
COMMON_INTERCEPTOR_STRERROR();
char *res = REAL(strerror)(errnum); char *res = REAL(strerror)(errnum);
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1); if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
return res; return res;
@ -6716,7 +6723,7 @@ INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t)); COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size, COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
(src_size + 1) * sizeof(wchar_t)); (src_size + 1) * sizeof(wchar_t));
return REAL(wcscat)(dst, src); // NOLINT return REAL(wcscat)(dst, src);
} }
INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) { INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
@ -6729,7 +6736,7 @@ INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t)); COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size, COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
(src_size + 1) * sizeof(wchar_t)); (src_size + 1) * sizeof(wchar_t));
return REAL(wcsncat)(dst, src, n); // NOLINT return REAL(wcsncat)(dst, src, n);
} }
#define INIT_WCSCAT \ #define INIT_WCSCAT \
COMMON_INTERCEPT_FUNCTION(wcscat); \ COMMON_INTERCEPT_FUNCTION(wcscat); \
@ -7843,10 +7850,11 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
if (iov) if (iov)
COMMON_INTERCEPTOR_WRITE_RANGE( COMMON_INTERCEPTOR_WRITE_RANGE(
ctx, iov->iov_base, Min(iov_len, iov->iov_len)); ctx, iov->iov_base, Min(iov_len, iov->iov_len));
} else if (operation == modctl_exists) } else if (operation == modctl_exists) {
ret = REAL(modctl)(operation, argp); ret = REAL(modctl)(operation, argp);
else } else {
ret = REAL(modctl)(operation, argp); ret = REAL(modctl)(operation, argp);
}
return ret; return ret;
} }
@ -9565,11 +9573,60 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
#define INIT_GETRANDOM #define INIT_GETRANDOM
#endif #endif
#if SANITIZER_INTERCEPT_CRYPT
INTERCEPTOR(char *, crypt, char *key, char *salt) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
char *res = REAL(crypt)(key, salt);
if (res != nullptr)
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
return res;
}
#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
#else
#define INIT_CRYPT
#endif
#if SANITIZER_INTERCEPT_CRYPT_R
INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
char *res = REAL(crypt_r)(key, salt, data);
if (res != nullptr) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
__sanitizer::struct_crypt_data_sz);
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
}
return res;
}
#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
#else
#define INIT_CRYPT_R
#endif
#if SANITIZER_INTERCEPT_GETENTROPY
INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
int r = REAL(getentropy)(buf, buflen);
if (r == 0) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
}
return r;
}
#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
#else
#define INIT_GETENTROPY
#endif
static void InitializeCommonInterceptors() { static void InitializeCommonInterceptors() {
#if SI_POSIX #if SI_POSIX
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map = interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
new ((void *)&metadata_mem) MetadataHashMap(); // NOLINT
#endif #endif
INIT_MMAP; INIT_MMAP;
@ -9864,6 +9921,9 @@ static void InitializeCommonInterceptors() {
INIT_GETUSERSHELL; INIT_GETUSERSHELL;
INIT_SL_INIT; INIT_SL_INIT;
INIT_GETRANDOM; INIT_GETRANDOM;
INIT_CRYPT;
INIT_CRYPT_R;
INIT_GETENTROPY;
INIT___PRINTF_CHK; INIT___PRINTF_CHK;
} }

View File

@ -14,6 +14,7 @@ INTERFACE_FUNCTION(__sanitizer_set_death_callback)
INTERFACE_FUNCTION(__sanitizer_set_report_path) INTERFACE_FUNCTION(__sanitizer_set_report_path)
INTERFACE_FUNCTION(__sanitizer_set_report_fd) INTERFACE_FUNCTION(__sanitizer_set_report_fd)
INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container) INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary) INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify) INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
// Sanitizer weak hooks // Sanitizer weak hooks

View File

@ -36,7 +36,7 @@
#include <zircon/sanitizer.h> #include <zircon/sanitizer.h>
#include <zircon/syscalls.h> #include <zircon/syscalls.h>
using namespace __sanitizer; // NOLINT using namespace __sanitizer;
namespace __sancov { namespace __sancov {
namespace { namespace {
@ -198,8 +198,8 @@ void InitializeCoverage(bool enabled, const char *dir) {
} // namespace __sanitizer } // namespace __sanitizer
extern "C" { extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr *pcs,
const uptr *pcs, uptr len) { uptr len) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }

View File

@ -166,8 +166,8 @@ void InitializeCoverage(bool enabled, const char *dir) {
} // namespace __sanitizer } // namespace __sanitizer
extern "C" { extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr* pcs,
const uptr* pcs, uptr len) { uptr len) {
return __sancov::SanitizerDumpCoverage(pcs, len); return __sancov::SanitizerDumpCoverage(pcs, len);
} }

View File

@ -31,7 +31,7 @@ extern "C" {
// Use uint64_t so the linker won't need to add any padding if it tries to word // Use uint64_t so the linker won't need to add any padding if it tries to word
// align the start of the 8-bit counters array. The array will always start 8 // align the start of the 8-bit counters array. The array will always start 8
// bytes after __start_sancov_cntrs. // bytes after __start_sancov_cntrs.
#pragma section(".SCOV$CA", read, write) // NOLINT #pragma section(".SCOV$CA", read, write)
__declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0; __declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0;
// Even though we said not to align __stop__sancov_cntrs (using the "align" // Even though we said not to align __stop__sancov_cntrs (using the "align"
@ -41,13 +41,13 @@ __declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0;
// padding would be added to align .SCOVP$Z, However, if .SCOV$CZ section is 1 // padding would be added to align .SCOVP$Z, However, if .SCOV$CZ section is 1
// byte, the linker won't try to align it on an 8-byte boundary, so use a // byte, the linker won't try to align it on an 8-byte boundary, so use a
// uint8_t for __stop_sancov_cntrs. // uint8_t for __stop_sancov_cntrs.
#pragma section(".SCOV$CZ", read, write) // NOLINT #pragma section(".SCOV$CZ", read, write)
__declspec(allocate(".SCOV$CZ")) __declspec(align(1)) uint8_t __declspec(allocate(".SCOV$CZ")) __declspec(align(1)) uint8_t
__stop___sancov_cntrs = 0; __stop___sancov_cntrs = 0;
#pragma section(".SCOV$GA", read, write) // NOLINT #pragma section(".SCOV$GA", read, write)
__declspec(allocate(".SCOV$GA")) uint64_t __start___sancov_guards = 0; __declspec(allocate(".SCOV$GA")) uint64_t __start___sancov_guards = 0;
#pragma section(".SCOV$GZ", read, write) // NOLINT #pragma section(".SCOV$GZ", read, write)
__declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t __declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
__stop___sancov_guards = 0; __stop___sancov_guards = 0;
@ -56,9 +56,9 @@ __declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
// constant it should be merged with the .rdata section. // constant it should be merged with the .rdata section.
#pragma comment(linker, "/MERGE:.SCOV=.data") #pragma comment(linker, "/MERGE:.SCOV=.data")
#pragma section(".SCOVP$A", read) // NOLINT #pragma section(".SCOVP$A", read)
__declspec(allocate(".SCOVP$A")) uint64_t __start___sancov_pcs = 0; __declspec(allocate(".SCOVP$A")) uint64_t __start___sancov_pcs = 0;
#pragma section(".SCOVP$Z", read) // NOLINT #pragma section(".SCOVP$Z", read)
__declspec(allocate(".SCOVP$Z")) __declspec(align(1)) uint8_t __declspec(allocate(".SCOVP$Z")) __declspec(align(1)) uint8_t
__stop___sancov_pcs = 0; __stop___sancov_pcs = 0;

View File

@ -199,7 +199,7 @@ char *FindPathToBinary(const char *name) {
} // namespace __sanitizer } // namespace __sanitizer
using namespace __sanitizer; // NOLINT using namespace __sanitizer;
extern "C" { extern "C" {
void __sanitizer_set_report_path(const char *path) { void __sanitizer_set_report_path(const char *path) {

View File

@ -83,8 +83,9 @@ void FlagParser::parse_flag(const char *env_option_name) {
Printf("%s: ERROR: expected '=' in %s\n", SanitizerToolName, Printf("%s: ERROR: expected '=' in %s\n", SanitizerToolName,
env_option_name); env_option_name);
Die(); Die();
} else } else {
fatal_error("expected '='"); fatal_error("expected '='");
}
} }
char *name = ll_strndup(buf_ + name_start, pos_ - name_start); char *name = ll_strndup(buf_ + name_start, pos_ - name_start);

View File

@ -24,7 +24,7 @@ class FlagHandlerBase {
virtual bool Parse(const char *value) { return false; } virtual bool Parse(const char *value) { return false; }
protected: protected:
~FlagHandlerBase() {}; ~FlagHandlerBase() {}
}; };
template <typename T> template <typename T>
@ -144,7 +144,7 @@ class FlagParser {
template <typename T> template <typename T>
static void RegisterFlag(FlagParser *parser, const char *name, const char *desc, static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
T *var) { T *var) {
FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var); // NOLINT FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
parser->RegisterHandler(name, fh, desc); parser->RegisterHandler(name, fh, desc);
} }

View File

@ -92,11 +92,11 @@ class FlagHandlerInclude : public FlagHandlerBase {
}; };
void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
FlagHandlerInclude(parser, /*ignore_missing*/ false); FlagHandlerInclude(parser, /*ignore_missing*/ false);
parser->RegisterHandler("include", fh_include, parser->RegisterHandler("include", fh_include,
"read more options from the given file"); "read more options from the given file");
FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc)
FlagHandlerInclude(parser, /*ignore_missing*/ true); FlagHandlerInclude(parser, /*ignore_missing*/ true);
parser->RegisterHandler( parser->RegisterHandler(
"include_if_exists", fh_include_if_exists, "include_if_exists", fh_include_if_exists,

View File

@ -502,7 +502,7 @@ uptr GetRSS() { UNIMPLEMENTED(); }
} // namespace __sanitizer } // namespace __sanitizer
using namespace __sanitizer; // NOLINT using namespace __sanitizer;
extern "C" { extern "C" {
void __sanitizer_startup_hook(int argc, char **argv, char **envp, void __sanitizer_startup_hook(int argc, char **argv, char **envp,

View File

@ -9,6 +9,7 @@
// Common getauxval() guards and definitions. // Common getauxval() guards and definitions.
// getauxval() is not defined until glibc version 2.16, or until API level 21 // getauxval() is not defined until glibc version 2.16, or until API level 21
// for Android. // for Android.
// Implement the getauxval() compat function for NetBSD.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -16,15 +17,10 @@
#define SANITIZER_GETAUXVAL_H #define SANITIZER_GETAUXVAL_H
#include "sanitizer_platform.h" #include "sanitizer_platform.h"
#include "sanitizer_glibc_version.h"
#if SANITIZER_LINUX || SANITIZER_FUCHSIA #if SANITIZER_LINUX || SANITIZER_FUCHSIA
# include <features.h>
# ifndef __GLIBC_PREREQ
# define __GLIBC_PREREQ(x, y) 0
# endif
# if __GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \ # if __GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \
SANITIZER_FUCHSIA SANITIZER_FUCHSIA
# define SANITIZER_USE_GETAUXVAL 1 # define SANITIZER_USE_GETAUXVAL 1
@ -38,10 +34,26 @@
// The weak getauxval definition allows to check for the function at runtime. // The weak getauxval definition allows to check for the function at runtime.
// This is useful for Android, when compiled at a lower API level yet running // This is useful for Android, when compiled at a lower API level yet running
// on a more recent platform that offers the function. // on a more recent platform that offers the function.
extern "C" SANITIZER_WEAK_ATTRIBUTE extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
unsigned long getauxval(unsigned long type); // NOLINT
# endif # endif
#endif // SANITIZER_LINUX || SANITIZER_FUCHSIA #elif SANITIZER_NETBSD
#define SANITIZER_USE_GETAUXVAL 1
#include <dlfcn.h>
#include <elf.h>
static inline decltype(AuxInfo::a_v) getauxval(decltype(AuxInfo::a_type) type) {
for (const AuxInfo *aux = (const AuxInfo *)_dlauxinfo();
aux->a_type != AT_NULL; ++aux) {
if (type == aux->a_type)
return aux->a_v;
}
return 0;
}
#endif
#endif // SANITIZER_GETAUXVAL_H #endif // SANITIZER_GETAUXVAL_H

View File

@ -0,0 +1,26 @@
//===-- sanitizer_glibc_version.h -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of Sanitizer common code.
//
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_GLIBC_VERSION_H
#define SANITIZER_GLIBC_VERSION_H
#include "sanitizer_platform.h"
#if SANITIZER_LINUX || SANITIZER_FUCHSIA
#include <features.h>
#endif
#ifndef __GLIBC_PREREQ
#define __GLIBC_PREREQ(x, y) 0
#endif
#endif

View File

@ -1404,7 +1404,7 @@ static void ioctl_table_fill() {
_(SNDCTL_DSP_SKIP, NONE, 0); _(SNDCTL_DSP_SKIP, NONE, 0);
_(SNDCTL_DSP_SILENCE, NONE, 0); _(SNDCTL_DSP_SILENCE, NONE, 0);
#undef _ #undef _
} } // NOLINT
static bool ioctl_initialized = false; static bool ioctl_initialized = false;

View File

@ -133,27 +133,27 @@ namespace __sanitizer {
#if defined(_WIN64) #if defined(_WIN64)
// 64-bit Windows uses LLP64 data model. // 64-bit Windows uses LLP64 data model.
typedef unsigned long long uptr; // NOLINT typedef unsigned long long uptr;
typedef signed long long sptr; // NOLINT typedef signed long long sptr;
#else #else
typedef unsigned long uptr; // NOLINT typedef unsigned long uptr;
typedef signed long sptr; // NOLINT typedef signed long sptr;
#endif // defined(_WIN64) #endif // defined(_WIN64)
#if defined(__x86_64__) #if defined(__x86_64__)
// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use // Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
// 64-bit pointer to unwind stack frame. // 64-bit pointer to unwind stack frame.
typedef unsigned long long uhwptr; // NOLINT typedef unsigned long long uhwptr;
#else #else
typedef uptr uhwptr; // NOLINT typedef uptr uhwptr;
#endif #endif
typedef unsigned char u8; typedef unsigned char u8;
typedef unsigned short u16; // NOLINT typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;
typedef unsigned long long u64; // NOLINT typedef unsigned long long u64;
typedef signed char s8; typedef signed char s8;
typedef signed short s16; // NOLINT typedef signed short s16;
typedef signed int s32; typedef signed int s32;
typedef signed long long s64; // NOLINT typedef signed long long s64;
#if SANITIZER_WINDOWS #if SANITIZER_WINDOWS
// On Windows, files are HANDLE, which is a synonim of void*. // On Windows, files are HANDLE, which is a synonim of void*.
// Use void* to avoid including <windows.h> everywhere. // Use void* to avoid including <windows.h> everywhere.
@ -264,7 +264,7 @@ typedef ALIGNED(1) s64 us64;
#if SANITIZER_WINDOWS #if SANITIZER_WINDOWS
} // namespace __sanitizer } // namespace __sanitizer
typedef unsigned long DWORD; // NOLINT typedef unsigned long DWORD;
namespace __sanitizer { namespace __sanitizer {
typedef DWORD thread_return_t; typedef DWORD thread_return_t;
# define THREAD_CALLING_CONV __stdcall # define THREAD_CALLING_CONV __stdcall
@ -419,18 +419,41 @@ inline void Trap() {
} // namespace __sanitizer } // namespace __sanitizer
namespace __asan { using namespace __sanitizer; } // NOLINT namespace __asan {
namespace __dsan { using namespace __sanitizer; } // NOLINT using namespace __sanitizer;
namespace __dfsan { using namespace __sanitizer; } // NOLINT }
namespace __lsan { using namespace __sanitizer; } // NOLINT namespace __dsan {
namespace __msan { using namespace __sanitizer; } // NOLINT using namespace __sanitizer;
namespace __hwasan { using namespace __sanitizer; } // NOLINT }
namespace __tsan { using namespace __sanitizer; } // NOLINT namespace __dfsan {
namespace __scudo { using namespace __sanitizer; } // NOLINT using namespace __sanitizer;
namespace __ubsan { using namespace __sanitizer; } // NOLINT }
namespace __xray { using namespace __sanitizer; } // NOLINT namespace __lsan {
namespace __interception { using namespace __sanitizer; } // NOLINT using namespace __sanitizer;
namespace __hwasan { using namespace __sanitizer; } // NOLINT }
namespace __msan {
using namespace __sanitizer;
}
namespace __hwasan {
using namespace __sanitizer;
}
namespace __tsan {
using namespace __sanitizer;
}
namespace __scudo {
using namespace __sanitizer;
}
namespace __ubsan {
using namespace __sanitizer;
}
namespace __xray {
using namespace __sanitizer;
}
namespace __interception {
using namespace __sanitizer;
}
namespace __hwasan {
using namespace __sanitizer;
}
#endif // SANITIZER_DEFS_H #endif // SANITIZER_DEFS_H

View File

@ -63,10 +63,11 @@ void *internal_memmove(void *dest, const void *src, uptr n) {
for (i = 0; i < signed_n; ++i) for (i = 0; i < signed_n; ++i)
d[i] = s[i]; d[i] = s[i];
} else { } else {
if (d > s && signed_n > 0) if (d > s && signed_n > 0) {
for (i = signed_n - 1; i >= 0 ; --i) { for (i = signed_n - 1; i >= 0; --i) {
d[i] = s[i]; d[i] = s[i];
} }
}
} }
return dest; return dest;
} }
@ -270,9 +271,9 @@ bool mem_is_zero(const char *beg, uptr size) {
for (; aligned_beg < aligned_end; aligned_beg++) for (; aligned_beg < aligned_end; aligned_beg++)
all |= *aligned_beg; all |= *aligned_beg;
// Epilogue. // Epilogue.
if ((char*)aligned_end >= beg) if ((char *)aligned_end >= beg) {
for (const char *mem = (char*)aligned_end; mem < end; mem++) for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem;
all |= *mem; }
return all == 0; return all == 0;
} }

View File

@ -1062,8 +1062,6 @@ uptr GetMaxUserVirtualAddress() {
uptr GetPageSize() { uptr GetPageSize() {
#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
return EXEC_PAGESIZE; return EXEC_PAGESIZE;
#elif SANITIZER_USE_GETAUXVAL
return getauxval(AT_PAGESZ);
#elif SANITIZER_FREEBSD || SANITIZER_NETBSD #elif SANITIZER_FREEBSD || SANITIZER_NETBSD
// Use sysctl as sysconf can trigger interceptors internally. // Use sysctl as sysconf can trigger interceptors internally.
int pz = 0; int pz = 0;
@ -1072,6 +1070,8 @@ uptr GetPageSize() {
int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0); int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
CHECK_EQ(rv, 0); CHECK_EQ(rv, 0);
return (uptr)pz; return (uptr)pz;
#elif SANITIZER_USE_GETAUXVAL
return getauxval(AT_PAGESZ);
#else #else
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
#endif #endif
@ -1849,6 +1849,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
#endif #endif
} }
bool SignalContext::IsTrueFaultingAddress() const {
auto si = static_cast<const siginfo_t *>(siginfo);
// SIGSEGV signals without a true fault address have si_code set to 128.
return si->si_signo == SIGSEGV && si->si_code != 128;
}
void SignalContext::DumpAllRegisters(void *context) { void SignalContext::DumpAllRegisters(void *context) {
// FIXME: Implement this. // FIXME: Implement this.
} }
@ -2011,6 +2017,35 @@ void CheckASLR() {
CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
ReExec(); ReExec();
} }
#elif SANITIZER_FREEBSD
int aslr_pie;
uptr len = sizeof(aslr_pie);
#if SANITIZER_WORDSIZE == 64
if (UNLIKELY(internal_sysctlbyname("kern.elf64.aslr.pie_enable",
&aslr_pie, &len, NULL, 0) == -1)) {
// We're making things less 'dramatic' here since
// the OID is not necessarily guaranteed to be here
// just yet regarding FreeBSD release
return;
}
if (aslr_pie > 0) {
Printf("This sanitizer is not compatible with enabled ASLR "
"and binaries compiled with PIE\n");
Die();
}
#endif
// there might be 32 bits compat for 64 bits
if (UNLIKELY(internal_sysctlbyname("kern.elf32.aslr.pie_enable",
&aslr_pie, &len, NULL, 0) == -1)) {
return;
}
if (aslr_pie > 0) {
Printf("This sanitizer is not compatible with enabled ASLR "
"and binaries compiled with PIE\n");
Die();
}
#else #else
// Do nothing // Do nothing
#endif #endif

View File

@ -23,6 +23,7 @@
#include "sanitizer_flags.h" #include "sanitizer_flags.h"
#include "sanitizer_freebsd.h" #include "sanitizer_freebsd.h"
#include "sanitizer_getauxval.h" #include "sanitizer_getauxval.h"
#include "sanitizer_glibc_version.h"
#include "sanitizer_linux.h" #include "sanitizer_linux.h"
#include "sanitizer_placement_new.h" #include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h" #include "sanitizer_procmaps.h"
@ -188,11 +189,7 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
static uptr g_tls_size; static uptr g_tls_size;
#ifdef __i386__ #ifdef __i386__
# ifndef __GLIBC_PREREQ # define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
# define CHECK_GET_TLS_STATIC_INFO_VERSION 1
# else
# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
# endif
#else #else
# define CHECK_GET_TLS_STATIC_INFO_VERSION 0 # define CHECK_GET_TLS_STATIC_INFO_VERSION 0
#endif #endif
@ -701,13 +698,9 @@ 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
} }

View File

@ -13,6 +13,7 @@
#include "sanitizer_platform.h" #include "sanitizer_platform.h"
#if SANITIZER_MAC #if SANITIZER_MAC
#include "sanitizer_mac.h" #include "sanitizer_mac.h"
#include "interception/interception.h"
// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
// the clients will most certainly use 64-bit ones as well. // the clients will most certainly use 64-bit ones as well.
@ -36,7 +37,7 @@
extern char **environ; extern char **environ;
#endif #endif
#if defined(__has_include) && __has_include(<os/trace.h>) && defined(__BLOCKS__) #if defined(__has_include) && __has_include(<os/trace.h>)
#define SANITIZER_OS_TRACE 1 #define SANITIZER_OS_TRACE 1
#include <os/trace.h> #include <os/trace.h>
#else #else
@ -64,7 +65,9 @@ extern "C" {
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
#include <signal.h> #include <signal.h>
#include <spawn.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -239,27 +242,102 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
(size_t)newlen); (size_t)newlen);
} }
int internal_forkpty(int *aparent) { static fd_t internal_spawn_impl(const char *argv[], pid_t *pid) {
int parent, worker; fd_t master_fd = kInvalidFd;
if (openpty(&parent, &worker, nullptr, nullptr, nullptr) == -1) return -1; fd_t slave_fd = kInvalidFd;
int pid = internal_fork();
if (pid == -1) { auto fd_closer = at_scope_exit([&] {
close(parent); internal_close(master_fd);
close(worker); internal_close(slave_fd);
return -1; });
// We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
// in particular detects when it's talking to a pipe and forgets to flush the
// output stream after sending a response.
master_fd = posix_openpt(O_RDWR);
if (master_fd == kInvalidFd) return kInvalidFd;
int res = grantpt(master_fd) || unlockpt(master_fd);
if (res != 0) return kInvalidFd;
// Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
char slave_pty_name[128];
res = ioctl(master_fd, TIOCPTYGNAME, slave_pty_name);
if (res == -1) return kInvalidFd;
slave_fd = internal_open(slave_pty_name, O_RDWR);
if (slave_fd == kInvalidFd) return kInvalidFd;
// File descriptor actions
posix_spawn_file_actions_t acts;
res = posix_spawn_file_actions_init(&acts);
if (res != 0) return kInvalidFd;
auto acts_cleanup = at_scope_exit([&] {
posix_spawn_file_actions_destroy(&acts);
});
res = posix_spawn_file_actions_adddup2(&acts, slave_fd, STDIN_FILENO) ||
posix_spawn_file_actions_adddup2(&acts, slave_fd, STDOUT_FILENO) ||
posix_spawn_file_actions_addclose(&acts, slave_fd);
if (res != 0) return kInvalidFd;
// Spawn attributes
posix_spawnattr_t attrs;
res = posix_spawnattr_init(&attrs);
if (res != 0) return kInvalidFd;
auto attrs_cleanup = at_scope_exit([&] {
posix_spawnattr_destroy(&attrs);
});
// In the spawned process, close all file descriptors that are not explicitly
// described by the file actions object. This is Darwin-specific extension.
res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
if (res != 0) return kInvalidFd;
// posix_spawn
char **argv_casted = const_cast<char **>(argv);
char **env = GetEnviron();
res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, env);
if (res != 0) return kInvalidFd;
// Disable echo in the new terminal, disable CR.
struct termios termflags;
tcgetattr(master_fd, &termflags);
termflags.c_oflag &= ~ONLCR;
termflags.c_lflag &= ~ECHO;
tcsetattr(master_fd, TCSANOW, &termflags);
// On success, do not close master_fd on scope exit.
fd_t fd = master_fd;
master_fd = kInvalidFd;
return fd;
}
fd_t internal_spawn(const char *argv[], pid_t *pid) {
// The client program may close its stdin and/or stdout and/or stderr thus
// allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
// case the communication is broken if either the parent or the child tries to
// close or duplicate these descriptors. We temporarily reserve these
// descriptors here to prevent this.
fd_t low_fds[3];
size_t count = 0;
for (; count < 3; count++) {
low_fds[count] = posix_openpt(O_RDWR);
if (low_fds[count] >= STDERR_FILENO)
break;
} }
if (pid == 0) {
close(parent); fd_t fd = internal_spawn_impl(argv, pid);
if (login_tty(worker) != 0) {
// We already forked, there's not much we can do. Let's quit. for (; count > 0; count--) {
Report("login_tty failed (errno %d)\n", errno); internal_close(low_fds[count]);
internal__exit(1);
}
} else {
*aparent = parent;
close(worker);
} }
return pid;
return fd;
} }
uptr internal_rename(const char *oldpath, const char *newpath) { uptr internal_rename(const char *oldpath, const char *newpath) {
@ -676,6 +754,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
#endif #endif
} }
bool SignalContext::IsTrueFaultingAddress() const {
auto si = static_cast<const siginfo_t *>(siginfo);
// "Real" SIGSEGV codes (e.g., SEGV_MAPERR, SEGV_MAPERR) are non-zero.
return si->si_signo == SIGSEGV && si->si_code != 0;
}
static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
ucontext_t *ucontext = (ucontext_t*)context; ucontext_t *ucontext = (ucontext_t*)context;
# if defined(__aarch64__) # if defined(__aarch64__)
@ -1122,7 +1206,7 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
if (!buffer || !length || length > 256) if (!buffer || !length || length > 256)
return false; return false;
// arc4random never fails. // arc4random never fails.
arc4random_buf(buffer, length); REAL(arc4random_buf)(buffer, length);
return true; return true;
} }

View File

@ -13,6 +13,7 @@
#ifndef SANITIZER_PLATFORM_INTERCEPTORS_H #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
#define SANITIZER_PLATFORM_INTERCEPTORS_H #define SANITIZER_PLATFORM_INTERCEPTORS_H
#include "sanitizer_glibc_version.h"
#include "sanitizer_internal_defs.h" #include "sanitizer_internal_defs.h"
#if SANITIZER_POSIX #if SANITIZER_POSIX
@ -331,10 +332,9 @@
#define SANITIZER_INTERCEPT_ETHER_HOST \ #define SANITIZER_INTERCEPT_ETHER_HOST \
(SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID) (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID)
#define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID) #define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
#define SANITIZER_INTERCEPT_SHMCTL \ #define SANITIZER_INTERCEPT_SHMCTL \
(SI_NETBSD || SI_OPENBSD || SI_SOLARIS || \ (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && \ SI_NETBSD || SI_OPENBSD || SI_SOLARIS) // NOLINT
SANITIZER_WORDSIZE == 64)) // NOLINT
#define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \ #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
@ -489,7 +489,8 @@
SI_NOT_RTEMS) SI_NOT_RTEMS)
#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX #define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS) #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_OPENBSD) #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE \
(!SI_MAC && !SI_OPENBSD && !SI_NETBSD)
#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX #define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX #define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
@ -561,11 +562,18 @@
#define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD #define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD
#define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC) #define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC)
#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD) #define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD || SI_MAC)
#define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD #define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD
#define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID) #define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID)
#define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD) #define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD)
#define SANITIZER_INTERCEPT_CRYPT (SI_POSIX && !SI_ANDROID)
#define SANITIZER_INTERCEPT_CRYPT_R (SI_LINUX && !SI_ANDROID)
#define SANITIZER_INTERCEPT_GETRANDOM SI_LINUX #define SANITIZER_INTERCEPT_GETRANDOM \
((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD
#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD
#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD
#define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

View File

@ -26,12 +26,9 @@
// 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. Beware that with <sys/stat.h>, struct stat // fine with newer headers, too.
// 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__) #if defined(__x86_64__) || defined(__mips__)
#include <sys/stat.h> #include <sys/stat.h>
#else #else
#define ino_t __kernel_ino_t #define ino_t __kernel_ino_t

View File

@ -22,6 +22,10 @@
#ifdef _FILE_OFFSET_BITS #ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS #undef _FILE_OFFSET_BITS
#endif #endif
// Must go after undef _FILE_OFFSET_BITS.
#include "sanitizer_glibc_version.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <dirent.h> #include <dirent.h>
#include <grp.h> #include <grp.h>
@ -136,6 +140,7 @@ typedef struct user_fpregs elf_fpregset_t;
#include <linux/serial.h> #include <linux/serial.h>
#include <sys/msg.h> #include <sys/msg.h>
#include <sys/ipc.h> #include <sys/ipc.h>
#include <crypt.h>
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID #endif // SANITIZER_LINUX && !SANITIZER_ANDROID
#if SANITIZER_ANDROID #if SANITIZER_ANDROID
@ -236,6 +241,7 @@ namespace __sanitizer {
unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT; unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
unsigned struct_rlimit64_sz = sizeof(struct rlimit64); unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
unsigned struct_statvfs64_sz = sizeof(struct statvfs64); unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
unsigned struct_crypt_data_sz = sizeof(struct crypt_data);
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID #endif // SANITIZER_LINUX && !SANITIZER_ANDROID
#if SANITIZER_LINUX && !SANITIZER_ANDROID #if SANITIZER_LINUX && !SANITIZER_ANDROID
@ -1005,10 +1011,6 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level); CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type); CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
#ifndef __GLIBC_PREREQ
#define __GLIBC_PREREQ(x, y) 0
#endif
#if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14)) #if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14))
CHECK_TYPE_SIZE(mmsghdr); CHECK_TYPE_SIZE(mmsghdr);
CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr); CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
@ -1129,9 +1131,8 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
#if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \ #if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \
!defined(__arm__) !defined(__arm__)
/* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */ /* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */
/* On Arm glibc 2.31 and later provide a different mode field, this field is /* On Arm newer glibc provide a different mode field, it's hard to detect
never used by libsanitizer so we can simply ignore this assert for all glibc so just disable the check. */
versions. */
CHECK_SIZE_AND_OFFSET(ipc_perm, mode); CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,7 @@ struct __sanitizer_ipc_perm {
#if !defined(_LP64) #if !defined(_LP64)
int pad[4]; int pad[4];
#endif #endif
}; };
struct __sanitizer_shmid_ds { struct __sanitizer_shmid_ds {
__sanitizer_ipc_perm shm_perm; __sanitizer_ipc_perm shm_perm;
@ -237,9 +237,8 @@ typedef int __sanitizer_clockid_t;
// This thing depends on the platform. We are only interested in the upper // This thing depends on the platform. We are only interested in the upper
// limit. Verified with a compiler assert in .cpp. // limit. Verified with a compiler assert in .cpp.
const int pthread_attr_t_max_sz = 128;
union __sanitizer_pthread_attr_t { union __sanitizer_pthread_attr_t {
char size[pthread_attr_t_max_sz]; // NOLINT char size[128];
void *align; void *align;
}; };

View File

@ -312,6 +312,8 @@ const char *SignalContext::Describe() const {
return "SEGV"; return "SEGV";
case SIGBUS: case SIGBUS:
return "BUS"; return "BUS";
case SIGTRAP:
return "TRAP";
} }
return "UNKNOWN SIGNAL"; return "UNKNOWN SIGNAL";
} }

View File

@ -63,7 +63,7 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);
uptr internal_waitpid(int pid, int *status, int options); uptr internal_waitpid(int pid, int *status, int options);
int internal_fork(); int internal_fork();
int internal_forkpty(int *amaster); fd_t internal_spawn(const char *argv[], pid_t *pid);
int internal_sysctl(const int *name, unsigned int namelen, void *oldp, int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
uptr *oldlenp, const void *newp, uptr newlen); uptr *oldlenp, const void *newp, uptr newlen);

View File

@ -304,11 +304,13 @@ void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
MemoryMappingLayout::CacheMemoryMappings(); MemoryMappingLayout::CacheMemoryMappings();
} }
bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) { static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags,
const char *name) {
size = RoundUpTo(size, GetPageSizeCached()); size = RoundUpTo(size, GetPageSizeCached());
fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached()); fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE, uptr p =
MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, name); MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
int reserrno; int reserrno;
if (internal_iserror(p, &reserrno)) { if (internal_iserror(p, &reserrno)) {
Report("ERROR: %s failed to " Report("ERROR: %s failed to "
@ -320,6 +322,24 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
return true; return true;
} }
bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
return MmapFixed(fixed_addr, size, MAP_NORESERVE, name);
}
bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
#if SANITIZER_FREEBSD
if (common_flags()->no_huge_pages_for_shadow)
return MmapFixedNoReserve(fixed_addr, size, name);
// MAP_NORESERVE is implicit with FreeBSD
return MmapFixed(fixed_addr, size, MAP_ALIGNED_SUPER, name);
#else
bool r = MmapFixedNoReserve(fixed_addr, size, name);
if (r)
SetShadowRegionHugePageMode(fixed_addr, size);
return r;
#endif
}
uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) { uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name) base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name)
: MmapNoAccess(size); : MmapNoAccess(size);

View File

@ -229,15 +229,15 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)) {
// Can be overriden in frontend. // Can be overriden in frontend.
#if SANITIZER_GO && defined(TSAN_EXTERNAL_HOOKS) #if SANITIZER_GO && defined(TSAN_EXTERNAL_HOOKS)
// Implementation must be defined in frontend. // Implementation must be defined in frontend.
extern "C" void OnPrint(const char *str); extern "C" void __sanitizer_on_print(const char *str);
#else #else
SANITIZER_INTERFACE_WEAK_DEF(void, OnPrint, const char *str) { SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_on_print, const char *str) {
(void)str; (void)str;
} }
#endif #endif
static void CallPrintfAndReportCallback(const char *str) { static void CallPrintfAndReportCallback(const char *str) {
OnPrint(str); __sanitizer_on_print(str);
if (PrintfAndReportCallback) if (PrintfAndReportCallback)
PrintfAndReportCallback(str); PrintfAndReportCallback(str);
} }

View File

@ -37,7 +37,7 @@ struct MemoryMappedSegmentData;
class MemoryMappedSegment { class MemoryMappedSegment {
public: public:
MemoryMappedSegment(char *buff = nullptr, uptr size = 0) explicit MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
: filename(buff), filename_size(size), data_(nullptr) {} : filename(buff), filename_size(size), data_(nullptr) {}
~MemoryMappedSegment() {} ~MemoryMappedSegment() {}

View File

@ -181,13 +181,14 @@ const mach_header *get_dyld_hdr() {
// Note that the segment addresses are not necessarily sorted. // Note that the segment addresses are not necessarily sorted.
template <u32 kLCSegment, typename SegmentCommand> template <u32 kLCSegment, typename SegmentCommand>
static bool NextSegmentLoad(MemoryMappedSegment *segment, static bool NextSegmentLoad(MemoryMappedSegment *segment,
MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) { MemoryMappedSegmentData *seg_data,
const char *lc = layout_data.current_load_cmd_addr; MemoryMappingLayoutData *layout_data) {
layout_data.current_load_cmd_addr += ((const load_command *)lc)->cmdsize; const char *lc = layout_data->current_load_cmd_addr;
layout_data->current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
if (((const load_command *)lc)->cmd == kLCSegment) { if (((const load_command *)lc)->cmd == kLCSegment) {
const SegmentCommand* sc = (const SegmentCommand *)lc; const SegmentCommand* sc = (const SegmentCommand *)lc;
uptr base_virt_addr, addr_mask; uptr base_virt_addr, addr_mask;
if (layout_data.current_image == kDyldImageIdx) { if (layout_data->current_image == kDyldImageIdx) {
base_virt_addr = (uptr)get_dyld_hdr(); base_virt_addr = (uptr)get_dyld_hdr();
// vmaddr is masked with 0xfffff because on macOS versions < 10.12, // vmaddr is masked with 0xfffff because on macOS versions < 10.12,
// it contains an absolute address rather than an offset for dyld. // it contains an absolute address rather than an offset for dyld.
@ -198,7 +199,7 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
addr_mask = 0xfffff; addr_mask = 0xfffff;
} else { } else {
base_virt_addr = base_virt_addr =
(uptr)_dyld_get_image_vmaddr_slide(layout_data.current_image); (uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);
addr_mask = ~0; addr_mask = ~0;
} }
@ -219,18 +220,18 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
// Return the initial protection. // Return the initial protection.
segment->protection = sc->initprot; segment->protection = sc->initprot;
segment->offset = (layout_data.current_filetype == segment->offset = (layout_data->current_filetype ==
/*MH_EXECUTE*/ 0x2) /*MH_EXECUTE*/ 0x2)
? sc->vmaddr ? sc->vmaddr
: sc->fileoff; : sc->fileoff;
if (segment->filename) { if (segment->filename) {
const char *src = (layout_data.current_image == kDyldImageIdx) const char *src = (layout_data->current_image == kDyldImageIdx)
? kDyldPath ? kDyldPath
: _dyld_get_image_name(layout_data.current_image); : _dyld_get_image_name(layout_data->current_image);
internal_strncpy(segment->filename, src, segment->filename_size); internal_strncpy(segment->filename, src, segment->filename_size);
} }
segment->arch = layout_data.current_arch; segment->arch = layout_data->current_arch;
internal_memcpy(segment->uuid, layout_data.current_uuid, kModuleUUIDSize); internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
return true; return true;
} }
return false; return false;
@ -331,14 +332,14 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
#ifdef MH_MAGIC_64 #ifdef MH_MAGIC_64
case MH_MAGIC_64: { case MH_MAGIC_64: {
if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>( if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
segment, segment->data_, data_)) segment, segment->data_, &data_))
return true; return true;
break; break;
} }
#endif #endif
case MH_MAGIC: { case MH_MAGIC: {
if (NextSegmentLoad<LC_SEGMENT, struct segment_command>( if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
segment, segment->data_, data_)) segment, segment->data_, &data_))
return true; return true;
break; break;
} }

View File

@ -60,8 +60,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 GCC. // layouts. Assume LLVM.
return bp_prev - 1; return bp_prev;
#else #else
return (uhwptr*)bp; return (uhwptr*)bp;
#endif #endif
@ -84,21 +84,14 @@ 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 on the // PowerPC ABIs specify that the return address is saved at offset
// *caller's* stack frame. Thus we must dereference the back chain // 16 of the *caller's* stack frame. Thus we must dereference the
// to find the caller frame before extracting it. // back chain 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];
#else #else

View File

@ -150,8 +150,9 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt,
} }
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
int __sanitizer_get_module_and_offset_for_pc( // NOLINT int __sanitizer_get_module_and_offset_for_pc(uptr pc, char *module_name,
uptr pc, char *module_name, uptr module_name_len, uptr *pc_offset) { uptr module_name_len,
uptr *pc_offset) {
return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len, return __sanitizer::GetModuleAndOffsetForPc(pc, module_name, module_name_len,
pc_offset); pc_offset);
} }

View File

@ -223,10 +223,11 @@ bool ThreadSuspender::SuspendAllThreads() {
case ThreadLister::Ok: case ThreadLister::Ok:
break; break;
} }
for (tid_t tid : threads) for (tid_t tid : threads) {
if (SuspendThread(tid)) if (SuspendThread(tid))
retry = true; retry = true;
}; }
}
return suspended_threads_list_.ThreadCount(); return suspended_threads_list_.ThreadCount();
} }

View File

@ -42,7 +42,7 @@ class SuppressionContext {
void GetMatched(InternalMmapVector<Suppression *> *matched); void GetMatched(InternalMmapVector<Suppression *> *matched);
private: private:
static const int kMaxSuppressionTypes = 32; static const int kMaxSuppressionTypes = 64;
const char **const suppression_types_; const char **const suppression_types_;
const int suppression_types_num_; const int suppression_types_num_;

View File

@ -76,7 +76,7 @@ class SymbolizerTool {
// SymbolizerProcess may not be used from two threads simultaneously. // SymbolizerProcess may not be used from two threads simultaneously.
class SymbolizerProcess { class SymbolizerProcess {
public: public:
explicit SymbolizerProcess(const char *path, bool use_forkpty = false); explicit SymbolizerProcess(const char *path, bool use_posix_spawn = false);
const char *SendCommand(const char *command); const char *SendCommand(const char *command);
protected: protected:
@ -114,7 +114,7 @@ class SymbolizerProcess {
uptr times_restarted_; uptr times_restarted_;
bool failed_to_start_; bool failed_to_start_;
bool reported_invalid_path_; bool reported_invalid_path_;
bool use_forkpty_; bool use_posix_spawn_;
}; };
class LLVMSymbolizerProcess; class LLVMSymbolizerProcess;

View File

@ -238,7 +238,8 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
// <empty line> // <empty line>
class LLVMSymbolizerProcess : public SymbolizerProcess { class LLVMSymbolizerProcess : public SymbolizerProcess {
public: public:
explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {} explicit LLVMSymbolizerProcess(const char *path)
: SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_MAC) {}
private: private:
bool ReachedEndOfOutput(const char *buffer, uptr length) const override { bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
@ -452,14 +453,14 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,
return symbolizer_process_->SendCommand(buffer_); return symbolizer_process_->SendCommand(buffer_);
} }
SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty) SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
: path_(path), : path_(path),
input_fd_(kInvalidFd), input_fd_(kInvalidFd),
output_fd_(kInvalidFd), output_fd_(kInvalidFd),
times_restarted_(0), times_restarted_(0),
failed_to_start_(false), failed_to_start_(false),
reported_invalid_path_(false), reported_invalid_path_(false),
use_forkpty_(use_forkpty) { use_posix_spawn_(use_posix_spawn) {
CHECK(path_); CHECK(path_);
CHECK_NE(path_[0], '\0'); CHECK_NE(path_[0], '\0');
} }

View File

@ -50,14 +50,14 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
class AtosSymbolizerProcess : public SymbolizerProcess { class AtosSymbolizerProcess : public SymbolizerProcess {
public: public:
explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid) explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid)
: SymbolizerProcess(path, /*use_forkpty*/ true) { : SymbolizerProcess(path, /*use_posix_spawn*/ true) {
// Put the string command line argument in the object so that it outlives // Put the string command line argument in the object so that it outlives
// the call to GetArgV. // the call to GetArgV.
internal_snprintf(pid_str_, sizeof(pid_str_), "%d", parent_pid); internal_snprintf(pid_str_, sizeof(pid_str_), "%d", parent_pid);
} }
private: private:
virtual bool StartSymbolizerSubprocess() override { bool StartSymbolizerSubprocess() override {
// Configure sandbox before starting atos process. // Configure sandbox before starting atos process.
return SymbolizerProcess::StartSymbolizerSubprocess(); return SymbolizerProcess::StartSymbolizerSubprocess();
} }

View File

@ -33,10 +33,6 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#if SANITIZER_MAC
#include <util.h> // for forkpty()
#endif // SANITIZER_MAC
// C++ demangling function, as required by Itanium C++ ABI. This is weak, // C++ demangling function, as required by Itanium C++ ABI. This is weak,
// because we do not require a C++ ABI library to be linked to a program // because we do not require a C++ ABI library to be linked to a program
// using sanitizers; if it's not present, we'll just use the mangled name. // using sanitizers; if it's not present, we'll just use the mangled name.
@ -151,80 +147,32 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
return false; return false;
} }
int pid = -1; const char *argv[kArgVMax];
GetArgV(path_, argv);
pid_t pid;
int infd[2]; if (use_posix_spawn_) {
internal_memset(&infd, 0, sizeof(infd));
int outfd[2];
internal_memset(&outfd, 0, sizeof(outfd));
if (!CreateTwoHighNumberedPipes(infd, outfd)) {
Report("WARNING: Can't create a socket pair to start "
"external symbolizer (errno: %d)\n", errno);
return false;
}
if (use_forkpty_) {
#if SANITIZER_MAC #if SANITIZER_MAC
fd_t fd = kInvalidFd; fd_t fd = internal_spawn(argv, &pid);
if (fd == kInvalidFd) {
// forkpty redirects stdout and stderr into a single stream, so we would Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
// receive error messages as standard replies. To avoid that, let's dup
// stderr and restore it in the child.
int saved_stderr = dup(STDERR_FILENO);
CHECK_GE(saved_stderr, 0);
// We only need one pipe, for stdin of the child.
close(outfd[0]);
close(outfd[1]);
// Use forkpty to disable buffering in the new terminal.
pid = internal_forkpty(&fd);
if (pid == -1) {
// forkpty() failed.
Report("WARNING: failed to fork external symbolizer (errno: %d)\n",
errno); errno);
return false; return false;
} else if (pid == 0) {
// Child subprocess.
// infd[0] is the child's reading end.
close(infd[1]);
// Set up stdin to read from the pipe.
CHECK_GE(dup2(infd[0], STDIN_FILENO), 0);
close(infd[0]);
// Restore stderr.
CHECK_GE(dup2(saved_stderr, STDERR_FILENO), 0);
close(saved_stderr);
const char *argv[kArgVMax];
GetArgV(path_, argv);
execv(path_, const_cast<char **>(&argv[0]));
internal__exit(1);
} }
// Input for the child, infd[1] is our writing end.
output_fd_ = infd[1];
close(infd[0]);
// Continue execution in parent process.
input_fd_ = fd; input_fd_ = fd;
output_fd_ = fd;
close(saved_stderr);
// Disable echo in the new terminal, disable CR.
struct termios termflags;
tcgetattr(fd, &termflags);
termflags.c_oflag &= ~ONLCR;
termflags.c_lflag &= ~ECHO;
tcsetattr(fd, TCSANOW, &termflags);
#else // SANITIZER_MAC #else // SANITIZER_MAC
UNIMPLEMENTED(); UNIMPLEMENTED();
#endif // SANITIZER_MAC #endif // SANITIZER_MAC
} else { } else {
const char *argv[kArgVMax]; fd_t infd[2] = {}, outfd[2] = {};
GetArgV(path_, argv); if (!CreateTwoHighNumberedPipes(infd, outfd)) {
Report("WARNING: Can't create a socket pair to start "
"external symbolizer (errno: %d)\n", errno);
return false;
}
pid = StartSubprocess(path_, argv, /* stdin */ outfd[0], pid = StartSubprocess(path_, argv, /* stdin */ outfd[0],
/* stdout */ infd[1]); /* stdout */ infd[1]);
if (pid < 0) { if (pid < 0) {

View File

@ -106,8 +106,9 @@ void ReportMmapWriteExec(int prot) {
if (StackTrace::WillUseFastUnwind(fast)) { if (StackTrace::WillUseFastUnwind(fast)) {
GetThreadStackTopAndBottom(false, &top, &bottom); GetThreadStackTopAndBottom(false, &top, &bottom);
stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true); stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
} else } else {
stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false); stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
}
Printf("%s", d.Warning()); Printf("%s", d.Warning());
Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName); Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
@ -190,9 +191,14 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
SanitizerCommonDecorator d; SanitizerCommonDecorator d;
Printf("%s", d.Warning()); Printf("%s", d.Warning());
const char *description = sig.Describe(); const char *description = sig.Describe();
Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n", if (sig.is_memory_access && !sig.is_true_faulting_addr)
SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc, Report("ERROR: %s: %s on unknown address (pc %p bp %p sp %p T%d)\n",
(void *)sig.bp, (void *)sig.sp, tid); SanitizerToolName, description, (void *)sig.pc, (void *)sig.bp,
(void *)sig.sp, tid);
else
Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
(void *)sig.bp, (void *)sig.sp, tid);
Printf("%s", d.Default()); Printf("%s", d.Default());
if (sig.pc < GetPageSizeCached()) if (sig.pc < GetPageSizeCached())
Report("Hint: pc points to the zero page.\n"); Report("Hint: pc points to the zero page.\n");
@ -202,7 +208,11 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
? "WRITE" ? "WRITE"
: (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
Report("The signal is caused by a %s memory access.\n", access_type); Report("The signal is caused by a %s memory access.\n", access_type);
if (sig.addr < GetPageSizeCached()) if (!sig.is_true_faulting_addr)
Report("Hint: this fault was caused by a dereference of a high value "
"address (see register values below). Dissassemble the provided "
"pc to learn which register was used.\n");
else if (sig.addr < GetPageSizeCached())
Report("Hint: address points to the zero page.\n"); Report("Hint: address points to the zero page.\n");
} }
MaybeReportNonExecRegion(sig.pc); MaybeReportNonExecRegion(sig.pc);

View File

@ -84,7 +84,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
} // namespace __sanitizer } // namespace __sanitizer
using namespace __sanitizer; // NOLINT using namespace __sanitizer;
extern "C" { extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE

View File

@ -27,6 +27,8 @@
namespace __sanitizer { namespace __sanitizer {
namespace {
//---------------------------- UnwindSlow -------------------------------------- //---------------------------- UnwindSlow --------------------------------------
typedef struct { typedef struct {
@ -46,38 +48,6 @@ release_my_map_info_list_func release_my_map_info_list;
unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch; unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
} // extern "C" } // extern "C"
#if SANITIZER_ANDROID
void SanitizerInitializeUnwinder() {
if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;
// Pre-lollipop Android can not unwind through signal handler frames with
// libgcc unwinder, but it has a libcorkscrew.so library with the necessary
// workarounds.
void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
if (!p) {
VReport(1,
"Failed to open libcorkscrew.so. You may see broken stack traces "
"in SEGV reports.");
return;
}
acquire_my_map_info_list =
(acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
release_my_map_info_list =
(release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
p, "unwind_backtrace_signal_arch");
if (!acquire_my_map_info_list || !release_my_map_info_list ||
!unwind_backtrace_signal_arch) {
VReport(1,
"Failed to find one of the required symbols in libcorkscrew.so. "
"You may see broken stack traces in SEGV reports.");
acquire_my_map_info_list = 0;
unwind_backtrace_signal_arch = 0;
release_my_map_info_list = 0;
}
}
#endif
#if defined(__arm__) && !SANITIZER_NETBSD #if defined(__arm__) && !SANITIZER_NETBSD
// NetBSD uses dwarf EH // NetBSD uses dwarf EH
#define UNWIND_STOP _URC_END_OF_STACK #define UNWIND_STOP _URC_END_OF_STACK
@ -119,6 +89,40 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
return UNWIND_CONTINUE; return UNWIND_CONTINUE;
} }
} // namespace
#if SANITIZER_ANDROID
void SanitizerInitializeUnwinder() {
if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;
// Pre-lollipop Android can not unwind through signal handler frames with
// libgcc unwinder, but it has a libcorkscrew.so library with the necessary
// workarounds.
void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
if (!p) {
VReport(1,
"Failed to open libcorkscrew.so. You may see broken stack traces "
"in SEGV reports.");
return;
}
acquire_my_map_info_list =
(acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
release_my_map_info_list =
(release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
p, "unwind_backtrace_signal_arch");
if (!acquire_my_map_info_list || !release_my_map_info_list ||
!unwind_backtrace_signal_arch) {
VReport(1,
"Failed to find one of the required symbols in libcorkscrew.so. "
"You may see broken stack traces in SEGV reports.");
acquire_my_map_info_list = 0;
unwind_backtrace_signal_arch = 0;
release_my_map_info_list = 0;
}
}
#endif
void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
CHECK_GE(max_depth, 2); CHECK_GE(max_depth, 2);
size = 0; size = 0;

View File

@ -23,11 +23,7 @@ namespace __sanitizer {
template<typename T> template<typename T>
class Vector { class Vector {
public: public:
explicit Vector() Vector() : begin_(), end_(), last_() {}
: begin_()
, end_()
, last_() {
}
~Vector() { ~Vector() {
if (begin_) if (begin_)

View File

@ -239,6 +239,11 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
return true; return true;
} }
bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
// FIXME: Windows support large pages too. Might be worth checking
return MmapFixedNoReserve(fixed_addr, size, name);
}
// Memory space mapped by 'MmapFixedOrDie' must have been reserved by // Memory space mapped by 'MmapFixedOrDie' must have been reserved by
// 'MmapFixedNoAccess'. // 'MmapFixedNoAccess'.
void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) { void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
@ -671,7 +676,7 @@ static int RunAtexit() {
return ret; return ret;
} }
#pragma section(".CRT$XID", long, read) // NOLINT #pragma section(".CRT$XID", long, read)
__declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit; __declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
#endif #endif
@ -940,6 +945,11 @@ bool SignalContext::IsMemoryAccess() const {
return GetWriteFlag() != SignalContext::UNKNOWN; return GetWriteFlag() != SignalContext::UNKNOWN;
} }
bool SignalContext::IsTrueFaultingAddress() const {
// FIXME: Provide real implementation for this. See Linux and Mac variants.
return IsMemoryAccess();
}
SignalContext::WriteFlag SignalContext::GetWriteFlag() const { SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo; EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
// The contents of this array are documented at // The contents of this array are documented at

View File

@ -43,6 +43,8 @@
#define STRINGIFY_(A) #A #define STRINGIFY_(A) #A
#define STRINGIFY(A) STRINGIFY_(A) #define STRINGIFY(A) STRINGIFY_(A)
#if !SANITIZER_GO
// ----------------- A workaround for the absence of weak symbols -------------- // ----------------- A workaround for the absence of weak symbols --------------
// We don't have a direct equivalent of weak symbols when using MSVC, but we can // We don't have a direct equivalent of weak symbols when using MSVC, but we can
// use the /alternatename directive to tell the linker to default a specific // use the /alternatename directive to tell the linker to default a specific
@ -158,5 +160,15 @@
// return a >= b; // return a >= b;
// } // }
// //
#else // SANITIZER_GO
// Go neither needs nor wants weak references.
// The shenanigans above don't work for gcc.
# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...) \
extern "C" ReturnType Name(__VA_ARGS__)
#endif // SANITIZER_GO
#endif // SANITIZER_WINDOWS #endif // SANITIZER_WINDOWS
#endif // SANITIZER_WIN_DEFS_H #endif // SANITIZER_WIN_DEFS_H

View File

@ -54,8 +54,8 @@ int dllThunkInterceptWhenPossible(const char* main_function,
#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) #define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
#include "sanitizer_common_interface.inc" #include "sanitizer_common_interface.inc"
#pragma section(".DLLTH$A", read) // NOLINT #pragma section(".DLLTH$A", read)
#pragma section(".DLLTH$Z", read) // NOLINT #pragma section(".DLLTH$Z", read)
typedef void (*DllThunkCB)(); typedef void (*DllThunkCB)();
extern "C" { extern "C" {
@ -85,7 +85,7 @@ extern "C" int __dll_thunk_init() {
// We want to call dll_thunk_init before C/C++ initializers / constructors are // We want to call dll_thunk_init before C/C++ initializers / constructors are
// executed, otherwise functions like memset might be invoked. // executed, otherwise functions like memset might be invoked.
#pragma section(".CRT$XIB", long, read) // NOLINT #pragma section(".CRT$XIB", long, read)
__declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() = __declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() =
__dll_thunk_init; __dll_thunk_init;
@ -94,7 +94,7 @@ static void WINAPI dll_thunk_thread_init(void *mod, unsigned long reason,
if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init(); if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init();
} }
#pragma section(".CRT$XLAB", long, read) // NOLINT #pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *, __declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *,
unsigned long, void *) = dll_thunk_thread_init; unsigned long, void *) = dll_thunk_thread_init;

View File

@ -38,6 +38,7 @@ int interceptWhenPossible(uptr dll_function, const char *real_function) {
// Declare weak hooks. // Declare weak hooks.
extern "C" { extern "C" {
void __sanitizer_on_print(const char *str);
void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1, void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1,
const void *s2, uptr n, int result); const void *s2, uptr n, int result);
void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1, void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1,
@ -53,8 +54,8 @@ void __sanitizer_weak_hook_strstr(uptr called_pc, const char *s1,
#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) #define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
#include "sanitizer_common_interface.inc" #include "sanitizer_common_interface.inc"
#pragma section(".WEAK$A", read) // NOLINT #pragma section(".WEAK$A", read)
#pragma section(".WEAK$Z", read) // NOLINT #pragma section(".WEAK$Z", read)
typedef void (*InterceptCB)(); typedef void (*InterceptCB)();
extern "C" { extern "C" {
@ -77,7 +78,7 @@ static int weak_intercept_init() {
return 0; return 0;
} }
#pragma section(".CRT$XIB", long, read) // NOLINT #pragma section(".CRT$XIB", long, read)
__declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() = __declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() =
weak_intercept_init; weak_intercept_init;
@ -86,7 +87,7 @@ static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason,
if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init(); if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init();
} }
#pragma section(".CRT$XLAB", long, read) // NOLINT #pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)( __declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)(
void *, unsigned long, void *) = weak_intercept_thread_init; void *, unsigned long, void *) = weak_intercept_thread_init;

View File

@ -31,11 +31,11 @@ typedef void (^dispatch_block_t)(void);
typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t data, typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t data,
int error); int error);
typedef long dispatch_once_t; // NOLINT typedef long dispatch_once_t;
typedef __sanitizer::u64 dispatch_time_t; typedef __sanitizer::u64 dispatch_time_t;
typedef int dispatch_fd_t; // NOLINT typedef int dispatch_fd_t;
typedef unsigned long dispatch_io_type_t; // NOLINT typedef unsigned long dispatch_io_type_t;
typedef unsigned long dispatch_io_close_flags_t; // NOLINT typedef unsigned long dispatch_io_close_flags_t;
extern "C" { extern "C" {
void *dispatch_get_context(dispatch_object_t object); void *dispatch_get_context(dispatch_object_t object);
@ -57,10 +57,10 @@ extern const dispatch_block_t _dispatch_data_destructor_munmap;
#endif #endif
// Data types used in dispatch APIs // Data types used in dispatch APIs
typedef unsigned long size_t; // NOLINT typedef unsigned long size_t;
typedef unsigned long uintptr_t; // NOLINT typedef unsigned long uintptr_t;
typedef __sanitizer::s64 off_t; typedef __sanitizer::s64 off_t;
typedef __sanitizer::u16 mode_t; typedef __sanitizer::u16 mode_t;
typedef long long_t; // NOLINT typedef long long_t;
#endif // TSAN_DISPATCH_DEFS_H #endif // TSAN_DISPATCH_DEFS_H

View File

@ -25,7 +25,7 @@ static TagData registered_tags[kExternalTagMax] = {
{}, {},
{"Swift variable", "Swift access race"}, {"Swift variable", "Swift access race"},
}; };
static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable}; // NOLINT. static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable};
static TagData *GetTagData(uptr tag) { static TagData *GetTagData(uptr tag) {
// Invalid/corrupted tag? Better return NULL and let the caller deal with it. // Invalid/corrupted tag? Better return NULL and let the caller deal with it.
if (tag >= atomic_load(&used_tags, memory_order_relaxed)) return nullptr; if (tag >= atomic_load(&used_tags, memory_order_relaxed)) return nullptr;

View File

@ -86,7 +86,8 @@ static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) {
else else
user_free(thr, pc, p, false); user_free(thr, pc, p, false);
} }
return &((FdDesc*)l1)[fd % kTableSizeL2]; // NOLINT FdDesc *fds = reinterpret_cast<FdDesc *>(l1);
return &fds[fd % kTableSizeL2];
} }
// pd must be already ref'ed. // pd must be already ref'ed.

View File

@ -1,4 +1,4 @@
//===-- tsan_libdispatch.cpp ----------------------------------------------===// //===-- tsan_interceptors_libdispatch.cpp ---------------------------------===//
// //
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.
@ -16,6 +16,7 @@
#include "tsan_interceptors.h" #include "tsan_interceptors.h"
#include "tsan_rtl.h" #include "tsan_rtl.h"
#include "BlocksRuntime/Block.h"
#include "tsan_dispatch_defs.h" #include "tsan_dispatch_defs.h"
namespace __tsan { namespace __tsan {

View File

@ -23,13 +23,14 @@
#include <errno.h> #include <errno.h>
#include <libkern/OSAtomic.h> #include <libkern/OSAtomic.h>
#include <objc/objc-sync.h> #include <objc/objc-sync.h>
#include <os/lock.h>
#include <sys/ucontext.h> #include <sys/ucontext.h>
#if defined(__has_include) && __has_include(<xpc/xpc.h>) #if defined(__has_include) && __has_include(<xpc/xpc.h>)
#include <xpc/xpc.h> #include <xpc/xpc.h>
#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>) #endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
typedef long long_t; // NOLINT typedef long long_t;
extern "C" { extern "C" {
int getcontext(ucontext_t *ucp) __attribute__((returns_twice)); int getcontext(ucontext_t *ucp) __attribute__((returns_twice));
@ -246,6 +247,45 @@ TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) {
REAL(os_lock_unlock)(lock); REAL(os_lock_unlock)(lock);
} }
TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
return REAL(os_unfair_lock_lock)(lock);
}
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock, lock);
REAL(os_unfair_lock_lock)(lock);
Acquire(thr, pc, (uptr)lock);
}
TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
u32 options) {
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
return REAL(os_unfair_lock_lock_with_options)(lock, options);
}
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_options, lock, options);
REAL(os_unfair_lock_lock_with_options)(lock, options);
Acquire(thr, pc, (uptr)lock);
}
TSAN_INTERCEPTOR(bool, os_unfair_lock_trylock, os_unfair_lock_t lock) {
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
return REAL(os_unfair_lock_trylock)(lock);
}
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_trylock, lock);
bool result = REAL(os_unfair_lock_trylock)(lock);
if (result)
Acquire(thr, pc, (uptr)lock);
return result;
}
TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
return REAL(os_unfair_lock_unlock)(lock);
}
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_unlock, lock);
Release(thr, pc, (uptr)lock);
REAL(os_unfair_lock_unlock)(lock);
}
#if defined(__has_include) && __has_include(<xpc/xpc.h>) #if defined(__has_include) && __has_include(<xpc/xpc.h>)
TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler, TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,

Some files were not shown because too many files have changed in this diff Show More