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>
PR sanitizer/92154

View File

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

View File

@ -1075,7 +1075,7 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
} // namespace __lsan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
// 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.

View File

@ -25,7 +25,7 @@ using namespace __asan;
static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
char *name, uptr name_size,
uptr &region_address, uptr &region_size) {
uptr *region_address, uptr *region_size) {
InternalMmapVector<StackVarDescr> vars;
vars.reserve(16);
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'.
internal_strlcpy(name, vars[i].name_pos,
Min(name_size, vars[i].name_len + 1));
region_address = addr - (offset - vars[i].beg);
region_size = vars[i].size;
*region_address = addr - (offset - vars[i].beg);
*region_size = vars[i].size;
return;
}
}
@ -108,7 +108,7 @@ const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
// region_{address,size} are already 0
} else {
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()) {
region_kind = "global";

View File

@ -203,7 +203,7 @@ class AddressDescription {
AddressDescription() = default;
// shouldLockThreadRegistry allows us to skip locking if we're sure we already
// have done it.
AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
: AddressDescription(addr, 1, shouldLockThreadRegistry) {}
AddressDescription(uptr addr, uptr access_size,
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
// print it.
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() {
@ -244,7 +245,7 @@ void ErrorInvalidPosixMemalignAlignment::Print() {
"ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
"%zd, alignment must be a power of two and a multiple of sizeof(void*) "
"== %zd (thread %s)\n",
alignment, sizeof(void*), AsanThreadIdAndName(tid).c_str()); // NOLINT
alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str());
Printf("%s", d.Default());
stack->Print();
PrintHintAllocatorCannotReturnNull();

View File

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

View File

@ -139,10 +139,10 @@ ASAN_FLAG(
"If >= 2, detect operations like <, <=, >, >= and - on invalid pointer "
"pairs (e.g. when pointers belong to different objects); "
"If == 1, detect invalid operations only when both pointers are non-null.")
ASAN_FLAG(
bool, detect_container_overflow, true,
"If true, honor the container overflow annotations. See "
"https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow")
ASAN_FLAG(bool, detect_container_overflow, true,
"If true, honor the container overflow annotations. See "
"https://github.com/google/sanitizers/wiki/"
"AddressSanitizerContainerOverflow")
ASAN_FLAG(int, detect_odr_violation, 2,
"If >=2, detect violation of One-Definition-Rule (ODR); "
"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,
"Check position of ASan runtime in library list (needs to be disabled"
" when other library has to be preloaded system-wide)")
ASAN_FLAG(bool, windows_hook_rtl_allocators, false,
"(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")
ASAN_FLAG(
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:
// 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
@ -199,6 +216,8 @@ static void RegisterGlobal(const Global *g) {
// where two globals with the same name are defined in different modules.
if (UseODRIndicator(g))
CheckODRViolationViaIndicator(g);
else
CheckODRViolationViaPoisoning(g);
}
if (CanPoisonMemory())
PoisonRedZones(*g);
@ -208,8 +227,7 @@ static void RegisterGlobal(const Global *g) {
list_of_all_globals = l;
if (g->has_dynamic_init) {
if (!dynamic_init_globals) {
dynamic_init_globals =
new (allocator_for_globals) VectorOfGlobals; // NOLINT
dynamic_init_globals = new (allocator_for_globals) VectorOfGlobals;
dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity);
}
DynInitGlobal dyn_global = { *g, false };
@ -296,8 +314,7 @@ void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
// Apply __asan_register_globals to all globals found in the same loaded
// 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);
if (!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);
}
GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};

View File

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

View File

@ -79,7 +79,7 @@ int OnExit() {
} // namespace __asan
// ---------------------- Wrappers ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
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); \
} 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_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|
// argument irrespective of the |from| length.
INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
uptr from_length = REAL(strlen)(from);
ASAN_READ_RANGE(ctx, from, from_length + 1);
uptr to_length = REAL(strlen)(to);
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
// If the copying actually happens, the |from| string should not overlap
// with the resulting string starting at |to|, which has a length of
// to_length + from_length + 1.
if (from_length > 0) {
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
from, from_length + 1);
INTERCEPTOR(char *, strcat, char *to, const char *from) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strcat);
ENSURE_ASAN_INITED();
if (flags()->replace_str) {
uptr from_length = REAL(strlen)(from);
ASAN_READ_RANGE(ctx, from, from_length + 1);
uptr to_length = REAL(strlen)(to);
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
// If the copying actually happens, the |from| string should not overlap
// with the resulting string starting at |to|, which has a length of
// to_length + from_length + 1.
if (from_length > 0) {
CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
from_length + 1);
}
}
return REAL(strcat)(to, from);
}
return REAL(strcat)(to, from); // NOLINT
}
INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
void *ctx;
@ -413,16 +418,17 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr 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;
ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
#if SANITIZER_MAC
if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
if (UNLIKELY(!asan_inited))
return REAL(strcpy)(to, from);
#endif
// strcpy is called from malloc_default_purgeable_zone()
// in __asan::ReplaceSystemAlloc() on Mac.
if (asan_init_is_running) {
return REAL(strcpy)(to, from); // NOLINT
return REAL(strcpy)(to, from);
}
ENSURE_ASAN_INITED();
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_WRITE_RANGE(ctx, to, from_size);
}
return REAL(strcpy)(to, from); // NOLINT
return REAL(strcpy)(to, from);
}
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);
}
INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
char **endptr, int base) {
INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtol);
ENSURE_ASAN_INITED();
@ -488,7 +493,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
return REAL(strtol)(nptr, endptr, base);
}
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);
return result;
}
@ -514,7 +519,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
return result;
}
INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
INTERCEPTOR(long, atol, const char *nptr) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atol);
#if SANITIZER_MAC
@ -525,15 +530,14 @@ INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
return REAL(atol)(nptr);
}
char *real_endptr;
long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
long result = REAL(strtol)(nptr, &real_endptr, 10);
FixRealStrtolEndptr(nptr, &real_endptr);
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
return result;
}
#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
char **endptr, int base) {
INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
ENSURE_ASAN_INITED();
@ -541,12 +545,12 @@ INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
return REAL(strtoll)(nptr, endptr, base);
}
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);
return result;
}
INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
INTERCEPTOR(long long, atoll, const char *nptr) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atoll);
ENSURE_ASAN_INITED();
@ -554,31 +558,66 @@ INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
return REAL(atoll)(nptr);
}
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);
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
return result;
}
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
#if ASAN_INTERCEPT___CXA_ATEXIT
#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
static void AtCxaAtexit(void *unused) {
(void)unused;
StopInitOrderChecking();
}
#endif
#if ASAN_INTERCEPT___CXA_ATEXIT
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
void *dso_handle) {
#if SANITIZER_MAC
if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
#endif
ENSURE_ASAN_INITED();
#if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler disabler;
#endif
int res = REAL(__cxa_atexit)(func, arg, dso_handle);
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
return res;
}
#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
DEFINE_REAL(int, vfork)
DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
@ -594,8 +633,8 @@ void InitializeAsanInterceptors() {
InitializeSignalInterceptors();
// Intercept str* functions.
ASAN_INTERCEPT_FUNC(strcat); // NOLINT
ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
ASAN_INTERCEPT_FUNC(strcat);
ASAN_INTERCEPT_FUNC(strcpy);
ASAN_INTERCEPT_FUNC(strncat);
ASAN_INTERCEPT_FUNC(strncpy);
ASAN_INTERCEPT_FUNC(strdup);
@ -661,6 +700,14 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(__cxa_atexit);
#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
ASAN_INTERCEPT_FUNC(vfork);
#endif

View File

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

View File

@ -16,7 +16,7 @@
#include "asan_stack.h"
#include "asan_suppressions.h"
using namespace __asan; // NOLINT
using namespace __asan;
void *__asan_memcpy(void *to, const void *from, uptr 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
using namespace __asan; // NOLINT
using namespace __asan;
// Wrap |ctxt| and |func| into an asan_block_context_t.
// The caller retains control of the allocated context.

View File

@ -27,7 +27,7 @@
#include "asan_stack.h"
// ---------------------- Replacement functions ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
static uptr allocated_for_dlsym;
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);
}
using namespace __asan; // NOLINT
using namespace __asan;
// MT: Simply defining functions with the same signature in *.obj
// files overrides the standard functions in the CRT.
@ -528,10 +528,11 @@ void ReplaceSystemMalloc() {
(uptr)WRAP(RtlAllocateHeap),
(uptr *)&REAL(RtlAllocateHeap));
} else {
#define INTERCEPT_UCRT_FUNCTION(func) \
if (!INTERCEPT_FUNCTION_DLLIMPORT("ucrtbase.dll", \
"api-ms-win-core-heap-l1-1-0.dll", func)) \
VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func);
#define INTERCEPT_UCRT_FUNCTION(func) \
if (!INTERCEPT_FUNCTION_DLLIMPORT( \
"ucrtbase.dll", "api-ms-win-core-heap-l1-1-0.dll", func)) { \
VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); \
}
INTERCEPT_UCRT_FUNCTION(HeapAlloc);
INTERCEPT_UCRT_FUNCTION(HeapFree);
INTERCEPT_UCRT_FUNCTION(HeapReAlloc);

View File

@ -163,7 +163,7 @@ static const u64 kDefaultShort64bitShadowOffset =
static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
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 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000
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
#endif
using namespace __asan; // NOLINT
using namespace __asan;
// FreeBSD prior v9.2 have wrong definition of 'size_t'.
// 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
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
// Current implementation of __asan_(un)poison_memory_region doesn't check
// 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) {
switch (flags()->detect_invalid_pointer_pairs) {
case 0 : return;
case 1 : if (p1 == nullptr || p2 == nullptr) return; break;
case 0:
return;
case 1:
if (p1 == nullptr || p2 == nullptr)
return;
break;
}
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
// --------------------------- Interface --------------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
uptr access_size, u32 exp) {

View File

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

View File

@ -402,7 +402,6 @@ static void AsanInitInternal() {
asan_init_is_running = true;
CacheBinaryName();
CheckASLR();
// Initialize flags. This must be done early, because most of the
// initialization steps look at flags().
@ -450,6 +449,7 @@ static void AsanInitInternal() {
SetLowLevelAllocateCallback(OnLowLevelAllocate);
InitializeAsanInterceptors();
CheckASLR();
// Enable system log ("adb logcat") on Android.
// 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).
class AsanInitializer {
public: // NOLINT
public:
AsanInitializer() {
AsanInitFromRtl();
}
@ -554,7 +554,7 @@ static AsanInitializer asan_initializer;
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
using namespace __asan;
void NOINLINE __asan_handle_no_return() {
if (asan_init_is_running)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,7 @@
#include "sanitizer_common/sanitizer_win.h"
#include "sanitizer_common/sanitizer_win_defs.h"
using namespace __asan; // NOLINT
using namespace __asan;
extern "C" {
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,
_EXCEPTION_RECORD *a, void *b, _CONTEXT *c,
_DISPATCHER_CONTEXT *d) { // NOLINT
_DISPATCHER_CONTEXT *d) {
CHECK(REAL(__C_specific_handler));
__asan_handle_no_return();
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
// immediately after the CRT runs. This way, our exception filter is called
// 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)() =
__asan_set_seh_filter;
@ -375,7 +375,7 @@ static void NTAPI asan_thread_init(void *module, DWORD reason, void *reserved) {
__asan_init();
}
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)(
void *, unsigned long, void *) = asan_thread_init;
#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)(
void *, unsigned long, void *) = asan_thread_exit;

View File

@ -67,10 +67,10 @@ INTERCEPT_LIBRARY_FUNCTION(memcmp);
INTERCEPT_LIBRARY_FUNCTION(memcpy);
INTERCEPT_LIBRARY_FUNCTION(memmove);
INTERCEPT_LIBRARY_FUNCTION(memset);
INTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT
INTERCEPT_LIBRARY_FUNCTION(strcat);
INTERCEPT_LIBRARY_FUNCTION(strchr);
INTERCEPT_LIBRARY_FUNCTION(strcmp);
INTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT
INTERCEPT_LIBRARY_FUNCTION(strcpy);
INTERCEPT_LIBRARY_FUNCTION(strcspn);
INTERCEPT_LIBRARY_FUNCTION(strdup);
INTERCEPT_LIBRARY_FUNCTION(strlen);
@ -135,7 +135,7 @@ static int asan_dll_thunk_init() {
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;
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();
}
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
unsigned long, void *) = asan_thread_init;

View File

@ -32,12 +32,12 @@
#include "asan_interface.inc"
// First, declare CRT sections we'll be using in this file
#pragma section(".CRT$XIB", long, read) // NOLINT
#pragma section(".CRT$XID", long, read) // NOLINT
#pragma section(".CRT$XCAB", long, read) // NOLINT
#pragma section(".CRT$XTW", long, read) // NOLINT
#pragma section(".CRT$XTY", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XIB", long, read)
#pragma section(".CRT$XID", long, read)
#pragma section(".CRT$XCAB", long, read)
#pragma section(".CRT$XTW", long, read)
#pragma section(".CRT$XTY", long, read)
#pragma section(".CRT$XLAB", long, read)
////////////////////////////////////////////////////////////////////////////////
// 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"
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));
}

View File

@ -17,10 +17,10 @@
extern "C" {
#endif
typedef char __tsan_atomic8;
typedef short __tsan_atomic16; // NOLINT
typedef int __tsan_atomic32;
typedef long __tsan_atomic64; // NOLINT
typedef char __tsan_atomic8;
typedef short __tsan_atomic16;
typedef int __tsan_atomic32;
typedef long __tsan_atomic64;
#if defined(__SIZEOF_INT128__) \
|| (__clang_major__ * 100 + __clang_minor__ >= 302)
__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.
namespace __interception {
#if defined(_WIN64)
typedef unsigned long long uptr; // NOLINT
typedef unsigned long long uptr;
#else
typedef unsigned long uptr; // NOLINT
typedef unsigned long uptr;
#endif // _WIN64
} // 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.
RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
headers->FileHeader.SizeOfOptionalHeader <
sizeof(IMAGE_OPTIONAL_HEADER)) {
return 0;
@ -963,8 +963,8 @@ bool OverrideImportedFunction(const char *module_to_patch,
// Check that the module header is full and present.
RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
headers->FileHeader.SizeOfOptionalHeader <
sizeof(IMAGE_OPTIONAL_HEADER)) {
return false;

View File

@ -50,7 +50,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(
}
}
using namespace __lsan; // NOLINT
using namespace __lsan;
static void InitializeFlags() {
// Set all the default values.
@ -89,7 +89,7 @@ static void InitializeFlags() {
static void OnStackUnwind(const SignalContext &sig, const void *,
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);
}

View File

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

View File

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

View File

@ -115,10 +115,14 @@ void HandleLeaks() {
if (common_flags()->exitcode) Die();
}
static int DoStopTheWorldCallback(struct dl_phdr_info *info, size_t size,
void *data) {
static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
size_t size, void *data) {
LockThreadRegistry();
LockAllocator();
DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
StopTheWorld(param->callback, param->argument);
UnlockAllocator();
UnlockThreadRegistry();
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
// in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr()
// callback in the parent thread.
void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void *argument) {
DoStopTheWorldParam param = {callback, argument};
dl_iterate_phdr(DoStopTheWorldCallback, &param);
dl_iterate_phdr(LockStuffAndStopTheWorldCallback, &param);
}
} // namespace __lsan

View File

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

View File

@ -345,6 +345,55 @@ INTERCEPTOR(void, thr_exit, tid_t *state) {
#define LSAN_MAYBE_INTERCEPT_THR_EXIT
#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 {
void *(*callback)(void *arg);
void *param;
@ -454,6 +503,12 @@ void InitializeInterceptors() {
LSAN_MAYBE_INTERCEPT__LWP_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 (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
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
using namespace __lsan; // NOLINT
using namespace __lsan;
// Wrap |ctxt| and |func| into an lsan_block_context_t.
// 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/interception interception
merge lib/ubsan ubsan
merge lib/BlocksRuntime/ BlocksRuntime
# Need to merge lib/builtins/assembly.h file:
mkdir -p builtins

View File

@ -54,7 +54,7 @@ INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
// and a multiple of sizeof(void *).
INLINE bool CheckPosixMemalignAlignment(uptr 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.

View File

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

View File

@ -60,7 +60,9 @@
#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
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
#define NO_EXEC_STACK_DIRECTIVE
#endif

View File

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

View File

@ -323,7 +323,7 @@ static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
} // namespace __sanitizer
using namespace __sanitizer; // NOLINT
using namespace __sanitizer;
extern "C" {
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);
bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
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 *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
@ -337,18 +339,18 @@ void ReportMmapWriteExec(int prot);
// Math
#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
extern "C" {
unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT
unsigned char _BitScanReverse(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);
#if defined(_WIN64)
unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask); // NOLINT
unsigned char _BitScanReverse64(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);
#endif
}
#endif
INLINE uptr MostSignificantSetBitIndex(uptr x) {
CHECK_NE(x, 0U);
unsigned long up; // NOLINT
unsigned long up;
#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
# ifdef _WIN64
up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
@ -365,7 +367,7 @@ INLINE uptr MostSignificantSetBitIndex(uptr x) {
INLINE uptr LeastSignificantSetBitIndex(uptr x) {
CHECK_NE(x, 0U);
unsigned long up; // NOLINT
unsigned long up;
#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
# ifdef _WIN64
up = __builtin_ctzll(x);
@ -879,6 +881,11 @@ struct SignalContext {
bool is_memory_access;
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
// constructor
SignalContext() = default;
@ -891,7 +898,8 @@ struct SignalContext {
context(context),
addr(GetAddress()),
is_memory_access(IsMemoryAccess()),
write_flag(GetWriteFlag()) {
write_flag(GetWriteFlag()),
is_true_faulting_addr(IsTrueFaultingAddress()) {
InitPcSpBp();
}
@ -912,6 +920,7 @@ struct SignalContext {
uptr GetAddress() const;
WriteFlag GetWriteFlag() const;
bool IsMemoryAccess() const;
bool IsTrueFaultingAddress() const;
};
void InitializePlatformEarly();
@ -971,7 +980,7 @@ INLINE u32 GetNumberOfCPUsCached() {
} // namespace __sanitizer
inline void *operator new(__sanitizer::operator_new_size_type size,
__sanitizer::LowLevelAllocator &alloc) {
__sanitizer::LowLevelAllocator &alloc) { // NOLINT
return alloc.Allocate(size);
}

View File

@ -36,6 +36,7 @@
// COMMON_INTERCEPTOR_MMAP_IMPL
// COMMON_INTERCEPTOR_COPY_STRING
// COMMON_INTERCEPTOR_STRNDUP_IMPL
// COMMON_INTERCEPTOR_STRERROR
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
@ -301,6 +302,10 @@ bool PlatformHasDifferentMemcpyAndMemmove();
return new_mem;
#endif
#ifndef COMMON_INTERCEPTOR_STRERROR
#define COMMON_INTERCEPTOR_STRERROR() {}
#endif
struct FileMetadata {
// For open_memstream().
char **addr;
@ -1267,9 +1272,8 @@ INTERCEPTOR(int, puts, char *s) {
#endif
#if SANITIZER_INTERCEPT_PRCTL
INTERCEPTOR(int, prctl, int option, unsigned long arg2,
unsigned long arg3, // NOLINT
unsigned long arg4, unsigned long arg5) { // NOLINT
INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
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)
#endif
INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT
INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT
const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
#endif
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
INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
SIZE_T size_to, const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT
SIZE_T size_to, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
#endif
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);
}
int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
if (res >= 0 && msgvec)
if (res >= 0 && msgvec) {
for (int i = 0; i < res; ++i) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
sizeof(msgvec[i].msg_len));
if (common_flags()->intercept_send)
read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
}
}
return res;
}
#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;
if (data) {
if (request == ptrace_setregs)
if (request == ptrace_setregs) {
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);
else if (request == ptrace_setfpxregs)
} else if (request == ptrace_setfpxregs) {
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);
else if (request == ptrace_setsiginfo)
} else if (request == ptrace_setsiginfo) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
// Some kernel might zero the iovec::iov_base in case of invalid
// write access. In this case copy the invalid address for further
// inspection.
else if (request == ptrace_setregset || request == ptrace_getregset) {
} else if (request == ptrace_setregset || request == ptrace_getregset) {
__sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
local_iovec = *iovec;
@ -3238,19 +3244,19 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
if (!res && data) {
// Note that PEEK* requests assign different meaning to the return value.
// 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);
else if (request == ptrace_getfpregs)
} else if (request == ptrace_getfpregs) {
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);
else if (request == ptrace_getvfpregs)
} else if (request == ptrace_getvfpregs) {
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);
else if (request == ptrace_geteventmsg)
} else if (request == ptrace_geteventmsg) {
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;
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
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) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
COMMON_INTERCEPTOR_STRERROR();
char *res = REAL(strerror)(errnum);
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
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_WRITE_RANGE(ctx, dst + dst_size,
(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) {
@ -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_WRITE_RANGE(ctx, dst + dst_size,
(src_size + 1) * sizeof(wchar_t));
return REAL(wcsncat)(dst, src, n); // NOLINT
return REAL(wcsncat)(dst, src, n);
}
#define INIT_WCSCAT \
COMMON_INTERCEPT_FUNCTION(wcscat); \
@ -7843,10 +7850,11 @@ INTERCEPTOR(int, modctl, int operation, void *argp) {
if (iov)
COMMON_INTERCEPTOR_WRITE_RANGE(
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);
else
} else {
ret = REAL(modctl)(operation, argp);
}
return ret;
}
@ -9565,11 +9573,60 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
#define INIT_GETRANDOM
#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() {
#if SI_POSIX
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map =
new ((void *)&metadata_mem) MetadataHashMap(); // NOLINT
interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
#endif
INIT_MMAP;
@ -9864,6 +9921,9 @@ static void InitializeCommonInterceptors() {
INIT_GETUSERSHELL;
INIT_SL_INIT;
INIT_GETRANDOM;
INIT_CRYPT;
INIT_CRYPT_R;
INIT_GETENTROPY;
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_fd)
INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
// Sanitizer weak hooks

View File

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

View File

@ -166,8 +166,8 @@ void InitializeCoverage(bool enabled, const char *dir) {
} // namespace __sanitizer
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT
const uptr* pcs, uptr len) {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr* pcs,
uptr 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
// align the start of the 8-bit counters array. The array will always start 8
// 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;
// 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
// byte, the linker won't try to align it on an 8-byte boundary, so use a
// 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
__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;
#pragma section(".SCOV$GZ", read, write) // NOLINT
#pragma section(".SCOV$GZ", read, write)
__declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
__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.
#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;
#pragma section(".SCOVP$Z", read) // NOLINT
#pragma section(".SCOVP$Z", read)
__declspec(allocate(".SCOVP$Z")) __declspec(align(1)) uint8_t
__stop___sancov_pcs = 0;

View File

@ -199,7 +199,7 @@ char *FindPathToBinary(const char *name) {
} // namespace __sanitizer
using namespace __sanitizer; // NOLINT
using namespace __sanitizer;
extern "C" {
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,
env_option_name);
Die();
} else
} else {
fatal_error("expected '='");
}
}
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; }
protected:
~FlagHandlerBase() {};
~FlagHandlerBase() {}
};
template <typename T>
@ -144,7 +144,7 @@ class FlagParser {
template <typename T>
static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
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);
}

View File

@ -92,11 +92,11 @@ class FlagHandlerInclude : public FlagHandlerBase {
};
void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT
FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
FlagHandlerInclude(parser, /*ignore_missing*/ false);
parser->RegisterHandler("include", fh_include,
"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);
parser->RegisterHandler(
"include_if_exists", fh_include_if_exists,

View File

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

View File

@ -9,6 +9,7 @@
// Common getauxval() guards and definitions.
// getauxval() is not defined until glibc version 2.16, or until API level 21
// for Android.
// Implement the getauxval() compat function for NetBSD.
//
//===----------------------------------------------------------------------===//
@ -16,15 +17,10 @@
#define SANITIZER_GETAUXVAL_H
#include "sanitizer_platform.h"
#include "sanitizer_glibc_version.h"
#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) || \
SANITIZER_FUCHSIA
# define SANITIZER_USE_GETAUXVAL 1
@ -38,10 +34,26 @@
// 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
// on a more recent platform that offers the function.
extern "C" SANITIZER_WEAK_ATTRIBUTE
unsigned long getauxval(unsigned long type); // NOLINT
extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
# 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

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_SILENCE, NONE, 0);
#undef _
}
} // NOLINT
static bool ioctl_initialized = false;

View File

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

View File

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

View File

@ -1062,8 +1062,6 @@ uptr GetMaxUserVirtualAddress() {
uptr GetPageSize() {
#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
return EXEC_PAGESIZE;
#elif SANITIZER_USE_GETAUXVAL
return getauxval(AT_PAGESZ);
#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
// Use sysctl as sysconf can trigger interceptors internally.
int pz = 0;
@ -1072,6 +1070,8 @@ uptr GetPageSize() {
int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
CHECK_EQ(rv, 0);
return (uptr)pz;
#elif SANITIZER_USE_GETAUXVAL
return getauxval(AT_PAGESZ);
#else
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
#endif
@ -1849,6 +1849,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
#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) {
// FIXME: Implement this.
}
@ -2011,6 +2017,35 @@ void CheckASLR() {
CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
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
// Do nothing
#endif

View File

@ -23,6 +23,7 @@
#include "sanitizer_flags.h"
#include "sanitizer_freebsd.h"
#include "sanitizer_getauxval.h"
#include "sanitizer_glibc_version.h"
#include "sanitizer_linux.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
@ -188,11 +189,7 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
static uptr g_tls_size;
#ifdef __i386__
# ifndef __GLIBC_PREREQ
# define CHECK_GET_TLS_STATIC_INFO_VERSION 1
# else
# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
# endif
# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27))
#else
# define CHECK_GET_TLS_STATIC_INFO_VERSION 0
#endif
@ -701,13 +698,9 @@ u32 GetNumberOfCPUs() {
#elif SANITIZER_SOLARIS
return sysconf(_SC_NPROCESSORS_ONLN);
#else
#if defined(CPU_COUNT)
cpu_set_t CPUs;
CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
return CPU_COUNT(&CPUs);
#else
return 1;
#endif
#endif
}

View File

@ -13,6 +13,7 @@
#include "sanitizer_platform.h"
#if SANITIZER_MAC
#include "sanitizer_mac.h"
#include "interception/interception.h"
// 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.
@ -36,7 +37,7 @@
extern char **environ;
#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
#include <os/trace.h>
#else
@ -64,7 +65,9 @@ extern "C" {
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <spawn.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
@ -239,27 +242,102 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
(size_t)newlen);
}
int internal_forkpty(int *aparent) {
int parent, worker;
if (openpty(&parent, &worker, nullptr, nullptr, nullptr) == -1) return -1;
int pid = internal_fork();
if (pid == -1) {
close(parent);
close(worker);
return -1;
static fd_t internal_spawn_impl(const char *argv[], pid_t *pid) {
fd_t master_fd = kInvalidFd;
fd_t slave_fd = kInvalidFd;
auto fd_closer = at_scope_exit([&] {
internal_close(master_fd);
internal_close(slave_fd);
});
// 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);
if (login_tty(worker) != 0) {
// We already forked, there's not much we can do. Let's quit.
Report("login_tty failed (errno %d)\n", errno);
internal__exit(1);
}
} else {
*aparent = parent;
close(worker);
fd_t fd = internal_spawn_impl(argv, pid);
for (; count > 0; count--) {
internal_close(low_fds[count]);
}
return pid;
return fd;
}
uptr internal_rename(const char *oldpath, const char *newpath) {
@ -676,6 +754,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
#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) {
ucontext_t *ucontext = (ucontext_t*)context;
# if defined(__aarch64__)
@ -1122,7 +1206,7 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
if (!buffer || !length || length > 256)
return false;
// arc4random never fails.
arc4random_buf(buffer, length);
REAL(arc4random_buf)(buffer, length);
return true;
}

View File

@ -13,6 +13,7 @@
#ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
#define SANITIZER_PLATFORM_INTERCEPTORS_H
#include "sanitizer_glibc_version.h"
#include "sanitizer_internal_defs.h"
#if SANITIZER_POSIX
@ -331,10 +332,9 @@
#define SANITIZER_INTERCEPT_ETHER_HOST \
(SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID)
#define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
#define SANITIZER_INTERCEPT_SHMCTL \
(SI_NETBSD || SI_OPENBSD || SI_SOLARIS || \
((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && \
SANITIZER_WORDSIZE == 64)) // NOLINT
#define SANITIZER_INTERCEPT_SHMCTL \
(((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
SI_NETBSD || SI_OPENBSD || SI_SOLARIS) // NOLINT
#define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
@ -489,7 +489,8 @@
SI_NOT_RTEMS)
#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
#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_WCSCAT SI_POSIX
#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
@ -561,11 +562,18 @@
#define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD)
#define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD
#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_GETUSERSHELL (SI_POSIX && !SI_ANDROID)
#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

View File

@ -26,12 +26,9 @@
// 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
// fine with newer headers, too. Beware that with <sys/stat.h>, struct stat
// takes the form of struct stat64 on 32-bit platforms if _FILE_OFFSET_BITS=64.
// Also, for some platforms (e.g. mips) there are additional members in the
// <sys/stat.h> struct stat:s.
// fine with newer headers, too.
#include <linux/posix_types.h>
#if defined(__x86_64__)
#if defined(__x86_64__) || defined(__mips__)
#include <sys/stat.h>
#else
#define ino_t __kernel_ino_t

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,7 @@ struct __sanitizer_ipc_perm {
#if !defined(_LP64)
int pad[4];
#endif
};
};
struct __sanitizer_shmid_ds {
__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
// limit. Verified with a compiler assert in .cpp.
const int pthread_attr_t_max_sz = 128;
union __sanitizer_pthread_attr_t {
char size[pthread_attr_t_max_sz]; // NOLINT
char size[128];
void *align;
};

View File

@ -312,6 +312,8 @@ const char *SignalContext::Describe() const {
return "SEGV";
case SIGBUS:
return "BUS";
case SIGTRAP:
return "TRAP";
}
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);
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,
uptr *oldlenp, const void *newp, uptr newlen);

View File

@ -304,11 +304,13 @@ void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
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());
fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, name);
uptr p =
MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
int reserrno;
if (internal_iserror(p, &reserrno)) {
Report("ERROR: %s failed to "
@ -320,6 +322,24 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
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) {
base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name)
: MmapNoAccess(size);

View File

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

View File

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

View File

@ -181,13 +181,14 @@ const mach_header *get_dyld_hdr() {
// Note that the segment addresses are not necessarily sorted.
template <u32 kLCSegment, typename SegmentCommand>
static bool NextSegmentLoad(MemoryMappedSegment *segment,
MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
const char *lc = layout_data.current_load_cmd_addr;
layout_data.current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
MemoryMappedSegmentData *seg_data,
MemoryMappingLayoutData *layout_data) {
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) {
const SegmentCommand* sc = (const SegmentCommand *)lc;
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();
// vmaddr is masked with 0xfffff because on macOS versions < 10.12,
// it contains an absolute address rather than an offset for dyld.
@ -198,7 +199,7 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
addr_mask = 0xfffff;
} else {
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;
}
@ -219,18 +220,18 @@ MemoryMappedSegmentData *seg_data, MemoryMappingLayoutData &layout_data) {
// Return the initial protection.
segment->protection = sc->initprot;
segment->offset = (layout_data.current_filetype ==
segment->offset = (layout_data->current_filetype ==
/*MH_EXECUTE*/ 0x2)
? sc->vmaddr
: sc->fileoff;
if (segment->filename) {
const char *src = (layout_data.current_image == kDyldImageIdx)
const char *src = (layout_data->current_image == kDyldImageIdx)
? 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);
}
segment->arch = layout_data.current_arch;
internal_memcpy(segment->uuid, layout_data.current_uuid, kModuleUUIDSize);
segment->arch = layout_data->current_arch;
internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
return true;
}
return false;
@ -331,14 +332,14 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
#ifdef MH_MAGIC_64
case MH_MAGIC_64: {
if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
segment, segment->data_, data_))
segment, segment->data_, &data_))
return true;
break;
}
#endif
case MH_MAGIC: {
if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
segment, segment->data_, data_))
segment, segment->data_, &data_))
return true;
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
// 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
// layouts. Assume GCC.
return bp_prev - 1;
// layouts. Assume LLVM.
return bp_prev;
#else
return (uhwptr*)bp;
#endif
@ -84,21 +84,14 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
IsAligned((uptr)frame, sizeof(*frame)) &&
size < max_depth) {
#ifdef __powerpc__
// PowerPC ABIs specify that the return address is saved on the
// *caller's* stack frame. Thus we must dereference the back chain
// to find the caller frame before extracting it.
// PowerPC ABIs specify that the return address is saved at offset
// 16 of the *caller's* stack frame. Thus we must dereference the
// back chain to find the caller frame before extracting it.
uhwptr *caller_frame = (uhwptr*)frame[0];
if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) ||
!IsAligned((uptr)caller_frame, sizeof(uhwptr)))
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];
#endif
#elif defined(__s390__)
uhwptr pc1 = frame[14];
#else

View File

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

View File

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

View File

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

View File

@ -76,7 +76,7 @@ class SymbolizerTool {
// SymbolizerProcess may not be used from two threads simultaneously.
class SymbolizerProcess {
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);
protected:
@ -114,7 +114,7 @@ class SymbolizerProcess {
uptr times_restarted_;
bool failed_to_start_;
bool reported_invalid_path_;
bool use_forkpty_;
bool use_posix_spawn_;
};
class LLVMSymbolizerProcess;

View File

@ -238,7 +238,8 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
// <empty line>
class LLVMSymbolizerProcess : public SymbolizerProcess {
public:
explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
explicit LLVMSymbolizerProcess(const char *path)
: SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_MAC) {}
private:
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_);
}
SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)
SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
: path_(path),
input_fd_(kInvalidFd),
output_fd_(kInvalidFd),
times_restarted_(0),
failed_to_start_(false),
reported_invalid_path_(false),
use_forkpty_(use_forkpty) {
use_posix_spawn_(use_posix_spawn) {
CHECK(path_);
CHECK_NE(path_[0], '\0');
}

View File

@ -50,14 +50,14 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
class AtosSymbolizerProcess : public SymbolizerProcess {
public:
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
// the call to GetArgV.
internal_snprintf(pid_str_, sizeof(pid_str_), "%d", parent_pid);
}
private:
virtual bool StartSymbolizerSubprocess() override {
bool StartSymbolizerSubprocess() override {
// Configure sandbox before starting atos process.
return SymbolizerProcess::StartSymbolizerSubprocess();
}

View File

@ -33,10 +33,6 @@
#include <sys/wait.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,
// 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.
@ -151,80 +147,32 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
return false;
}
int pid = -1;
const char *argv[kArgVMax];
GetArgV(path_, argv);
pid_t pid;
int infd[2];
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 (use_posix_spawn_) {
#if SANITIZER_MAC
fd_t fd = kInvalidFd;
// forkpty redirects stdout and stderr into a single stream, so we would
// 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",
fd_t fd = internal_spawn(argv, &pid);
if (fd == kInvalidFd) {
Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
errno);
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;
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);
output_fd_ = fd;
#else // SANITIZER_MAC
UNIMPLEMENTED();
#endif // SANITIZER_MAC
} else {
const char *argv[kArgVMax];
GetArgV(path_, argv);
fd_t infd[2] = {}, outfd[2] = {};
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],
/* stdout */ infd[1]);
if (pid < 0) {

View File

@ -106,8 +106,9 @@ void ReportMmapWriteExec(int prot) {
if (StackTrace::WillUseFastUnwind(fast)) {
GetThreadStackTopAndBottom(false, &top, &bottom);
stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
} else
} else {
stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
}
Printf("%s", d.Warning());
Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
@ -190,9 +191,14 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
SanitizerCommonDecorator d;
Printf("%s", d.Warning());
const char *description = sig.Describe();
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);
if (sig.is_memory_access && !sig.is_true_faulting_addr)
Report("ERROR: %s: %s on unknown address (pc %p bp %p sp %p T%d)\n",
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());
if (sig.pc < GetPageSizeCached())
Report("Hint: pc points to the zero page.\n");
@ -202,7 +208,11 @@ static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
? "WRITE"
: (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
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");
}
MaybeReportNonExecRegion(sig.pc);

View File

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

View File

@ -27,6 +27,8 @@
namespace __sanitizer {
namespace {
//---------------------------- UnwindSlow --------------------------------------
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;
} // 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
// NetBSD uses dwarf EH
#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;
}
} // 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) {
CHECK_GE(max_depth, 2);
size = 0;

View File

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

View File

@ -239,6 +239,11 @@ bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
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
// 'MmapFixedNoAccess'.
void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
@ -671,7 +676,7 @@ static int RunAtexit() {
return ret;
}
#pragma section(".CRT$XID", long, read) // NOLINT
#pragma section(".CRT$XID", long, read)
__declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
#endif
@ -940,6 +945,11 @@ bool SignalContext::IsMemoryAccess() const {
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 {
EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
// The contents of this array are documented at

View File

@ -43,6 +43,8 @@
#define STRINGIFY_(A) #A
#define STRINGIFY(A) STRINGIFY_(A)
#if !SANITIZER_GO
// ----------------- A workaround for the absence of weak symbols --------------
// 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
@ -158,5 +160,15 @@
// 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_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)
#include "sanitizer_common_interface.inc"
#pragma section(".DLLTH$A", read) // NOLINT
#pragma section(".DLLTH$Z", read) // NOLINT
#pragma section(".DLLTH$A", read)
#pragma section(".DLLTH$Z", read)
typedef void (*DllThunkCB)();
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
// 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)() =
__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();
}
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *,
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.
extern "C" {
void __sanitizer_on_print(const char *str);
void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1,
const void *s2, uptr n, int result);
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)
#include "sanitizer_common_interface.inc"
#pragma section(".WEAK$A", read) // NOLINT
#pragma section(".WEAK$Z", read) // NOLINT
#pragma section(".WEAK$A", read)
#pragma section(".WEAK$Z", read)
typedef void (*InterceptCB)();
extern "C" {
@ -77,7 +78,7 @@ static int weak_intercept_init() {
return 0;
}
#pragma section(".CRT$XIB", long, read) // NOLINT
#pragma section(".CRT$XIB", long, read)
__declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() =
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();
}
#pragma section(".CRT$XLAB", long, read) // NOLINT
#pragma section(".CRT$XLAB", long, read)
__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_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,
int error);
typedef long dispatch_once_t; // NOLINT
typedef long dispatch_once_t;
typedef __sanitizer::u64 dispatch_time_t;
typedef int dispatch_fd_t; // NOLINT
typedef unsigned long dispatch_io_type_t; // NOLINT
typedef unsigned long dispatch_io_close_flags_t; // NOLINT
typedef int dispatch_fd_t;
typedef unsigned long dispatch_io_type_t;
typedef unsigned long dispatch_io_close_flags_t;
extern "C" {
void *dispatch_get_context(dispatch_object_t object);
@ -57,10 +57,10 @@ extern const dispatch_block_t _dispatch_data_destructor_munmap;
#endif
// Data types used in dispatch APIs
typedef unsigned long size_t; // NOLINT
typedef unsigned long uintptr_t; // NOLINT
typedef unsigned long size_t;
typedef unsigned long uintptr_t;
typedef __sanitizer::s64 off_t;
typedef __sanitizer::u16 mode_t;
typedef long long_t; // NOLINT
typedef long long_t;
#endif // TSAN_DISPATCH_DEFS_H

View File

@ -25,7 +25,7 @@ static TagData registered_tags[kExternalTagMax] = {
{},
{"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) {
// Invalid/corrupted tag? Better return NULL and let the caller deal with it.
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
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.

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.
// See https://llvm.org/LICENSE.txt for license information.
@ -16,6 +16,7 @@
#include "tsan_interceptors.h"
#include "tsan_rtl.h"
#include "BlocksRuntime/Block.h"
#include "tsan_dispatch_defs.h"
namespace __tsan {

View File

@ -23,13 +23,14 @@
#include <errno.h>
#include <libkern/OSAtomic.h>
#include <objc/objc-sync.h>
#include <os/lock.h>
#include <sys/ucontext.h>
#if defined(__has_include) && __has_include(<xpc/xpc.h>)
#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" {
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);
}
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>)
TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,

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