diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-02-06 13:39:20 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-02-06 13:39:20 +0000 |
commit | f8ca070d3aeee9332d1843f5aa44945374b51b8e (patch) | |
tree | 4efb8604227ede935238eb1c67b626da1265d459 /contrib/compiler-rt/lib/asan | |
parent | 752d00608cb24d3c902d6890efe6964247c2532c (diff) | |
parent | 807551b099338b7cc4f66ee567aae20a529dd27e (diff) | |
download | src-f8ca070d3aeee9332d1843f5aa44945374b51b8e.tar.gz src-f8ca070d3aeee9332d1843f5aa44945374b51b8e.zip |
Merge compiler-rt release_38 branch r258968.
Note that there is still a problem on amd64, causing SIGBUS in the early
startup of Address Sanitizer. This is being investigated.
Notes
Notes:
svn path=/projects/clang380-import/; revision=295349
Diffstat (limited to 'contrib/compiler-rt/lib/asan')
52 files changed, 540 insertions, 5979 deletions
diff --git a/contrib/compiler-rt/lib/asan/README.txt b/contrib/compiler-rt/lib/asan/README.txt index 8cc9bb17b59d..bb6ff42c5cde 100644 --- a/contrib/compiler-rt/lib/asan/README.txt +++ b/contrib/compiler-rt/lib/asan/README.txt @@ -23,4 +23,4 @@ from the root of your CMake build tree: make check-asan For more instructions see: -http://code.google.com/p/address-sanitizer/wiki/HowToBuild +https://github.com/google/sanitizers/wiki/AddressSanitizerHowToBuild diff --git a/contrib/compiler-rt/lib/asan/asan_activation.cc b/contrib/compiler-rt/lib/asan/asan_activation.cc index 3bc01984898d..9df3b977ea1b 100644 --- a/contrib/compiler-rt/lib/asan/asan_activation.cc +++ b/contrib/compiler-rt/lib/asan/asan_activation.cc @@ -38,7 +38,7 @@ static struct AsanDeactivatedFlags { #undef ASAN_ACTIVATION_FLAG #undef COMMON_ACTIVATION_FLAG - RegisterIncludeFlag(parser, cf); + RegisterIncludeFlags(parser, cf); } void OverrideFromActivationFlags() { @@ -61,11 +61,6 @@ static struct AsanDeactivatedFlags { parser.ParseString(env); } - // Override from getprop asan.options. - char buf[100]; - GetExtraActivationFlags(buf, sizeof(buf)); - parser.ParseString(buf); - SetVerbosity(cf.verbosity); if (Verbosity()) ReportUnrecognizedFlags(); @@ -124,6 +119,8 @@ void AsanActivate() { if (!asan_is_deactivated) return; VReport(1, "Activating ASan\n"); + UpdateProcessName(); + asan_deactivated_flags.OverrideFromActivationFlags(); SetCanPoisonMemory(asan_deactivated_flags.poison_heap); diff --git a/contrib/compiler-rt/lib/asan/asan_allocator.cc b/contrib/compiler-rt/lib/asan/asan_allocator.cc index 2df9a510bd9a..56f184a36651 100644 --- a/contrib/compiler-rt/lib/asan/asan_allocator.cc +++ b/contrib/compiler-rt/lib/asan/asan_allocator.cc @@ -14,8 +14,8 @@ // with ThreadSanitizer and MemorySanitizer. // //===----------------------------------------------------------------------===// -#include "asan_allocator.h" +#include "asan_allocator.h" #include "asan_mapping.h" #include "asan_poisoning.h" #include "asan_report.h" @@ -541,7 +541,7 @@ struct Allocator { u8 chunk_state = m->chunk_state; if (chunk_state != CHUNK_ALLOCATED) ReportInvalidFree(old_ptr, chunk_state, stack); - CHECK_NE(REAL(memcpy), (void*)0); + CHECK_NE(REAL(memcpy), nullptr); uptr memcpy_size = Min(new_size, m->UsedSize()); // If realloc() races with free(), we may start copying freed memory. // However, we will report racy double-free later anyway. @@ -579,7 +579,7 @@ struct Allocator { // Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg). AsanChunk *GetAsanChunk(void *alloc_beg) { - if (!alloc_beg) return 0; + if (!alloc_beg) return nullptr; if (!allocator.FromPrimary(alloc_beg)) { uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(alloc_beg)); AsanChunk *m = reinterpret_cast<AsanChunk *>(meta[1]); @@ -619,7 +619,7 @@ struct Allocator { // The address is in the chunk's left redzone, so maybe it is actually // a right buffer overflow from the other chunk to the left. // Search a bit to the left to see if there is another chunk. - AsanChunk *m2 = 0; + AsanChunk *m2 = nullptr; for (uptr l = 1; l < GetPageSizeCached(); l++) { m2 = GetAsanChunkByAddr(addr - l); if (m2 == m1) continue; // Still the same chunk. @@ -653,7 +653,7 @@ static AsanAllocator &get_allocator() { } bool AsanChunkView::IsValid() { - return chunk_ != 0 && chunk_->chunk_state != CHUNK_AVAILABLE; + return chunk_ && chunk_->chunk_state != CHUNK_AVAILABLE; } uptr AsanChunkView::Beg() { return chunk_->Beg(); } uptr AsanChunkView::End() { return Beg() + UsedSize(); } @@ -723,11 +723,11 @@ void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) { } void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) { - if (p == 0) + if (!p) return instance.Allocate(size, 8, stack, FROM_MALLOC, true); if (size == 0) { instance.Deallocate(p, 0, stack, FROM_MALLOC); - return 0; + return nullptr; } return instance.Reallocate(p, size, stack); } @@ -755,7 +755,7 @@ int asan_posix_memalign(void **memptr, uptr alignment, uptr size, } uptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp) { - if (ptr == 0) return 0; + if (!ptr) return 0; uptr usable_size = instance.AllocationSize(reinterpret_cast<uptr>(ptr)); if (flags()->check_malloc_usable_size && (usable_size == 0)) { GET_STACK_TRACE_FATAL(pc, bp); @@ -780,7 +780,7 @@ void AsanSoftRssLimitExceededCallback(bool exceeded) { instance.allocator.SetRssLimitIsExceeded(exceeded); } -} // namespace __asan +} // namespace __asan // --- Implementation of LSan-specific functions --- {{{1 namespace __lsan { @@ -881,7 +881,7 @@ int __sanitizer_get_ownership(const void *p) { } uptr __sanitizer_get_allocated_size(const void *p) { - if (p == 0) return 0; + if (!p) return 0; uptr ptr = reinterpret_cast<uptr>(p); uptr allocated_size = instance.AllocationSize(ptr); // Die if p is not malloced or if it is already freed. @@ -904,5 +904,5 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_free_hook(void *ptr) { (void)ptr; } -} // extern "C" +} // extern "C" #endif diff --git a/contrib/compiler-rt/lib/asan/asan_allocator.h b/contrib/compiler-rt/lib/asan/asan_allocator.h index 5ccd00c97bab..e3d53330cd2f 100644 --- a/contrib/compiler-rt/lib/asan/asan_allocator.h +++ b/contrib/compiler-rt/lib/asan/asan_allocator.h @@ -114,6 +114,11 @@ struct AsanMapUnmapCallback { # if defined(__powerpc64__) const uptr kAllocatorSpace = 0xa0000000000ULL; const uptr kAllocatorSize = 0x20000000000ULL; // 2T. +# elif defined(__aarch64__) +// AArch64/SANITIZIER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA +// so no need to different values for different VMA. +const uptr kAllocatorSpace = 0x10000000000ULL; +const uptr kAllocatorSize = 0x10000000000ULL; // 3T. # else const uptr kAllocatorSpace = 0x600000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. diff --git a/contrib/compiler-rt/lib/asan/asan_debugging.cc b/contrib/compiler-rt/lib/asan/asan_debugging.cc index 6fc5b690de99..7c3a8a73bd4e 100644 --- a/contrib/compiler-rt/lib/asan/asan_debugging.cc +++ b/contrib/compiler-rt/lib/asan/asan_debugging.cc @@ -108,14 +108,14 @@ static uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id, return 0; } -} // namespace __asan +} // namespace __asan using namespace __asan; SANITIZER_INTERFACE_ATTRIBUTE const char *__asan_locate_address(uptr addr, char *name, uptr name_size, uptr *region_address, uptr *region_size) { - AddressDescription descr = { name, name_size, 0, 0, 0 }; + AddressDescription descr = { name, name_size, 0, 0, nullptr }; AsanLocateAddress(addr, &descr); if (region_address) *region_address = descr.region_address; if (region_size) *region_size = descr.region_size; diff --git a/contrib/compiler-rt/lib/asan/asan_fake_stack.cc b/contrib/compiler-rt/lib/asan/asan_fake_stack.cc index d20641155b88..91fdf0aa1dca 100644 --- a/contrib/compiler-rt/lib/asan/asan_fake_stack.cc +++ b/contrib/compiler-rt/lib/asan/asan_fake_stack.cc @@ -11,6 +11,7 @@ // // FakeStack is used to detect use-after-return bugs. //===----------------------------------------------------------------------===// + #include "asan_allocator.h" #include "asan_poisoning.h" #include "asan_thread.h" @@ -32,7 +33,8 @@ ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { if (class_id <= 6) { for (uptr i = 0; i < (1U << class_id); i++) { shadow[i] = magic; - SanitizerBreakOptimization(0); // Make sure this does not become memset. + // Make sure this does not become memset. + SanitizerBreakOptimization(nullptr); } } else { // The size class is too big, it's cheaper to poison only size bytes. @@ -80,7 +82,9 @@ void FakeStack::PoisonAll(u8 magic) { magic); } +#if !defined(_MSC_VER) || defined(__clang__) ALWAYS_INLINE USED +#endif FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id, uptr real_stack) { CHECK_LT(class_id, kNumberOfSizeClasses); @@ -106,7 +110,7 @@ FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id, *SavedFlagPtr(reinterpret_cast<uptr>(res), class_id) = &flags[pos]; return res; } - return 0; // We are out of fake stack. + return nullptr; // We are out of fake stack. } uptr FakeStack::AddrIsInFakeStack(uptr ptr, uptr *frame_beg, uptr *frame_end) { @@ -183,7 +187,7 @@ void SetTLSFakeStack(FakeStack *fs) { } static FakeStack *GetFakeStack() { AsanThread *t = GetCurrentThread(); - if (!t) return 0; + if (!t) return nullptr; return t->fake_stack(); } @@ -191,7 +195,7 @@ static FakeStack *GetFakeStackFast() { if (FakeStack *fs = GetTLSFakeStack()) return fs; if (!__asan_option_detect_stack_use_after_return) - return 0; + return nullptr; return GetFakeStack(); } @@ -212,7 +216,7 @@ ALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size) { SetShadow(ptr, size, class_id, kMagic8); } -} // namespace __asan +} // namespace __asan // ---------------------- Interface ---------------- {{{1 using namespace __asan; @@ -245,13 +249,13 @@ SANITIZER_INTERFACE_ATTRIBUTE void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg, void **end) { FakeStack *fs = reinterpret_cast<FakeStack*>(fake_stack); - if (!fs) return 0; + if (!fs) return nullptr; uptr frame_beg, frame_end; FakeFrame *frame = reinterpret_cast<FakeFrame *>(fs->AddrIsInFakeStack( reinterpret_cast<uptr>(addr), &frame_beg, &frame_end)); - if (!frame) return 0; + if (!frame) return nullptr; if (frame->magic != kCurrentStackFrameMagic) - return 0; + return nullptr; if (beg) *beg = reinterpret_cast<void*>(frame_beg); if (end) *end = reinterpret_cast<void*>(frame_end); return reinterpret_cast<void*>(frame->real_stack); @@ -276,4 +280,4 @@ void __asan_allocas_unpoison(uptr top, uptr bottom) { REAL(memset)(reinterpret_cast<void*>(MemToShadow(top)), 0, (bottom - top) / SHADOW_GRANULARITY); } -} // extern "C" +} // extern "C" diff --git a/contrib/compiler-rt/lib/asan/asan_flags.cc b/contrib/compiler-rt/lib/asan/asan_flags.cc index e8ea549b62e3..363ee67e77c6 100644 --- a/contrib/compiler-rt/lib/asan/asan_flags.cc +++ b/contrib/compiler-rt/lib/asan/asan_flags.cc @@ -65,6 +65,7 @@ void InitializeFlags() { cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); cf.malloc_context_size = kDefaultMallocContextSize; cf.intercept_tls_get_addr = true; + cf.exitcode = 1; OverrideCommonFlags(cf); } Flags *f = flags(); @@ -115,14 +116,6 @@ void InitializeFlags() { ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS")); #endif - // Let activation flags override current settings. On Android they come - // from a system property. On other platforms this is no-op. - if (!flags()->start_deactivated) { - char buf[100]; - GetExtraActivationFlags(buf, sizeof(buf)); - asan_parser.ParseString(buf); - } - SetVerbosity(common_flags()->verbosity); // TODO(eugenis): dump all flags at verbosity>=2? diff --git a/contrib/compiler-rt/lib/asan/asan_flags.inc b/contrib/compiler-rt/lib/asan/asan_flags.inc index 53a8a4039e7e..5e69242fb8e9 100644 --- a/contrib/compiler-rt/lib/asan/asan_flags.inc +++ b/contrib/compiler-rt/lib/asan/asan_flags.inc @@ -44,9 +44,6 @@ ASAN_FLAG( "to find more errors.") ASAN_FLAG(bool, replace_intrin, true, "If set, uses custom wrappers for memset/memcpy/memmove intinsics.") -ASAN_FLAG(bool, mac_ignore_invalid_free, false, - "Ignore invalid free() calls to work around some bugs. Used on OS X " - "only.") ASAN_FLAG(bool, detect_stack_use_after_return, false, "Enables stack-use-after-return checking at run-time.") ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway. @@ -62,8 +59,6 @@ ASAN_FLAG( "bytes that will be filled with malloc_fill_byte on malloc.") ASAN_FLAG(int, malloc_fill_byte, 0xbe, "Value used to fill the newly allocated memory.") -ASAN_FLAG(int, exitcode, ASAN_DEFAULT_FAILURE_EXITCODE, - "Override the program exit status if the tool found an error.") ASAN_FLAG(bool, allow_user_poisoning, true, "If set, user may manually mark memory regions as poisoned or " "unpoisoned.") @@ -77,10 +72,7 @@ ASAN_FLAG(bool, check_malloc_usable_size, true, "295.*.") ASAN_FLAG(bool, unmap_shadow_on_exit, false, "If set, explicitly unmaps the (huge) shadow at exit.") -ASAN_FLAG( - bool, abort_on_error, false, - "If set, the tool calls abort() instead of _exit() after printing the " - "error report.") +ASAN_FLAG(bool, protect_shadow_gap, true, "If set, mprotect the shadow gap") ASAN_FLAG(bool, print_stats, false, "Print various statistics after printing an error message or if " "atexit=1.") @@ -104,8 +96,8 @@ ASAN_FLAG(bool, poison_array_cookie, true, "Poison (or not) the array cookie after operator new[].") // Turn off alloc/dealloc mismatch checker on Mac and Windows for now. -// https://code.google.com/p/address-sanitizer/issues/detail?id=131 -// https://code.google.com/p/address-sanitizer/issues/detail?id=309 +// https://github.com/google/sanitizers/issues/131 +// https://github.com/google/sanitizers/issues/309 // TODO(glider,timurrrr): Fix known issues and enable this back. ASAN_FLAG(bool, alloc_dealloc_mismatch, (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0), @@ -113,9 +105,6 @@ ASAN_FLAG(bool, alloc_dealloc_mismatch, ASAN_FLAG(bool, new_delete_type_mismatch, true, "Report errors on mismatch betwen size of new and delete.") -ASAN_FLAG(bool, strict_memcmp, true, - "If true, assume that memcmp(p1, p2, n) always reads n bytes before " - "comparing p1 and p2.") ASAN_FLAG( bool, strict_init_order, false, "If true, assume that dynamic initializers can never access globals from " @@ -134,8 +123,8 @@ ASAN_FLAG( "The bigger the value the harder we try.") ASAN_FLAG( bool, detect_container_overflow, true, - "If true, honor the container overflow annotations. " - "See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow") + "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 " @@ -143,3 +132,6 @@ ASAN_FLAG(int, detect_odr_violation, 2, ASAN_FLAG(bool, dump_instruction_bytes, false, "If true, dump 16 bytes starting at the instruction that caused SEGV") ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.") +ASAN_FLAG(bool, halt_on_error, true, + "Crash the program after printing the first error report " + "(WARNING: USE AT YOUR OWN RISK!)") diff --git a/contrib/compiler-rt/lib/asan/asan_globals.cc b/contrib/compiler-rt/lib/asan/asan_globals.cc index c34b1d3cedf2..eb9f1bfefec2 100644 --- a/contrib/compiler-rt/lib/asan/asan_globals.cc +++ b/contrib/compiler-rt/lib/asan/asan_globals.cc @@ -11,6 +11,7 @@ // // Handle globals. //===----------------------------------------------------------------------===// + #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_mapping.h" @@ -167,7 +168,7 @@ static void RegisterGlobal(const Global *g) { l->next = list_of_all_globals; list_of_all_globals = l; if (g->has_dynamic_init) { - if (dynamic_init_globals == 0) { + if (!dynamic_init_globals) { dynamic_init_globals = new(allocator_for_globals) VectorOfGlobals(kDynamicInitGlobalsInitialCapacity); } @@ -206,7 +207,7 @@ void StopInitOrderChecking() { } } -} // namespace __asan +} // namespace __asan // ---------------------- Interface ---------------- {{{1 using namespace __asan; // NOLINT diff --git a/contrib/compiler-rt/lib/asan/asan_init_version.h b/contrib/compiler-rt/lib/asan/asan_init_version.h index 6cf57c4aa2a8..bc8a622f5bb1 100644 --- a/contrib/compiler-rt/lib/asan/asan_init_version.h +++ b/contrib/compiler-rt/lib/asan/asan_init_version.h @@ -27,8 +27,8 @@ extern "C" { // v3=>v4: added '__asan_global_source_location' to __asan_global. // v4=>v5: changed the semantics and format of __asan_stack_malloc_ and // __asan_stack_free_ functions. - #define __asan_init __asan_init_v5 - #define __asan_init_name "__asan_init_v5" + // v5=>v6: changed the name of the version check symbol + #define __asan_version_mismatch_check __asan_version_mismatch_check_v6 } #endif // ASAN_INIT_VERSION_H diff --git a/contrib/compiler-rt/lib/asan/asan_interceptors.cc b/contrib/compiler-rt/lib/asan/asan_interceptors.cc index d8b48d391ab8..d9a0c71a002d 100644 --- a/contrib/compiler-rt/lib/asan/asan_interceptors.cc +++ b/contrib/compiler-rt/lib/asan/asan_interceptors.cc @@ -11,8 +11,8 @@ // // Intercept various libc functions. //===----------------------------------------------------------------------===// -#include "asan_interceptors.h" +#include "asan_interceptors.h" #include "asan_allocator.h" #include "asan_internal.h" #include "asan_mapping.h" @@ -27,6 +27,12 @@ #include "sanitizer_common/sanitizer_posix.h" #endif +#if defined(__i386) && SANITIZER_LINUX +#define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1" +#elif defined(__mips__) && SANITIZER_LINUX +#define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2" +#endif + namespace __asan { // Return true if we can quickly decide that the region is unpoisoned. @@ -69,7 +75,7 @@ struct AsanInterceptorContext { } \ if (!suppressed) { \ GET_CURRENT_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0); \ + ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\ } \ } \ } while (0) @@ -105,7 +111,7 @@ static inline bool RangesOverlap(const char *offset1, uptr length1, static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { #if ASAN_INTERCEPT_STRNLEN - if (REAL(strnlen) != 0) { + if (REAL(strnlen)) { return REAL(strnlen)(s, maxlen); } #endif @@ -123,7 +129,7 @@ int OnExit() { return 0; } -} // namespace __asan +} // namespace __asan // ---------------------- Wrappers ---------------- {{{1 using namespace __asan; // NOLINT @@ -172,7 +178,7 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) } while (false) #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) // Strict init-order checking is dlopen-hostile: -// https://code.google.com/p/address-sanitizer/issues/detail?id=178 +// https://github.com/google/sanitizers/issues/178 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ if (flags()->strict_init_order) { \ StopInitOrderChecking(); \ @@ -216,7 +222,7 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg); AsanThread *t = nullptr; while ((t = reinterpret_cast<AsanThread *>( - atomic_load(¶m->t, memory_order_acquire))) == 0) + atomic_load(¶m->t, memory_order_acquire))) == nullptr) internal_sched_yield(); SetCurrentThread(t); return t->ThreadStart(GetTid(), ¶m->is_registered); @@ -231,7 +237,7 @@ INTERCEPTOR(int, pthread_create, void *thread, StopInitOrderChecking(); GET_STACK_TRACE_THREAD; int detached = 0; - if (attr != 0) + if (attr) REAL(pthread_attr_getdetachstate)(attr, &detached); ThreadStartParam param; atomic_store(¶m.t, 0, memory_order_relaxed); @@ -270,14 +276,14 @@ INTERCEPTOR(void*, bsd_signal, int signum, void *handler) { } return 0; } -#else +#endif + INTERCEPTOR(void*, signal, int signum, void *handler) { if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) { return REAL(signal)(signum, handler); } - return 0; + return nullptr; } -#endif INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, struct sigaction *oldact) { @@ -292,7 +298,7 @@ int real_sigaction(int signum, const void *act, void *oldact) { return REAL(sigaction)(signum, (const struct sigaction *)act, (struct sigaction *)oldact); } -} // namespace __sanitizer +} // namespace __sanitizer #elif SANITIZER_POSIX // We need to have defined REAL(sigaction) on posix systems. @@ -363,40 +369,6 @@ INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { } #endif -static inline int CharCmp(unsigned char c1, unsigned char c2) { - return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; -} - -INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { - void *ctx; - ASAN_INTERCEPTOR_ENTER(ctx, memcmp); - if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size); - ENSURE_ASAN_INITED(); - if (flags()->replace_intrin) { - if (flags()->strict_memcmp) { - // Check the entire regions even if the first bytes of the buffers are - // different. - ASAN_READ_RANGE(ctx, a1, size); - ASAN_READ_RANGE(ctx, a2, size); - // Fallthrough to REAL(memcmp) below. - } else { - unsigned char c1 = 0, c2 = 0; - const unsigned char *s1 = (const unsigned char*)a1; - const unsigned char *s2 = (const unsigned char*)a2; - uptr i; - for (i = 0; i < size; i++) { - c1 = s1[i]; - c2 = s2[i]; - if (c1 != c2) break; - } - ASAN_READ_RANGE(ctx, s1, Min(i + 1, size)); - ASAN_READ_RANGE(ctx, s2, Min(i + 1, size)); - return CharCmp(c1, c2); - } - } - return REAL(memcmp(a1, a2, size)); -} - // memcpy is called during __asan_init() from the internals of printf(...). // We do not treat memcpy with to==from as a bug. // See http://llvm.org/bugs/show_bug.cgi?id=11763. @@ -743,7 +715,7 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, #endif ENSURE_ASAN_INITED(); int res = REAL(__cxa_atexit)(func, arg, dso_handle); - REAL(__cxa_atexit)(AtCxaAtexit, 0, 0); + REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); return res; } #endif // ASAN_INTERCEPT___CXA_ATEXIT @@ -767,7 +739,6 @@ void InitializeAsanInterceptors() { InitializeCommonInterceptors(); // Intercept mem* functions. - ASAN_INTERCEPT_FUNC(memcmp); ASAN_INTERCEPT_FUNC(memmove); ASAN_INTERCEPT_FUNC(memset); if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { @@ -806,9 +777,8 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(sigaction); #if SANITIZER_ANDROID ASAN_INTERCEPT_FUNC(bsd_signal); -#else - ASAN_INTERCEPT_FUNC(signal); #endif + ASAN_INTERCEPT_FUNC(signal); #endif #if ASAN_INTERCEPT_SWAPCONTEXT ASAN_INTERCEPT_FUNC(swapcontext); @@ -827,7 +797,11 @@ void InitializeAsanInterceptors() { // Intercept threading-related functions #if ASAN_INTERCEPT_PTHREAD_CREATE +#if defined(ASAN_PTHREAD_CREATE_VERSION) + ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION); +#else ASAN_INTERCEPT_FUNC(pthread_create); +#endif ASAN_INTERCEPT_FUNC(pthread_join); #endif @@ -845,4 +819,4 @@ void InitializeAsanInterceptors() { VReport(1, "AddressSanitizer: libc interceptors initialized\n"); } -} // namespace __asan +} // namespace __asan diff --git a/contrib/compiler-rt/lib/asan/asan_interceptors.h b/contrib/compiler-rt/lib/asan/asan_interceptors.h index 488ada78ab8b..279c5f38451f 100644 --- a/contrib/compiler-rt/lib/asan/asan_interceptors.h +++ b/contrib/compiler-rt/lib/asan/asan_interceptors.h @@ -98,6 +98,12 @@ DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act, if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \ VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \ } while (0) +#define ASAN_INTERCEPT_FUNC_VER(name, ver) \ + do { \ + if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \ + VReport( \ + 1, "AddressSanitizer: failed to intercept '" #name "@@" #ver "'\n"); \ + } while (0) #else // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. #define ASAN_INTERCEPT_FUNC(name) diff --git a/contrib/compiler-rt/lib/asan/asan_interface_internal.h b/contrib/compiler-rt/lib/asan/asan_interface_internal.h index ad8ebcd91ad9..9efddcbd42b2 100644 --- a/contrib/compiler-rt/lib/asan/asan_interface_internal.h +++ b/contrib/compiler-rt/lib/asan/asan_interface_internal.h @@ -27,10 +27,14 @@ using __sanitizer::uptr; extern "C" { // This function should be called at the very beginning of the process, // before any instrumented code is executed and before any call to malloc. - // Please note that __asan_init is a macro that is replaced with - // __asan_init_vXXX at compile-time. SANITIZER_INTERFACE_ATTRIBUTE void __asan_init(); + // This function exists purely to get a linker/loader error when using + // incompatible versions of instrumentation and runtime library. Please note + // that __asan_version_mismatch_check is a macro that is replaced with + // __asan_version_mismatch_check_vXXX at compile-time. + SANITIZER_INTERFACE_ATTRIBUTE void __asan_version_mismatch_check(); + // This structure is used to describe the source location of a place where // global was defined. struct __asan_global_source_location { @@ -131,8 +135,6 @@ extern "C" { uptr addr, int is_write, uptr access_size, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE - int __asan_set_error_exit_code(int exit_code); - SANITIZER_INTERFACE_ATTRIBUTE void __asan_set_death_callback(void (*callback)(void)); SANITIZER_INTERFACE_ATTRIBUTE void __asan_set_error_report_callback(void (*callback)(const char*)); @@ -165,6 +167,19 @@ extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size); SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uptr p); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr p, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uptr p, uptr size); + SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load1(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load2(uptr p, u32 exp); SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load4(uptr p, u32 exp); diff --git a/contrib/compiler-rt/lib/asan/asan_internal.h b/contrib/compiler-rt/lib/asan/asan_internal.h index 107e16ee31b9..0ef0d0eb5263 100644 --- a/contrib/compiler-rt/lib/asan/asan_internal.h +++ b/contrib/compiler-rt/lib/asan/asan_internal.h @@ -21,8 +21,6 @@ #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_libc.h" -#define ASAN_DEFAULT_FAILURE_EXITCODE 1 - #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # error "The AddressSanitizer run-time should not be" " instrumented by AddressSanitizer" @@ -75,12 +73,9 @@ void *AsanDoesNotSupportStaticLinkage(); void AsanCheckDynamicRTPrereqs(); void AsanCheckIncompatibleRT(); -void AsanOnSIGSEGV(int, void *siginfo, void *context); +void AsanOnDeadlySignal(int, void *siginfo, void *context); -void DisableReexec(); -void MaybeReexec(); void ReadContextStack(void *context, uptr *stack, uptr *ssize); -void AsanPlatformThreadInit(); void StopInitOrderChecking(); // Wrapper for TLS/TSD. diff --git a/contrib/compiler-rt/lib/asan/asan_linux.cc b/contrib/compiler-rt/lib/asan/asan_linux.cc index 9580fc7c06d4..e26b400562df 100644 --- a/contrib/compiler-rt/lib/asan/asan_linux.cc +++ b/contrib/compiler-rt/lib/asan/asan_linux.cc @@ -70,14 +70,6 @@ namespace __asan { void InitializePlatformInterceptors() {} -void DisableReexec() { - // No need to re-exec on Linux. -} - -void MaybeReexec() { - // No need to re-exec on Linux. -} - void *AsanDoesNotSupportStaticLinkage() { // This will fail to link with -static. return &_DYNAMIC; // defined in link.h @@ -117,7 +109,7 @@ void AsanCheckDynamicRTPrereqs() { return; // Ensure that dynamic RT is the first DSO in the list - const char *first_dso_name = 0; + const char *first_dso_name = nullptr; dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name); if (first_dso_name && !IsDynamicRTName(first_dso_name)) { Report("ASan runtime does not come first in initial library list; " @@ -142,7 +134,8 @@ void AsanCheckIncompatibleRT() { // system libraries, causing crashes later in ASan initialization. MemoryMappingLayout proc_maps(/*cache_enabled*/true); char filename[128]; - while (proc_maps.Next(0, 0, 0, filename, sizeof(filename), 0)) { + while (proc_maps.Next(nullptr, nullptr, nullptr, filename, + sizeof(filename), nullptr)) { if (IsDynamicRTName(filename)) { Report("Your application is linked against " "incompatible ASan runtimes.\n"); @@ -155,11 +148,7 @@ void AsanCheckIncompatibleRT() { } } } -#endif // SANITIZER_ANDROID - -void AsanPlatformThreadInit() { - // Nothing here for now. -} +#endif // SANITIZER_ANDROID #if !SANITIZER_ANDROID void ReadContextStack(void *context, uptr *stack, uptr *ssize) { @@ -177,6 +166,6 @@ void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); } -} // namespace __asan +} // namespace __asan -#endif // SANITIZER_FREEBSD || SANITIZER_LINUX +#endif // SANITIZER_FREEBSD || SANITIZER_LINUX diff --git a/contrib/compiler-rt/lib/asan/asan_mac.cc b/contrib/compiler-rt/lib/asan/asan_mac.cc index 3e028378df28..f00d98f8e5e6 100644 --- a/contrib/compiler-rt/lib/asan/asan_mac.cc +++ b/contrib/compiler-rt/lib/asan/asan_mac.cc @@ -24,26 +24,17 @@ #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_mac.h" -#if !SANITIZER_IOS -#include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron -#else -extern "C" { - extern char ***_NSGetArgv(void); -} -#endif - -#include <dlfcn.h> // for dladdr() +#include <fcntl.h> +#include <libkern/OSAtomic.h> #include <mach-o/dyld.h> #include <mach-o/loader.h> +#include <pthread.h> +#include <stdlib.h> // for free() #include <sys/mman.h> #include <sys/resource.h> #include <sys/sysctl.h> #include <sys/ucontext.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdlib.h> // for free() #include <unistd.h> -#include <libkern/OSAtomic.h> namespace __asan { @@ -52,187 +43,12 @@ void InitializePlatformInterceptors() {} bool PlatformHasDifferentMemcpyAndMemmove() { // On OS X 10.7 memcpy() and memmove() are both resolved // into memmove$VARIANT$sse42. - // See also http://code.google.com/p/address-sanitizer/issues/detail?id=34. + // See also https://github.com/google/sanitizers/issues/34. // TODO(glider): need to check dynamically that memcpy() and memmove() are // actually the same function. return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD; } -extern "C" -void __asan_init(); - -static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; -LowLevelAllocator allocator_for_env; - -// Change the value of the env var |name|, leaking the original value. -// If |name_value| is NULL, the variable is deleted from the environment, -// otherwise the corresponding "NAME=value" string is replaced with -// |name_value|. -void LeakyResetEnv(const char *name, const char *name_value) { - char **env = GetEnviron(); - uptr name_len = internal_strlen(name); - while (*env != 0) { - uptr len = internal_strlen(*env); - if (len > name_len) { - const char *p = *env; - if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { - // Match. - if (name_value) { - // Replace the old value with the new one. - *env = const_cast<char*>(name_value); - } else { - // Shift the subsequent pointers back. - char **del = env; - do { - del[0] = del[1]; - } while (*del++); - } - } - } - env++; - } -} - -static bool reexec_disabled = false; - -void DisableReexec() { - reexec_disabled = true; -} - -bool DyldNeedsEnvVariable() { -// If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if -// DYLD_INSERT_LIBRARIES is not set. - -#if SANITIZER_IOSSIM - // GetMacosVersion will not work for the simulator, whose kernel version - // is tied to the host. Use a weak linking hack for the simulator. - // This API was introduced in the same version of the OS as the dyld - // optimization. - - // Check for presence of a symbol that is available on OS X 10.11+, iOS 9.0+. - return (dlsym(RTLD_NEXT, "mach_memory_info") == nullptr); -#else - return (GetMacosVersion() <= MACOS_VERSION_YOSEMITE); -#endif -} - -void MaybeReexec() { - if (reexec_disabled) return; - - // Make sure the dynamic ASan runtime library is preloaded so that the - // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec - // ourselves. - Dl_info info; - CHECK(dladdr((void*)((uptr)__asan_init), &info)); - char *dyld_insert_libraries = - const_cast<char*>(GetEnv(kDyldInsertLibraries)); - uptr old_env_len = dyld_insert_libraries ? - internal_strlen(dyld_insert_libraries) : 0; - uptr fname_len = internal_strlen(info.dli_fname); - const char *dylib_name = StripModuleName(info.dli_fname); - uptr dylib_name_len = internal_strlen(dylib_name); - - bool lib_is_in_env = - dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, dylib_name); - if (DyldNeedsEnvVariable() && !lib_is_in_env) { - // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime - // library. - char program_name[1024]; - uint32_t buf_size = sizeof(program_name); - _NSGetExecutablePath(program_name, &buf_size); - char *new_env = const_cast<char*>(info.dli_fname); - if (dyld_insert_libraries) { - // Append the runtime dylib name to the existing value of - // DYLD_INSERT_LIBRARIES. - new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); - internal_strncpy(new_env, dyld_insert_libraries, old_env_len); - new_env[old_env_len] = ':'; - // Copy fname_len and add a trailing zero. - internal_strncpy(new_env + old_env_len + 1, info.dli_fname, - fname_len + 1); - // Ok to use setenv() since the wrappers don't depend on the value of - // asan_inited. - setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); - } else { - // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. - setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); - } - VReport(1, "exec()-ing the program with\n"); - VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env); - VReport(1, "to enable ASan wrappers.\n"); - execv(program_name, *_NSGetArgv()); - - // We get here only if execv() failed. - Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, " - "which is required for ASan to work. ASan tried to set the " - "environment variable and re-execute itself, but execv() failed, " - "possibly because of sandbox restrictions. Make sure to launch the " - "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env); - CHECK("execv failed" && 0); - } - - if (!lib_is_in_env) - return; - - // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove - // the dylib from the environment variable, because interceptors are installed - // and we don't want our children to inherit the variable. - - uptr env_name_len = internal_strlen(kDyldInsertLibraries); - // Allocate memory to hold the previous env var name, its value, the '=' - // sign and the '\0' char. - char *new_env = (char*)allocator_for_env.Allocate( - old_env_len + 2 + env_name_len); - CHECK(new_env); - internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); - internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); - new_env[env_name_len] = '='; - char *new_env_pos = new_env + env_name_len + 1; - - // Iterate over colon-separated pieces of |dyld_insert_libraries|. - char *piece_start = dyld_insert_libraries; - char *piece_end = NULL; - char *old_env_end = dyld_insert_libraries + old_env_len; - do { - if (piece_start[0] == ':') piece_start++; - piece_end = REAL(strchr)(piece_start, ':'); - if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; - if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; - uptr piece_len = piece_end - piece_start; - - char *filename_start = - (char *)internal_memrchr(piece_start, '/', piece_len); - uptr filename_len = piece_len; - if (filename_start) { - filename_start += 1; - filename_len = piece_len - (filename_start - piece_start); - } else { - filename_start = piece_start; - } - - // If the current piece isn't the runtime library name, - // append it to new_env. - if ((dylib_name_len != filename_len) || - (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) { - if (new_env_pos != new_env + env_name_len + 1) { - new_env_pos[0] = ':'; - new_env_pos++; - } - internal_strncpy(new_env_pos, piece_start, piece_len); - new_env_pos += piece_len; - } - // Move on to the next piece. - piece_start = piece_end; - } while (piece_start < old_env_end); - - // Can't use setenv() here, because it requires the allocator to be - // initialized. - // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in - // a separate function called after InitializeAllocator(). - if (new_env_pos == new_env + env_name_len + 1) new_env = NULL; - LeakyResetEnv(kDyldInsertLibraries, new_env); -} - // No-op. Mac does not support static linkage anyway. void *AsanDoesNotSupportStaticLinkage() { return 0; @@ -244,9 +60,6 @@ void AsanCheckDynamicRTPrereqs() {} // No-op. Mac does not support static linkage anyway. void AsanCheckIncompatibleRT() {} -void AsanPlatformThreadInit() { -} - void ReadContextStack(void *context, uptr *stack, uptr *ssize) { UNIMPLEMENTED(); } diff --git a/contrib/compiler-rt/lib/asan/asan_malloc_linux.cc b/contrib/compiler-rt/lib/asan/asan_malloc_linux.cc index 46a6a9db4a81..d5089f9f7b36 100644 --- a/contrib/compiler-rt/lib/asan/asan_malloc_linux.cc +++ b/contrib/compiler-rt/lib/asan/asan_malloc_linux.cc @@ -26,13 +26,25 @@ // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; // NOLINT +static const uptr kCallocPoolSize = 1024; +static uptr calloc_memory_for_dlsym[kCallocPoolSize]; + +static bool IsInCallocPool(const void *ptr) { + sptr off = (sptr)ptr - (sptr)calloc_memory_for_dlsym; + return 0 <= off && off < (sptr)kCallocPoolSize; +} + INTERCEPTOR(void, free, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInCallocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void, cfree, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInCallocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } @@ -44,8 +56,6 @@ INTERCEPTOR(void*, malloc, uptr size) { INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { if (UNLIKELY(!asan_inited)) { // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - const uptr kCallocPoolSize = 1024; - static uptr calloc_memory_for_dlsym[kCallocPoolSize]; static uptr allocated; uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; void *mem = (void*)&calloc_memory_for_dlsym[allocated]; @@ -59,6 +69,13 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { INTERCEPTOR(void*, realloc, void *ptr, uptr size) { GET_STACK_TRACE_MALLOC; + if (UNLIKELY(IsInCallocPool(ptr))) { + uptr offset = (uptr)ptr - (uptr)calloc_memory_for_dlsym; + uptr copy_size = Min(size, kCallocPoolSize - offset); + void *new_ptr = asan_malloc(size, &stack); + internal_memcpy(new_ptr, ptr, copy_size); + return new_ptr; + } return asan_realloc(ptr, size, &stack); } diff --git a/contrib/compiler-rt/lib/asan/asan_malloc_mac.cc b/contrib/compiler-rt/lib/asan/asan_malloc_mac.cc index d7a6307c9bdc..744728d40df5 100644 --- a/contrib/compiler-rt/lib/asan/asan_malloc_mac.cc +++ b/contrib/compiler-rt/lib/asan/asan_malloc_mac.cc @@ -15,348 +15,47 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_MAC -#include <AvailabilityMacros.h> -#include <CoreFoundation/CFBase.h> -#include <dlfcn.h> -#include <malloc/malloc.h> -#include <sys/mman.h> - -#include "asan_allocator.h" #include "asan_interceptors.h" -#include "asan_internal.h" #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" -#include "sanitizer_common/sanitizer_mac.h" - -// Similar code is used in Google Perftools, -// http://code.google.com/p/google-perftools. - -// ---------------------- Replacement functions ---------------- {{{1 -using namespace __asan; // NOLINT - -// TODO(glider): do we need both zones? -static malloc_zone_t *system_malloc_zone = 0; -static malloc_zone_t asan_zone; - -INTERCEPTOR(malloc_zone_t *, malloc_create_zone, - vm_size_t start_size, unsigned zone_flags) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - uptr page_size = GetPageSizeCached(); - uptr allocated_size = RoundUpTo(sizeof(asan_zone), page_size); - malloc_zone_t *new_zone = - (malloc_zone_t*)asan_memalign(page_size, allocated_size, - &stack, FROM_MALLOC); - internal_memcpy(new_zone, &asan_zone, sizeof(asan_zone)); - new_zone->zone_name = NULL; // The name will be changed anyway. - if (GetMacosVersion() >= MACOS_VERSION_LION) { - // Prevent the client app from overwriting the zone contents. - // Library functions that need to modify the zone will set PROT_WRITE on it. - // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher. - mprotect(new_zone, allocated_size, PROT_READ); - } - return new_zone; -} - -INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) { - ENSURE_ASAN_INITED(); - return &asan_zone; -} - -INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) { - // FIXME: ASan should support purgeable allocations. - // https://code.google.com/p/address-sanitizer/issues/detail?id=139 - ENSURE_ASAN_INITED(); - return &asan_zone; -} - -INTERCEPTOR(void, malloc_make_purgeable, void *ptr) { - // FIXME: ASan should support purgeable allocations. Ignoring them is fine - // for now. - ENSURE_ASAN_INITED(); -} - -INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) { - // FIXME: ASan should support purgeable allocations. Ignoring them is fine - // for now. - ENSURE_ASAN_INITED(); - // Must return 0 if the contents were not purged since the last call to - // malloc_make_purgeable(). - return 0; -} - -INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) { - ENSURE_ASAN_INITED(); - // Allocate |strlen("asan-") + 1 + internal_strlen(name)| bytes. - size_t buflen = 6 + (name ? internal_strlen(name) : 0); - InternalScopedString new_name(buflen); - if (name && zone->introspect == asan_zone.introspect) { - new_name.append("asan-%s", name); - name = new_name.data(); - } - - // Call the system malloc's implementation for both external and our zones, - // since that appropriately changes VM region protections on the zone. - REAL(malloc_set_zone_name)(zone, name); -} - -INTERCEPTOR(void *, malloc, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - void *res = asan_malloc(size, &stack); - return res; -} -INTERCEPTOR(void, free, void *ptr) { - ENSURE_ASAN_INITED(); - if (!ptr) return; - GET_STACK_TRACE_FREE; +using namespace __asan; +#define COMMON_MALLOC_ZONE_NAME "asan" +#define COMMON_MALLOC_ENTER() ENSURE_ASAN_INITED() +#define COMMON_MALLOC_SANITIZER_INITIALIZED asan_inited +#define COMMON_MALLOC_FORCE_LOCK() asan_mz_force_lock() +#define COMMON_MALLOC_FORCE_UNLOCK() asan_mz_force_unlock() +#define COMMON_MALLOC_MEMALIGN(alignment, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_memalign(alignment, size, &stack, FROM_MALLOC) +#define COMMON_MALLOC_MALLOC(size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_malloc(size, &stack) +#define COMMON_MALLOC_REALLOC(ptr, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_realloc(ptr, size, &stack); +#define COMMON_MALLOC_CALLOC(count, size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_calloc(count, size, &stack); +#define COMMON_MALLOC_VALLOC(size) \ + GET_STACK_TRACE_MALLOC; \ + void *p = asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); +#define COMMON_MALLOC_FREE(ptr) \ + GET_STACK_TRACE_FREE; \ asan_free(ptr, &stack, FROM_MALLOC); -} - -INTERCEPTOR(void *, realloc, void *ptr, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_realloc(ptr, size, &stack); -} - -INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_calloc(nmemb, size, &stack); -} - -INTERCEPTOR(void *, valloc, size_t size) { - ENSURE_ASAN_INITED(); - GET_STACK_TRACE_MALLOC; - return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); -} - -INTERCEPTOR(size_t, malloc_good_size, size_t size) { - ENSURE_ASAN_INITED(); - return asan_zone.introspect->good_size(&asan_zone, size); -} - -INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { - ENSURE_ASAN_INITED(); - CHECK(memptr); - GET_STACK_TRACE_MALLOC; - void *result = asan_memalign(alignment, size, &stack, FROM_MALLOC); - if (result) { - *memptr = result; - return 0; - } - return -1; -} - -namespace { - -// TODO(glider): the __asan_mz_* functions should be united with the Linux -// wrappers, as they are basically copied from there. -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -size_t __asan_mz_size(malloc_zone_t* zone, const void* ptr) { - return asan_mz_size(ptr); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_malloc(malloc_zone_t *zone, uptr size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_malloc(system_malloc_zone, size); - } - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { - if (UNLIKELY(!asan_inited)) { - // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - const size_t kCallocPoolSize = 1024; - static uptr calloc_memory_for_dlsym[kCallocPoolSize]; - static size_t allocated; - size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; - void *mem = (void*)&calloc_memory_for_dlsym[allocated]; - allocated += size_in_words; - CHECK(allocated < kCallocPoolSize); - return mem; - } - GET_STACK_TRACE_MALLOC; - return asan_calloc(nmemb, size, &stack); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_valloc(malloc_zone_t *zone, size_t size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_valloc(system_malloc_zone, size); - } - GET_STACK_TRACE_MALLOC; - return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC); -} - -#define GET_ZONE_FOR_PTR(ptr) \ - malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ - const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name - -void ALWAYS_INLINE free_common(void *context, void *ptr) { - if (!ptr) return; - GET_STACK_TRACE_FREE; - // FIXME: need to retire this flag. - if (!flags()->mac_ignore_invalid_free) { - asan_free(ptr, &stack, FROM_MALLOC); - } else { - GET_ZONE_FOR_PTR(ptr); - WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - return; - } -} - -// TODO(glider): the allocation callbacks need to be refactored. -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void __asan_mz_free(malloc_zone_t *zone, void *ptr) { - free_common(zone, ptr); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { - if (!ptr) { - GET_STACK_TRACE_MALLOC; - return asan_malloc(size, &stack); - } else { - if (asan_mz_size(ptr)) { - GET_STACK_TRACE_MALLOC; - return asan_realloc(ptr, size, &stack); - } else { - // We can't recover from reallocating an unknown address, because - // this would require reading at most |size| bytes from - // potentially unaccessible memory. - GET_STACK_TRACE_FREE; - GET_ZONE_FOR_PTR(ptr); - ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); - } - } -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void __asan_mz_destroy(malloc_zone_t* zone) { - // A no-op -- we will not be destroyed! - Report("__asan_mz_destroy() called -- ignoring\n"); -} - -extern "C" -SANITIZER_INTERFACE_ATTRIBUTE -void *__asan_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { - if (UNLIKELY(!asan_inited)) { - CHECK(system_malloc_zone); - return malloc_zone_memalign(system_malloc_zone, align, size); - } - GET_STACK_TRACE_MALLOC; - return asan_memalign(align, size, &stack, FROM_MALLOC); -} - -// This function is currently unused, and we build with -Werror. -#if 0 -void __asan_mz_free_definite_size( - malloc_zone_t* zone, void *ptr, size_t size) { - // TODO(glider): check that |size| is valid. - UNIMPLEMENTED(); -} -#endif - -kern_return_t mi_enumerator(task_t task, void *, - unsigned type_mask, vm_address_t zone_address, - memory_reader_t reader, - vm_range_recorder_t recorder) { - // Should enumerate all the pointers we have. Seems like a lot of work. - return KERN_FAILURE; -} - -size_t mi_good_size(malloc_zone_t *zone, size_t size) { - // I think it's always safe to return size, but we maybe could do better. - return size; -} - -boolean_t mi_check(malloc_zone_t *zone) { - UNIMPLEMENTED(); -} - -void mi_print(malloc_zone_t *zone, boolean_t verbose) { - UNIMPLEMENTED(); -} - -void mi_log(malloc_zone_t *zone, void *address) { - // I don't think we support anything like this -} - -void mi_force_lock(malloc_zone_t *zone) { - asan_mz_force_lock(); -} - -void mi_force_unlock(malloc_zone_t *zone) { - asan_mz_force_unlock(); -} - -void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { - AsanMallocStats malloc_stats; - FillMallocStatistics(&malloc_stats); - CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); +#define COMMON_MALLOC_SIZE(ptr) \ + uptr size = asan_mz_size(ptr); +#define COMMON_MALLOC_FILL_STATS(zone, stats) \ + AsanMallocStats malloc_stats; \ + FillMallocStatistics(&malloc_stats); \ + CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); \ internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t)); -} - -boolean_t mi_zone_locked(malloc_zone_t *zone) { - // UNIMPLEMENTED(); - return false; -} - -} // unnamed namespace - -namespace __asan { +#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ + GET_STACK_TRACE_FREE; \ + ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); +#define COMMON_MALLOC_NAMESPACE __asan -void ReplaceSystemMalloc() { - static malloc_introspection_t asan_introspection; - // Ok to use internal_memset, these places are not performance-critical. - internal_memset(&asan_introspection, 0, sizeof(asan_introspection)); +#include "sanitizer_common/sanitizer_malloc_mac.inc" - asan_introspection.enumerator = &mi_enumerator; - asan_introspection.good_size = &mi_good_size; - asan_introspection.check = &mi_check; - asan_introspection.print = &mi_print; - asan_introspection.log = &mi_log; - asan_introspection.force_lock = &mi_force_lock; - asan_introspection.force_unlock = &mi_force_unlock; - asan_introspection.statistics = &mi_statistics; - asan_introspection.zone_locked = &mi_zone_locked; - - internal_memset(&asan_zone, 0, sizeof(malloc_zone_t)); - - // Use version 6 for OSX >= 10.6. - asan_zone.version = 6; - asan_zone.zone_name = "asan"; - asan_zone.size = &__asan_mz_size; - asan_zone.malloc = &__asan_mz_malloc; - asan_zone.calloc = &__asan_mz_calloc; - asan_zone.valloc = &__asan_mz_valloc; - asan_zone.free = &__asan_mz_free; - asan_zone.realloc = &__asan_mz_realloc; - asan_zone.destroy = &__asan_mz_destroy; - asan_zone.batch_malloc = 0; - asan_zone.batch_free = 0; - asan_zone.free_definite_size = 0; - asan_zone.memalign = &__asan_mz_memalign; - asan_zone.introspect = &asan_introspection; - - // Register the ASan zone. - malloc_zone_register(&asan_zone); -} -} // namespace __asan - -#endif // SANITIZER_MAC +#endif diff --git a/contrib/compiler-rt/lib/asan/asan_mapping.h b/contrib/compiler-rt/lib/asan/asan_mapping.h index f9e1a527de18..8fe347c8bad0 100644 --- a/contrib/compiler-rt/lib/asan/asan_mapping.h +++ b/contrib/compiler-rt/lib/asan/asan_mapping.h @@ -17,7 +17,7 @@ #include "asan_internal.h" // The full explanation of the memory mapping could be found here: -// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm +// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm // // Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: // || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || @@ -73,6 +73,20 @@ // || `[0x2000000000, 0x23ffffffff]` || LowShadow || // || `[0x0000000000, 0x1fffffffff]` || LowMem || // +// Default Linux/AArch64 (39-bit VMA) mapping: +// || `[0x2000000000, 0x7fffffffff]` || highmem || +// || `[0x1400000000, 0x1fffffffff]` || highshadow || +// || `[0x1200000000, 0x13ffffffff]` || shadowgap || +// || `[0x1000000000, 0x11ffffffff]` || lowshadow || +// || `[0x0000000000, 0x0fffffffff]` || lowmem || +// +// Default Linux/AArch64 (42-bit VMA) mapping: +// || `[0x10000000000, 0x3ffffffffff]` || highmem || +// || `[0x0a000000000, 0x0ffffffffff]` || highshadow || +// || `[0x09000000000, 0x09fffffffff]` || shadowgap || +// || `[0x08000000000, 0x08fffffffff]` || lowshadow || +// || `[0x00000000000, 0x07fffffffff]` || lowmem || +// // Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000: // || `[0x500000000000, 0x7fffffffffff]` || HighMem || // || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow || @@ -113,11 +127,12 @@ static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000 static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 #define SHADOW_SCALE kDefaultShadowScale -#if SANITIZER_ANDROID -# define SHADOW_OFFSET (0) -#else -# if SANITIZER_WORDSIZE == 32 -# if defined(__mips__) + + +#if SANITIZER_WORDSIZE == 32 +# if SANITIZER_ANDROID +# define SHADOW_OFFSET (0) +# elif defined(__mips__) # define SHADOW_OFFSET kMIPS32_ShadowOffset32 # elif SANITIZER_FREEBSD # define SHADOW_OFFSET kFreeBSD_ShadowOffset32 @@ -130,7 +145,7 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 # else # define SHADOW_OFFSET kDefaultShadowOffset32 # endif -# else +#else # if defined(__aarch64__) # define SHADOW_OFFSET kAArch64_ShadowOffset64 # elif defined(__powerpc64__) @@ -148,7 +163,6 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 # else # define SHADOW_OFFSET kDefaultShort64bitShadowOffset # endif -# endif #endif #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) @@ -171,7 +185,8 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 // With the zero shadow base we can not actually map pages starting from 0. // This constant is somewhat arbitrary. -#define kZeroBaseShadowStart (1 << 18) +#define kZeroBaseShadowStart 0 +#define kZeroBaseMaxShadowStart (1 << 18) #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ : kZeroBaseShadowStart) diff --git a/contrib/compiler-rt/lib/asan/asan_new_delete.cc b/contrib/compiler-rt/lib/asan/asan_new_delete.cc index e48bdaf03dd3..b5ba13ef4055 100644 --- a/contrib/compiler-rt/lib/asan/asan_new_delete.cc +++ b/contrib/compiler-rt/lib/asan/asan_new_delete.cc @@ -30,7 +30,7 @@ using namespace __asan; // NOLINT // This code has issues on OSX. -// See https://code.google.com/p/address-sanitizer/issues/detail?id=131. +// See https://github.com/google/sanitizers/issues/131. // Fake std::nothrow_t to avoid including <new>. namespace std { @@ -90,11 +90,11 @@ INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { #if !SANITIZER_MAC CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr) throw() { +void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); } CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr) throw() { +void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW_BR); } CXX_OPERATOR_ATTRIBUTE @@ -106,12 +106,12 @@ void operator delete[](void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(FROM_NEW_BR); } CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, size_t size) throw() { +void operator delete(void *ptr, size_t size) NOEXCEPT { GET_STACK_TRACE_FREE; asan_sized_free(ptr, size, &stack, FROM_NEW); } CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, size_t size) throw() { +void operator delete[](void *ptr, size_t size) NOEXCEPT { GET_STACK_TRACE_FREE; asan_sized_free(ptr, size, &stack, FROM_NEW_BR); } diff --git a/contrib/compiler-rt/lib/asan/asan_poisoning.cc b/contrib/compiler-rt/lib/asan/asan_poisoning.cc index 569d359aa425..f77ab8780bb7 100644 --- a/contrib/compiler-rt/lib/asan/asan_poisoning.cc +++ b/contrib/compiler-rt/lib/asan/asan_poisoning.cc @@ -102,7 +102,7 @@ using namespace __asan; // NOLINT // that user program (un)poisons the memory it owns. It poisons memory // conservatively, and unpoisons progressively to make sure asan shadow // mapping invariant is preserved (see detailed mapping description here: -// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm). +// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm). // // * if user asks to poison region [left, right), the program poisons // at least [left, AlignDown(right)). @@ -354,7 +354,7 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, // Make a quick sanity check that we are indeed in this state. // // FIXME: Two of these three checks are disabled until we fix - // https://code.google.com/p/address-sanitizer/issues/detail?id=258. + // https://github.com/google/sanitizers/issues/258. // if (d1 != d2) // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1); if (a + granularity <= d1) @@ -375,10 +375,10 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, } } -int __sanitizer_verify_contiguous_container(const void *beg_p, - const void *mid_p, - const void *end_p) { - if (!flags()->detect_container_overflow) return 1; +const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg_p, const void *mid_p, const void *end_p) { + if (!flags()->detect_container_overflow) + return nullptr; uptr beg = reinterpret_cast<uptr>(beg_p); uptr end = reinterpret_cast<uptr>(end_p); uptr mid = reinterpret_cast<uptr>(mid_p); @@ -395,17 +395,24 @@ int __sanitizer_verify_contiguous_container(const void *beg_p, uptr r3_end = end; for (uptr i = r1_beg; i < r1_end; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast<const void *>(i); for (uptr i = r2_beg; i < mid; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast<const void *>(i); for (uptr i = mid; i < r2_end; i++) if (!AddressIsPoisoned(i)) - return 0; + return reinterpret_cast<const void *>(i); for (uptr i = r3_beg; i < r3_end; i++) if (!AddressIsPoisoned(i)) - return 0; - return 1; + return reinterpret_cast<const void *>(i); + return nullptr; +} + +int __sanitizer_verify_contiguous_container(const void *beg_p, + const void *mid_p, + const void *end_p) { + return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p, + end_p) == nullptr; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE diff --git a/contrib/compiler-rt/lib/asan/asan_posix.cc b/contrib/compiler-rt/lib/asan/asan_posix.cc index 2e857f6f624c..9e01bcd091bf 100644 --- a/contrib/compiler-rt/lib/asan/asan_posix.cc +++ b/contrib/compiler-rt/lib/asan/asan_posix.cc @@ -33,11 +33,11 @@ namespace __asan { -void AsanOnSIGSEGV(int, void *siginfo, void *context) { +void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { ScopedDeadlySignal signal_scope(GetCurrentThread()); int code = (int)((siginfo_t*)siginfo)->si_code; // Write the first message using the bullet-proof write. - if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); + if (18 != internal_write(2, "ASAN:DEADLYSIGNAL\n", 18)) Die(); SignalContext sig = SignalContext::Create(siginfo, context); // Access at a reasonable offset above SP, or slightly below it (to account @@ -75,8 +75,12 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) { // unaligned memory access. if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) ReportStackOverflow(sig); + else if (signo == SIGFPE) + ReportDeadlySignal("FPE", sig); + else if (signo == SIGILL) + ReportDeadlySignal("ILL", sig); else - ReportSIGSEGV("SEGV", sig); + ReportDeadlySignal("SEGV", sig); } // ---------------------- TSD ---------------- {{{1 diff --git a/contrib/compiler-rt/lib/asan/asan_report.cc b/contrib/compiler-rt/lib/asan/asan_report.cc index c1681e644464..bb7e36e84652 100644 --- a/contrib/compiler-rt/lib/asan/asan_report.cc +++ b/contrib/compiler-rt/lib/asan/asan_report.cc @@ -11,6 +11,7 @@ // // This file contains error reporting code. //===----------------------------------------------------------------------===// + #include "asan_flags.h" #include "asan_internal.h" #include "asan_mapping.h" @@ -27,9 +28,11 @@ namespace __asan { // -------------------- User-specified callbacks ----------------- {{{1 static void (*error_report_callback)(const char*); -static char *error_message_buffer = 0; +static char *error_message_buffer = nullptr; static uptr error_message_buffer_pos = 0; -static uptr error_message_buffer_size = 0; +static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED); +static const unsigned kAsanBuggyPcPoolSize = 25; +static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize]; struct ReportData { uptr pc; @@ -45,16 +48,20 @@ static bool report_happened = false; static ReportData report_data = {}; void AppendToErrorMessageBuffer(const char *buffer) { - if (error_message_buffer) { - uptr length = internal_strlen(buffer); - CHECK_GE(error_message_buffer_size, error_message_buffer_pos); - uptr remaining = error_message_buffer_size - error_message_buffer_pos; - internal_strncpy(error_message_buffer + error_message_buffer_pos, - buffer, remaining); - error_message_buffer[error_message_buffer_size - 1] = '\0'; - // FIXME: reallocate the buffer instead of truncating the message. - error_message_buffer_pos += Min(remaining, length); + BlockingMutexLock l(&error_message_buf_mutex); + if (!error_message_buffer) { + error_message_buffer = + (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__); + error_message_buffer_pos = 0; } + uptr length = internal_strlen(buffer); + RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos); + uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos; + internal_strncpy(error_message_buffer + error_message_buffer_pos, + buffer, remaining); + error_message_buffer[kErrorMessageBufferSize - 1] = '\0'; + // FIXME: reallocate the buffer instead of truncating the message. + error_message_buffer_pos += Min(remaining, length); } // ---------------------- Decorator ------------------------------ {{{1 @@ -373,7 +380,7 @@ static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr, uptr next_var_beg) { uptr var_end = var.beg + var.size; uptr addr_end = addr + access_size; - const char *pos_descr = 0; + const char *pos_descr = nullptr; // If the variable [var.beg, var_end) is the nearest variable to the // current memory access, indicate it in the log. if (addr >= var.beg) { @@ -544,7 +551,7 @@ void DescribeHeapAddress(uptr addr, uptr access_size) { StackTrace alloc_stack = chunk.GetAllocStack(); char tname[128]; Decorator d; - AsanThreadContext *free_thread = 0; + AsanThreadContext *free_thread = nullptr; if (chunk.FreeTid() != kInvalidTid) { free_thread = GetThreadContextByTidLocked(chunk.FreeTid()); Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), @@ -621,26 +628,90 @@ void DescribeThread(AsanThreadContext *context) { // immediately after printing error report. class ScopedInErrorReport { public: - explicit ScopedInErrorReport(ReportData *report = nullptr) { - static atomic_uint32_t num_calls; - static u32 reporting_thread_tid; - if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { + explicit ScopedInErrorReport(ReportData *report = nullptr, + bool fatal = false) { + halt_on_error_ = fatal || flags()->halt_on_error; + + if (lock_.TryLock()) { + StartReporting(report); + return; + } + + // ASan found two bugs in different threads simultaneously. + + u32 current_tid = GetCurrentTidOrInvalid(); + if (reporting_thread_tid_ == current_tid || + reporting_thread_tid_ == kInvalidTid) { + // This is either asynch signal or nested error during error reporting. + // Fail simple to avoid deadlocks in Report(). + + // Can't use Report() here because of potential deadlocks + // in nested signal handlers. + const char msg[] = "AddressSanitizer: nested bug in the same thread, " + "aborting.\n"; + WriteToFile(kStderrFd, msg, sizeof(msg)); + + internal__exit(common_flags()->exitcode); + } + + if (halt_on_error_) { // Do not print more than one report, otherwise they will mix up. // Error reporting functions shouldn't return at this situation, as - // they are defined as no-return. + // they are effectively no-returns. + Report("AddressSanitizer: while reporting a bug found another one. " - "Ignoring.\n"); - u32 current_tid = GetCurrentTidOrInvalid(); - if (current_tid != reporting_thread_tid) { - // ASan found two bugs in different threads simultaneously. Sleep - // long enough to make sure that the thread which started to print - // an error report will finish doing it. - SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); - } + "Ignoring.\n"); + + // Sleep long enough to make sure that the thread which started + // to print an error report will finish doing it. + SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); + // If we're still not dead for some reason, use raw _exit() instead of // Die() to bypass any additional checks. - internal__exit(flags()->exitcode); + internal__exit(common_flags()->exitcode); + } else { + // The other thread will eventually finish reporting + // so it's safe to wait + lock_.Lock(); } + + StartReporting(report); + } + + ~ScopedInErrorReport() { + // Make sure the current thread is announced. + DescribeThread(GetCurrentThread()); + // We may want to grab this lock again when printing stats. + asanThreadRegistry().Unlock(); + // Print memory stats. + if (flags()->print_stats) + __asan_print_accumulated_stats(); + + // Copy the message buffer so that we could start logging without holding a + // lock that gets aquired during printing. + InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize); + { + BlockingMutexLock l(&error_message_buf_mutex); + internal_memcpy(buffer_copy.data(), + error_message_buffer, kErrorMessageBufferSize); + } + + LogFullErrorReport(buffer_copy.data()); + + if (error_report_callback) { + error_report_callback(buffer_copy.data()); + } + CommonSanitizerReportMutex.Unlock(); + reporting_thread_tid_ = kInvalidTid; + lock_.Unlock(); + if (halt_on_error_) { + Report("ABORTING\n"); + Die(); + } + } + + private: + void StartReporting(ReportData *report) { if (report) report_data = *report; report_happened = true; ASAN_ON_ERROR(); @@ -650,27 +721,19 @@ class ScopedInErrorReport { // recursive reports. asanThreadRegistry().Lock(); CommonSanitizerReportMutex.Lock(); - reporting_thread_tid = GetCurrentTidOrInvalid(); + reporting_thread_tid_ = GetCurrentTidOrInvalid(); Printf("====================================================" "=============\n"); } - // Destructor is NORETURN, as functions that report errors are. - NORETURN ~ScopedInErrorReport() { - // Make sure the current thread is announced. - DescribeThread(GetCurrentThread()); - // We may want to grab this lock again when printing stats. - asanThreadRegistry().Unlock(); - // Print memory stats. - if (flags()->print_stats) - __asan_print_accumulated_stats(); - if (error_report_callback) { - error_report_callback(error_message_buffer); - } - Report("ABORTING\n"); - Die(); - } + + static StaticSpinMutex lock_; + static u32 reporting_thread_tid_; + bool halt_on_error_; }; +StaticSpinMutex ScopedInErrorReport::lock_; +u32 ScopedInErrorReport::reporting_thread_tid_; + void ReportStackOverflow(const SignalContext &sig) { ScopedInErrorReport in_report; Decorator d; @@ -686,8 +749,8 @@ void ReportStackOverflow(const SignalContext &sig) { ReportErrorSummary("stack-overflow", &stack); } -void ReportSIGSEGV(const char *description, const SignalContext &sig) { - ScopedInErrorReport in_report; +void ReportDeadlySignal(const char *description, const SignalContext &sig) { + ScopedInErrorReport in_report(/*report*/nullptr, /*fatal*/true); Decorator d; Printf("%s", d.Warning()); Report( @@ -703,7 +766,7 @@ void ReportSIGSEGV(const char *description, const SignalContext &sig) { stack.Print(); MaybeDumpInstructionBytes(sig.pc); Printf("AddressSanitizer can not provide additional info.\n"); - ReportErrorSummary("SEGV", &stack); + ReportErrorSummary(description, &stack); } void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) { @@ -744,7 +807,7 @@ void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("new-delete-type-mismatch", &stack); - Report("HINT: if you don't care about these warnings you may set " + Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=new_delete_type_mismatch=0\n"); } @@ -784,7 +847,7 @@ void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, stack.Print(); DescribeHeapAddress(addr, 1); ReportErrorSummary("alloc-dealloc-mismatch", &stack); - Report("HINT: if you don't care about these warnings you may set " + Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); } @@ -886,7 +949,7 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1, Printf(" [2]:\n"); StackDepotGet(stack_id2).Print(); } - Report("HINT: if you don't care about these warnings you may set " + Report("HINT: if you don't care about these errors you may set " "ASAN_OPTIONS=detect_odr_violation=0\n"); InternalScopedString error_msg(256); error_msg.append("odr-violation: global '%s' at %s", @@ -925,17 +988,6 @@ static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { } // ----------------------- Mac-specific reports ----------------- {{{1 -void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name, - BufferedStackTrace *stack) { - // Just print a warning here. - Printf("free_common(%p) -- attempting to free unallocated memory.\n" - "AddressSanitizer is ignoring this error on Mac OS now.\n", - addr); - PrintZoneForPointer(addr, zone_ptr, zone_name); - stack->Print(); - DescribeHeapAddress(addr, 1); -} - void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, BufferedStackTrace *stack) { ScopedInErrorReport in_report; @@ -947,24 +999,23 @@ void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, DescribeHeapAddress(addr, 1); } -void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, - BufferedStackTrace *stack) { - ScopedInErrorReport in_report; - Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n" - "This is an unrecoverable problem, exiting now.\n", - addr); - PrintZoneForPointer(addr, zone_ptr, zone_name); - stack->Print(); - DescribeHeapAddress(addr, 1); +// -------------- SuppressErrorReport -------------- {{{1 +// Avoid error reports duplicating for ASan recover mode. +static bool SuppressErrorReport(uptr pc) { + if (!common_flags()->suppress_equal_pcs) return false; + for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) { + uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]); + if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp, + pc, memory_order_relaxed)) + return false; + if (cmp == pc) return true; + } + Die(); } -} // namespace __asan - -// --------------------------- Interface --------------------- {{{1 -using namespace __asan; // NOLINT - -void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, - uptr access_size, u32 exp) { +void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, + uptr access_size, u32 exp, bool fatal) { + if (!fatal && SuppressErrorReport(pc)) return; ENABLE_FRAME_POINTER; // Optimization experiments. @@ -1033,7 +1084,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size, bug_descr }; - ScopedInErrorReport in_report(&report); + ScopedInErrorReport in_report(&report, fatal); Decorator d; Printf("%s", d.Warning()); @@ -1059,14 +1110,21 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, PrintShadowMemoryForAddress(addr); } +} // namespace __asan + +// --------------------------- Interface --------------------- {{{1 +using namespace __asan; // NOLINT + +void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, + uptr access_size, u32 exp) { + ENABLE_FRAME_POINTER; + bool fatal = flags()->halt_on_error; + ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal); +} + void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { + BlockingMutexLock l(&error_message_buf_mutex); error_report_callback = callback; - if (callback) { - error_message_buffer_size = 1 << 16; - error_message_buffer = - (char*)MmapOrDie(error_message_buffer_size, __func__); - error_message_buffer_pos = 0; - } } void __asan_describe_address(uptr addr) { @@ -1117,7 +1175,7 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_ptr_cmp(void *a, void *b) { CheckForInvalidPointerPair(a, b); } -} // extern "C" +} // extern "C" #if !SANITIZER_SUPPORTS_WEAK_HOOKS // Provide default implementation of __asan_on_error that does nothing diff --git a/contrib/compiler-rt/lib/asan/asan_report.h b/contrib/compiler-rt/lib/asan/asan_report.h index e2786b0f260c..559b8adfd51d 100644 --- a/contrib/compiler-rt/lib/asan/asan_report.h +++ b/contrib/compiler-rt/lib/asan/asan_report.h @@ -49,44 +49,39 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size); void DescribeThread(AsanThreadContext *context); // Different kinds of error reports. -void NORETURN ReportStackOverflow(const SignalContext &sig); -void NORETURN ReportSIGSEGV(const char *description, const SignalContext &sig); -void NORETURN ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, - BufferedStackTrace *free_stack); -void NORETURN ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); -void NORETURN ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack); -void NORETURN ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, - AllocType alloc_type, - AllocType dealloc_type); -void NORETURN - ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack); -void NORETURN - ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, - BufferedStackTrace *stack); -void NORETURN - ReportStringFunctionMemoryRangesOverlap(const char *function, - const char *offset1, uptr length1, - const char *offset2, uptr length2, - BufferedStackTrace *stack); -void NORETURN ReportStringFunctionSizeOverflow(uptr offset, uptr size, - BufferedStackTrace *stack); -void NORETURN - ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, - uptr old_mid, uptr new_mid, - BufferedStackTrace *stack); +void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, + uptr access_size, u32 exp, bool fatal); +void ReportStackOverflow(const SignalContext &sig); +void ReportDeadlySignal(const char *description, const SignalContext &sig); +void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, + BufferedStackTrace *free_stack); +void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); +void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack); +void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack, + AllocType alloc_type, + AllocType dealloc_type); +void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack); +void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, + BufferedStackTrace *stack); +void ReportStringFunctionMemoryRangesOverlap(const char *function, + const char *offset1, uptr length1, + const char *offset2, uptr length2, + BufferedStackTrace *stack); +void ReportStringFunctionSizeOverflow(uptr offset, uptr size, + BufferedStackTrace *stack); +void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, + uptr old_mid, uptr new_mid, + BufferedStackTrace *stack); -void NORETURN -ReportODRViolation(const __asan_global *g1, u32 stack_id1, - const __asan_global *g2, u32 stack_id2); +void ReportODRViolation(const __asan_global *g1, u32 stack_id1, + const __asan_global *g2, u32 stack_id2); // Mac-specific errors and warnings. -void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name, - BufferedStackTrace *stack); -void NORETURN ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, - const char *zone_name, - BufferedStackTrace *stack); -void NORETURN ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, - const char *zone_name, - BufferedStackTrace *stack); +void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, + const char *zone_name, + BufferedStackTrace *stack); +void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, + const char *zone_name, + BufferedStackTrace *stack); } // namespace __asan diff --git a/contrib/compiler-rt/lib/asan/asan_rtl.cc b/contrib/compiler-rt/lib/asan/asan_rtl.cc index a8d92b915a9a..7b8b5dd9be1b 100644 --- a/contrib/compiler-rt/lib/asan/asan_rtl.cc +++ b/contrib/compiler-rt/lib/asan/asan_rtl.cc @@ -11,6 +11,7 @@ // // Main file of the ASan run-time library. //===----------------------------------------------------------------------===// + #include "asan_activation.h" #include "asan_allocator.h" #include "asan_interceptors.h" @@ -56,11 +57,6 @@ static void AsanDie() { UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); } } - if (common_flags()->coverage) - __sanitizer_cov_dump(); - if (flags()->abort_on_error) - Abort(); - internal__exit(flags()->exitcode); } static void AsanCheckFailed(const char *file, int line, const char *cond, @@ -117,13 +113,18 @@ static void OnLowLevelAllocate(uptr ptr, uptr size) { extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_ ## type ## size(uptr addr) { \ GET_CALLER_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, addr, is_write, size, 0); \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \ GET_CALLER_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, addr, is_write, size, exp); \ -} + ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ +} \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## size ## _noabort(uptr addr) { \ + GET_CALLER_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ +} \ ASAN_REPORT_ERROR(load, false, 1) ASAN_REPORT_ERROR(load, false, 2) @@ -136,22 +137,27 @@ ASAN_REPORT_ERROR(store, true, 4) ASAN_REPORT_ERROR(store, true, 8) ASAN_REPORT_ERROR(store, true, 16) -#define ASAN_REPORT_ERROR_N(type, is_write) \ -extern "C" NOINLINE INTERFACE_ATTRIBUTE \ -void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ - GET_CALLER_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, addr, is_write, size, 0); \ -} \ -extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +#define ASAN_REPORT_ERROR_N(type, is_write) \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ + GET_CALLER_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ +} \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \ GET_CALLER_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, addr, is_write, size, exp); \ -} + ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ +} \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \ + GET_CALLER_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ +} \ ASAN_REPORT_ERROR_N(load, false) ASAN_REPORT_ERROR_N(store, true) -#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg) \ +#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \ uptr sp = MEM_TO_SHADOW(addr); \ uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \ : *reinterpret_cast<u16 *>(sp); \ @@ -163,7 +169,8 @@ ASAN_REPORT_ERROR_N(store, true) *__asan_test_only_reported_buggy_pointer = addr; \ } else { \ GET_CALLER_PC_BP_SP; \ - __asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg); \ + ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, \ + fatal); \ } \ } \ } @@ -171,12 +178,16 @@ ASAN_REPORT_ERROR_N(store, true) #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_##type##size(uptr addr) { \ - ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0) \ + ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \ } \ extern "C" NOINLINE INTERFACE_ATTRIBUTE \ void __asan_exp_##type##size(uptr addr, u32 exp) { \ - ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp) \ - } + ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \ + } \ + extern "C" NOINLINE INTERFACE_ATTRIBUTE \ + void __asan_##type##size ## _noabort(uptr addr) { \ + ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \ + } \ ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) @@ -194,7 +205,7 @@ NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; - __asan_report_error(pc, bp, sp, addr, false, size, 0); + ReportGenericError(pc, bp, sp, addr, false, size, 0, true); } } @@ -203,7 +214,16 @@ NOINLINE INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; - __asan_report_error(pc, bp, sp, addr, false, size, exp); + ReportGenericError(pc, bp, sp, addr, false, size, exp, true); + } +} + +extern "C" +NOINLINE INTERFACE_ATTRIBUTE +void __asan_loadN_noabort(uptr addr, uptr size) { + if (__asan_region_is_poisoned(addr, size)) { + GET_CALLER_PC_BP_SP; + ReportGenericError(pc, bp, sp, addr, false, size, 0, false); } } @@ -212,7 +232,7 @@ NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; - __asan_report_error(pc, bp, sp, addr, true, size, 0); + ReportGenericError(pc, bp, sp, addr, true, size, 0, true); } } @@ -221,7 +241,16 @@ NOINLINE INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { if (__asan_region_is_poisoned(addr, size)) { GET_CALLER_PC_BP_SP; - __asan_report_error(pc, bp, sp, addr, true, size, exp); + ReportGenericError(pc, bp, sp, addr, true, size, exp, true); + } +} + +extern "C" +NOINLINE INTERFACE_ATTRIBUTE +void __asan_storeN_noabort(uptr addr, uptr size) { + if (__asan_region_is_poisoned(addr, size)) { + GET_CALLER_PC_BP_SP; + ReportGenericError(pc, bp, sp, addr, true, size, 0, false); } } @@ -259,16 +288,15 @@ static NOINLINE void force_interface_symbols() { case 22: __asan_report_exp_store8(0, 0); break; case 23: __asan_report_exp_store16(0, 0); break; case 24: __asan_report_exp_store_n(0, 0, 0); break; - case 25: __asan_register_globals(0, 0); break; - case 26: __asan_unregister_globals(0, 0); break; - case 27: __asan_set_death_callback(0); break; - case 28: __asan_set_error_report_callback(0); break; + case 25: __asan_register_globals(nullptr, 0); break; + case 26: __asan_unregister_globals(nullptr, 0); break; + case 27: __asan_set_death_callback(nullptr); break; + case 28: __asan_set_error_report_callback(nullptr); break; case 29: __asan_handle_no_return(); break; - case 30: __asan_address_is_poisoned(0); break; - case 31: __asan_poison_memory_region(0, 0); break; - case 32: __asan_unpoison_memory_region(0, 0); break; - case 33: __asan_set_error_exit_code(0); break; - case 34: __asan_before_dynamic_init(0); break; + case 30: __asan_address_is_poisoned(nullptr); break; + case 31: __asan_poison_memory_region(nullptr, 0); break; + case 32: __asan_unpoison_memory_region(nullptr, 0); break; + case 34: __asan_before_dynamic_init(nullptr); break; case 35: __asan_after_dynamic_init(); break; case 36: __asan_poison_stack_memory(0, 0); break; case 37: __asan_unpoison_stack_memory(0, 0); break; @@ -298,9 +326,25 @@ static void InitializeHighMemEnd() { } static void ProtectGap(uptr addr, uptr size) { + if (!flags()->protect_shadow_gap) + return; void *res = MmapNoAccess(addr, size, "shadow gap"); if (addr == (uptr)res) return; + // A few pages at the start of the address space can not be protected. + // But we really want to protect as much as possible, to prevent this memory + // being returned as a result of a non-FIXED mmap(). + if (addr == kZeroBaseShadowStart) { + uptr step = GetPageSizeCached(); + while (size > step && addr < kZeroBaseMaxShadowStart) { + addr += step; + size -= step; + void *res = MmapNoAccess(addr, size, "shadow gap"); + if (addr == (uptr)res) + return; + } + } + Report("ERROR: Failed to protect the shadow gap. " "ASan cannot proceed correctly. ABORTING.\n"); DumpProcessMap(); @@ -363,12 +407,12 @@ static void AsanInitInternal() { CHECK(!asan_init_is_running && "ASan init calls itself!"); asan_init_is_running = true; + CacheBinaryName(); + // Initialize flags. This must be done early, because most of the // initialization steps look at flags(). InitializeFlags(); - CacheBinaryName(); - AsanCheckIncompatibleRT(); AsanCheckDynamicRTPrereqs(); @@ -381,7 +425,7 @@ static void AsanInitInternal() { AsanDoesNotSupportStaticLinkage(); // Install tool-specific callbacks in sanitizer_common. - SetDieCallback(AsanDie); + AddDieCallback(AsanDie); SetCheckFailedCallback(AsanCheckFailed); SetPrintfAndReportCallback(AppendToErrorMessageBuffer); @@ -457,7 +501,7 @@ static void AsanInitInternal() { } AsanTSDInit(PlatformTSDDtor); - InstallDeadlySignalHandlers(AsanOnSIGSEGV); + InstallDeadlySignalHandlers(AsanOnDeadlySignal); AllocatorOptions allocator_options; allocator_options.SetFrom(flags(), common_flags()); @@ -531,24 +575,26 @@ public: // NOLINT static AsanInitializer asan_initializer; #endif // ASAN_DYNAMIC -} // namespace __asan +} // namespace __asan // ---------------------- Interface ---------------- {{{1 using namespace __asan; // NOLINT -int NOINLINE __asan_set_error_exit_code(int exit_code) { - int old = flags()->exitcode; - flags()->exitcode = exit_code; - return old; -} - void NOINLINE __asan_handle_no_return() { int local_stack; AsanThread *curr_thread = GetCurrentThread(); - CHECK(curr_thread); uptr PageSize = GetPageSizeCached(); - uptr top = curr_thread->stack_top(); - uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1); + uptr top, bottom; + if (curr_thread) { + top = curr_thread->stack_top(); + bottom = ((uptr)&local_stack - PageSize) & ~(PageSize - 1); + } else { + // If we haven't seen this thread, try asking the OS for stack bounds. + uptr tls_addr, tls_size, stack_size; + GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr, + &tls_size); + top = bottom + stack_size; + } static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M if (top - bottom > kMaxExpectedCleanupSize) { static bool reported_warning = false; @@ -559,12 +605,12 @@ void NOINLINE __asan_handle_no_return() { "stack top: %p; bottom %p; size: %p (%zd)\n" "False positive error reports may follow\n" "For details see " - "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n", + "https://github.com/google/sanitizers/issues/189\n", top, bottom, top - bottom, top - bottom); return; } PoisonShadow(bottom, top - bottom, 0); - if (curr_thread->has_fake_stack()) + if (curr_thread && curr_thread->has_fake_stack()) curr_thread->fake_stack()->HandleNoReturn(); } @@ -578,3 +624,7 @@ void __asan_init() { AsanActivate(); AsanInitInternal(); } + +void __asan_version_mismatch_check() { + // Do nothing. +} diff --git a/contrib/compiler-rt/lib/asan/asan_stack.h b/contrib/compiler-rt/lib/asan/asan_stack.h index 122967a152f8..5c5181509801 100644 --- a/contrib/compiler-rt/lib/asan/asan_stack.h +++ b/contrib/compiler-rt/lib/asan/asan_stack.h @@ -11,6 +11,7 @@ // // ASan-private header for asan_stack.cc. //===----------------------------------------------------------------------===// + #ifndef ASAN_STACK_H #define ASAN_STACK_H @@ -48,15 +49,15 @@ void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth, uptr stack_bottom = t->stack_bottom(); ScopedUnwinding unwind_scope(t); stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast); - } else if (t == 0 && !fast) { + } else if (!t && !fast) { /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ stack->Unwind(max_depth, pc, bp, context, 0, 0, false); } } -#endif // SANITIZER_WINDOWS +#endif // SANITIZER_WINDOWS } -} // namespace __asan +} // namespace __asan // NOTE: A Rule of thumb is to retrieve stack trace in the interceptors // as early as possible (in functions exposed to the user), as we generally @@ -115,4 +116,4 @@ void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth, stack.Print(); \ } -#endif // ASAN_STACK_H +#endif // ASAN_STACK_H diff --git a/contrib/compiler-rt/lib/asan/asan_thread.cc b/contrib/compiler-rt/lib/asan/asan_thread.cc index 9af5706d86d0..69813546f551 100644 --- a/contrib/compiler-rt/lib/asan/asan_thread.cc +++ b/contrib/compiler-rt/lib/asan/asan_thread.cc @@ -42,7 +42,7 @@ void AsanThreadContext::OnCreated(void *arg) { void AsanThreadContext::OnFinished() { // Drop the link to the AsanThread object. - thread = 0; + thread = nullptr; } // MIPS requires aligned address @@ -125,7 +125,7 @@ void AsanThread::Destroy() { FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() { uptr stack_size = this->stack_size(); if (stack_size == 0) // stack_size is not yet available, don't use FakeStack. - return 0; + return nullptr; uptr old_val = 0; // fake_stack_ has 3 states: // 0 -- not initialized @@ -146,11 +146,11 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() { SetTLSFakeStack(fake_stack_); return fake_stack_; } - return 0; + return nullptr; } void AsanThread::Init() { - fake_stack_ = 0; // Will be initialized lazily if needed. + fake_stack_ = nullptr; // Will be initialized lazily if needed. CHECK_EQ(this->stack_size(), 0U); SetThreadStackAndTls(); CHECK_GT(this->stack_size(), 0U); @@ -161,13 +161,12 @@ void AsanThread::Init() { VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(), (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_, &local); - AsanPlatformThreadInit(); } thread_return_t AsanThread::ThreadStart( uptr os_id, atomic_uintptr_t *signal_thread_is_registered) { Init(); - asanThreadRegistry().StartThread(tid(), os_id, 0); + asanThreadRegistry().StartThread(tid(), os_id, nullptr); if (signal_thread_is_registered) atomic_store(signal_thread_is_registered, 1, memory_order_release); @@ -277,7 +276,7 @@ AsanThread *GetCurrentThread() { return tctx->thread; } } - return 0; + return nullptr; } return context->thread; } @@ -302,7 +301,7 @@ AsanThread *FindThreadByStackAddress(uptr addr) { AsanThreadContext *tctx = static_cast<AsanThreadContext *>( asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress, (void *)addr)); - return tctx ? tctx->thread : 0; + return tctx ? tctx->thread : nullptr; } void EnsureMainThreadIDIsCorrect() { @@ -315,10 +314,10 @@ void EnsureMainThreadIDIsCorrect() { __asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) { __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>( __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id)); - if (!context) return 0; + if (!context) return nullptr; return context->thread; } -} // namespace __asan +} // namespace __asan // --- Implementation of LSan-specific functions --- {{{1 namespace __lsan { @@ -355,4 +354,4 @@ void UnlockThreadRegistry() { void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); } -} // namespace __lsan +} // namespace __lsan diff --git a/contrib/compiler-rt/lib/asan/asan_thread.h b/contrib/compiler-rt/lib/asan/asan_thread.h index 50acfc42d6a2..ac35711f5794 100644 --- a/contrib/compiler-rt/lib/asan/asan_thread.h +++ b/contrib/compiler-rt/lib/asan/asan_thread.h @@ -11,6 +11,7 @@ // // ASan-private header for asan_thread.cc. //===----------------------------------------------------------------------===// + #ifndef ASAN_THREAD_H #define ASAN_THREAD_H @@ -36,7 +37,7 @@ class AsanThreadContext : public ThreadContextBase { explicit AsanThreadContext(int tid) : ThreadContextBase(tid), announced(false), destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), - thread(0) {} + thread(nullptr) {} bool announced; u8 destructor_iterations; u32 stack_id; @@ -84,8 +85,8 @@ class AsanThread { void DeleteFakeStack(int tid) { if (!fake_stack_) return; FakeStack *t = fake_stack_; - fake_stack_ = 0; - SetTLSFakeStack(0); + fake_stack_ = nullptr; + SetTLSFakeStack(nullptr); t->Destroy(tid); } @@ -95,7 +96,7 @@ class AsanThread { FakeStack *fake_stack() { if (!__asan_option_detect_stack_use_after_return) - return 0; + return nullptr; if (!has_fake_stack()) return AsyncSignalSafeLazyInitFakeStack(); return fake_stack_; @@ -179,6 +180,6 @@ AsanThread *FindThreadByStackAddress(uptr addr); // Used to handle fork(). void EnsureMainThreadIDIsCorrect(); -} // namespace __asan +} // namespace __asan -#endif // ASAN_THREAD_H +#endif // ASAN_THREAD_H diff --git a/contrib/compiler-rt/lib/asan/asan_win.cc b/contrib/compiler-rt/lib/asan/asan_win.cc index addb3d40a696..92bd893d10ef 100644 --- a/contrib/compiler-rt/lib/asan/asan_win.cc +++ b/contrib/compiler-rt/lib/asan/asan_win.cc @@ -14,9 +14,9 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_WINDOWS +#define WIN32_LEAN_AND_MEAN #include <windows.h> -#include <dbghelp.h> #include <stdlib.h> #include "asan_interceptors.h" @@ -175,14 +175,6 @@ void PlatformTSDDtor(void *tsd) { // }}} // ---------------------- Various stuff ---------------- {{{ -void DisableReexec() { - // No need to re-exec on Windows. -} - -void MaybeReexec() { - // No need to re-exec on Windows. -} - void *AsanDoesNotSupportStaticLinkage() { #if defined(_DEBUG) #error Please build the runtime with a non-debug CRT: /MD or /MT @@ -194,15 +186,11 @@ void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} -void AsanPlatformThreadInit() { - // Nothing here for now. -} - void ReadContextStack(void *context, uptr *stack, uptr *ssize) { UNIMPLEMENTED(); } -void AsanOnSIGSEGV(int, void *siginfo, void *context) { +void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); } @@ -219,7 +207,7 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { ? "access-violation" : "in-page-error"; SignalContext sig = SignalContext::Create(exception_record, context); - ReportSIGSEGV(description, sig); + ReportDeadlySignal(description, sig); } // FIXME: Handle EXCEPTION_STACK_OVERFLOW here. @@ -257,7 +245,7 @@ int __asan_set_seh_filter() { // Put a pointer to __asan_set_seh_filter at the end of the global list // of C initializers, after the default EH is set by the CRT. #pragma section(".CRT$XIZ", long, read) // NOLINT -static __declspec(allocate(".CRT$XIZ")) +__declspec(allocate(".CRT$XIZ")) int (*__intercept_seh)() = __asan_set_seh_filter; #endif // }}} diff --git a/contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc b/contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc index b77f18168ae5..672cabf43ec1 100644 --- a/contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc +++ b/contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc @@ -12,8 +12,7 @@ // This file defines a family of thunks that should be statically linked into // the DLLs that have ASan instrumentation in order to delegate the calls to the // shared runtime that lives in the main binary. -// See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the -// details. +// See https://github.com/google/sanitizers/issues/209 for the details. //===----------------------------------------------------------------------===// // Only compile this code when buidling asan_dll_thunk.lib @@ -30,8 +29,9 @@ void *__stdcall GetProcAddress(void *module, const char *proc_name); void abort(); } -static void *getRealProcAddressOrDie(const char *name) { - void *ret = GetProcAddress(GetModuleHandleA(0), name); +static uptr getRealProcAddressOrDie(const char *name) { + uptr ret = + __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name); if (!ret) abort(); return ret; @@ -62,13 +62,12 @@ struct FunctionInterceptor<0> { }; #define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function) \ - template<> struct FunctionInterceptor<__LINE__> { \ + template <> struct FunctionInterceptor<__LINE__> { \ static void Execute() { \ - void *wrapper = getRealProcAddressOrDie(main_function); \ - if (!__interception::OverrideFunction((uptr)dll_function, \ - (uptr)wrapper, 0)) \ + uptr wrapper = getRealProcAddressOrDie(main_function); \ + if (!__interception::OverrideFunction((uptr)dll_function, wrapper, 0)) \ abort(); \ - FunctionInterceptor<__LINE__-1>::Execute(); \ + FunctionInterceptor<__LINE__ - 1>::Execute(); \ } \ }; @@ -210,7 +209,7 @@ extern "C" { // __asan_init is expected to be called by only one thread. if (fn) return; - fn = (fntype)getRealProcAddressOrDie(__asan_init_name); + fn = (fntype)getRealProcAddressOrDie("__asan_init"); fn(); __asan_option_detect_stack_use_after_return = (__asan_should_detect_stack_use_after_return() != 0); @@ -219,6 +218,10 @@ extern "C" { } } +extern "C" void __asan_version_mismatch_check() { + // Do nothing. +} + INTERFACE_FUNCTION(__asan_handle_no_return) INTERFACE_FUNCTION(__asan_report_store1) @@ -253,6 +256,9 @@ INTERFACE_FUNCTION(__asan_memcpy); INTERFACE_FUNCTION(__asan_memset); INTERFACE_FUNCTION(__asan_memmove); +INTERFACE_FUNCTION(__asan_alloca_poison); +INTERFACE_FUNCTION(__asan_allocas_unpoison); + INTERFACE_FUNCTION(__asan_register_globals) INTERFACE_FUNCTION(__asan_unregister_globals) @@ -296,6 +302,7 @@ INTERFACE_FUNCTION(__asan_stack_free_10) // FIXME: we might want to have a sanitizer_win_dll_thunk? INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container) +INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address) INTERFACE_FUNCTION(__sanitizer_cov) INTERFACE_FUNCTION(__sanitizer_cov_dump) INTERFACE_FUNCTION(__sanitizer_cov_indir_call16) @@ -304,14 +311,17 @@ INTERFACE_FUNCTION(__sanitizer_cov_module_init) INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block) INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter) INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp) +INTERFACE_FUNCTION(__sanitizer_cov_trace_switch) INTERFACE_FUNCTION(__sanitizer_cov_with_check) INTERFACE_FUNCTION(__sanitizer_get_allocated_size) INTERFACE_FUNCTION(__sanitizer_get_coverage_guards) +INTERFACE_FUNCTION(__sanitizer_get_coverage_pc_buffer) INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes) INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size) INTERFACE_FUNCTION(__sanitizer_get_free_bytes) INTERFACE_FUNCTION(__sanitizer_get_heap_size) INTERFACE_FUNCTION(__sanitizer_get_ownership) +INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs) INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage) INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes) INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file) diff --git a/contrib/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc b/contrib/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc index d59f9f5768a0..73e5207bb334 100644 --- a/contrib/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc +++ b/contrib/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -24,6 +24,7 @@ // Using #ifdef rather than relying on Makefiles etc. // simplifies the build procedure. #ifdef ASAN_DYNAMIC_RUNTIME_THUNK +#define WIN32_LEAN_AND_MEAN #include <windows.h> // First, declare CRT sections we'll be using in this file @@ -58,6 +59,7 @@ int __asan_option_detect_stack_use_after_return = // using atexit() that calls a small subset of C terminators // where LLVM global_dtors is placed. Fingers crossed, no other C terminators // are there. +extern "C" int __cdecl atexit(void (__cdecl *f)(void)); extern "C" void __cdecl _initterm(void *a, void *b); namespace { diff --git a/contrib/compiler-rt/lib/asan/scripts/asan_device_setup b/contrib/compiler-rt/lib/asan/scripts/asan_device_setup deleted file mode 100755 index 104e07b722ca..000000000000 --- a/contrib/compiler-rt/lib/asan/scripts/asan_device_setup +++ /dev/null @@ -1,344 +0,0 @@ -#!/bin/bash -#===- lib/asan/scripts/asan_device_setup -----------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -# Prepare Android device to run ASan applications. -# -#===------------------------------------------------------------------------===# - -set -e - -HERE="$(cd "$(dirname "$0")" && pwd)" - -revert=no -extra_options= -device= -lib= -use_su=0 - -function usage { - echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]" - echo " --revert: Uninstall ASan from the device." - echo " --lib: Path to ASan runtime library." - echo " --extra-options: Extra ASAN_OPTIONS." - echo " --device: Install to the given device. Use 'adb devices' to find" - echo " device-id." - echo " --use-su: Use 'su -c' prefix for every adb command instead of using" - echo " 'adb root' once." - echo - exit 1 -} - -function adb_push { - if [ $use_su -eq 0 ]; then - $ADB push "$1" "$2" - else - local FILENAME=$(basename $1) - $ADB push "$1" "/data/local/tmp/$FILENAME" - $ADB shell su -c "rm \\\"$2/$FILENAME\\\"" >&/dev/null - $ADB shell su -c "cat \\\"/data/local/tmp/$FILENAME\\\" > \\\"$2/$FILENAME\\\"" - $ADB shell su -c "rm \\\"/data/local/tmp/$FILENAME\\\"" - fi -} - -function adb_remount { - if [ $use_su -eq 0 ]; then - $ADB remount - else - local STORAGE=`$ADB shell mount | grep /system | cut -d ' ' -f1` - if [ "$STORAGE" != "" ]; then - echo Remounting $STORAGE at /system - $ADB shell su -c "mount -o remount,rw $STORAGE /system" - else - echo Failed to get storage device name for "/system" mount point - fi - fi -} - -function adb_shell { - if [ $use_su -eq 0 ]; then - $ADB shell $@ - else - $ADB shell su -c "$*" - fi -} - -function adb_root { - if [ $use_su -eq 0 ]; then - $ADB root - fi -} - -function adb_wait_for_device { - $ADB wait-for-device -} - -function adb_pull { - if [ $use_su -eq 0 ]; then - $ADB pull "$1" "$2" - else - local FILENAME=$(basename $1) - $ADB shell rm "/data/local/tmp/$FILENAME" >&/dev/null - $ADB shell su -c "[ -f \\\"$1\\\" ] && cat \\\"$1\\\" > \\\"/data/local/tmp/$FILENAME\\\" && chown root.shell \\\"/data/local/tmp/$FILENAME\\\" && chmod 755 \\\"/data/local/tmp/$FILENAME\\\"" && - $ADB pull "/data/local/tmp/$FILENAME" "$2" >&/dev/null && $ADB shell "rm \"/data/local/tmp/$FILENAME\"" - fi -} - -function get_device_arch { # OUTVAR - local _outvar=$1 - local _ABI=$(adb_shell getprop ro.product.cpu.abi) - local _ARCH= - if [[ $_ABI == x86* ]]; then - _ARCH=i686 - elif [[ $_ABI == armeabi* ]]; then - _ARCH=arm - else - echo "Unrecognized device ABI: $_ABI" - exit 1 - fi - eval $_outvar=\$_ARCH -} - -while [[ $# > 0 ]]; do - case $1 in - --revert) - revert=yes - ;; - --extra-options) - shift - if [[ $# == 0 ]]; then - echo "--extra-options requires an argument." - exit 1 - fi - extra_options="$1" - ;; - --lib) - shift - if [[ $# == 0 ]]; then - echo "--lib requires an argument." - exit 1 - fi - lib="$1" - ;; - --device) - shift - if [[ $# == 0 ]]; then - echo "--device requires an argument." - exit 1 - fi - device="$1" - ;; - --use-su) - use_su=1 - ;; - *) - usage - ;; - esac - shift -done - -ADB=${ADB:-adb} -if [[ x$device != x ]]; then - ADB="$ADB -s $device" -fi - -if [ $use_su -eq 1 ]; then - # Test if 'su' is present on the device - SU_TEST_OUT=`$ADB shell su -c "echo foo" 2>&1 | sed 's/\r$//'` - if [ $? != 0 -o "$SU_TEST_OUT" != "foo" ]; then - echo "ERROR: Cannot use 'su -c':" - echo "$ adb shell su -c \"echo foo\"" - echo $SU_TEST_OUT - echo "Check that 'su' binary is correctly installed on the device or omit" - echo " --use-su flag" - exit 1 - fi -fi - -echo '>> Remounting /system rw' -adb_wait_for_device -adb_root -adb_wait_for_device -adb_remount -adb_wait_for_device - -get_device_arch ARCH -echo "Target architecture: $ARCH" -ASAN_RT="libclang_rt.asan-$ARCH-android.so" - -if [[ x$revert == xyes ]]; then - echo '>> Uninstalling ASan' - - if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then - echo '>> Pre-L device detected.' - adb_shell mv /system/bin/app_process.real /system/bin/app_process - adb_shell rm /system/bin/asanwrapper - else - adb_shell rm /system/bin/app_process.wrap - adb_shell rm /system/bin/asanwrapper - adb_shell rm /system/bin/app_process - adb_shell ln -s /system/bin/app_process32 /system/bin/app_process - fi - - echo '>> Restarting shell' - adb_shell stop - adb_shell start - - # Remove the library on the last step to give a chance to the 'su' binary to - # be executed without problem. - adb_shell rm /system/lib/$ASAN_RT - - echo '>> Done' - exit 0 -fi - -if [[ -d "$lib" ]]; then - ASAN_RT_PATH="$lib" -elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then - ASAN_RT_PATH=$(dirname "$lib") -elif [[ -f "$HERE/$ASAN_RT" ]]; then - ASAN_RT_PATH="$HERE" -elif [[ $(basename "$HERE") == "bin" ]]; then - # We could be in the toolchain's base directory. - # Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/linux. - P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../lib/linux/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1) - if [[ -n "$P" ]]; then - ASAN_RT_PATH="$(dirname "$P")" - fi -fi - -if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then - echo ">> ASan runtime library not found" - exit 1 -fi - -TMPDIRBASE=$(mktemp -d) -TMPDIROLD="$TMPDIRBASE/old" -TMPDIR="$TMPDIRBASE/new" -mkdir "$TMPDIROLD" - -RELEASE=$(adb_shell getprop ro.build.version.release) -PRE_L=0 -if echo "$RELEASE" | grep '^4\.' >&/dev/null; then - PRE_L=1 -fi - -if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then - - if adb_pull /system/bin/app_process.real /dev/null >&/dev/null; then - echo '>> Old-style ASan installation detected. Reverting.' - adb_shell mv /system/bin/app_process.real /system/bin/app_process - fi - - echo '>> Pre-L device detected. Setting up app_process symlink.' - adb_shell mv /system/bin/app_process /system/bin/app_process32 - adb_shell ln -s /system/bin/app_process32 /system/bin/app_process -fi - -echo '>> Copying files from the device' -adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true -adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true -adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true -cp -r "$TMPDIROLD" "$TMPDIR" - -if [[ -f "$TMPDIR/app_process.wrap" ]]; then - echo ">> Previous installation detected" -else - echo ">> New installation" -fi - -echo '>> Generating wrappers' - -cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/" - -# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup, -# which may or may not be a real bug (probably not). -ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0 - -# On Android-L not allowing user segv handler breaks some applications. -if [[ PRE_L -eq 0 ]]; then - ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1" -fi - -if [[ x$extra_options != x ]] ; then - ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" -fi - -# Zygote wrapper. -cat <<EOF >"$TMPDIR/app_process.wrap" -#!/system/bin/sh-from-zygote -ASAN_OPTIONS=$ASAN_OPTIONS \\ -LD_PRELOAD=\$LD_PRELOAD:$ASAN_RT \\ -exec /system/bin/app_process32 \$@ - -EOF - -# General command-line tool wrapper (use for anything that's not started as -# zygote). -cat <<EOF >"$TMPDIR/asanwrapper" -#!/system/bin/sh -LD_PRELOAD=$ASAN_RT \\ -exec \$@ - -EOF - -if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then - echo '>> Pushing files to the device' - adb_push "$TMPDIR/$ASAN_RT" /system/lib/ - adb_push "$TMPDIR/app_process.wrap" /system/bin - adb_push "$TMPDIR/asanwrapper" /system/bin - - adb_shell rm /system/bin/app_process - adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process - - adb_shell chown root.shell \ - /system/lib/"$ASAN_RT" \ - /system/bin/app_process.wrap \ - /system/bin/asanwrapper - adb_shell chmod 644 \ - /system/lib/"$ASAN_RT" - adb_shell chmod 755 \ - /system/bin/app_process.wrap \ - /system/bin/asanwrapper - - # Make SELinux happy by keeping app_process wrapper and the shell - # it runs on in zygote domain. - ENFORCING=0 - if adb_shell getenforce | grep Enforcing >/dev/null; then - # Sometimes shell is not allowed to change file contexts. - # Temporarily switch to permissive. - ENFORCING=1 - adb_shell setenforce 0 - fi - - adb_shell cp /system/bin/sh /system/bin/sh-from-zygote - - if [[ PRE_L -eq 1 ]]; then - CTX=u:object_r:system_file:s0 - else - CTX=u:object_r:zygote_exec:s0 - fi - adb_shell chcon $CTX \ - /system/bin/sh-from-zygote \ - /system/bin/app_process.wrap \ - /system/bin/app_process32 - - if [ $ENFORCING == 1 ]; then - adb_shell setenforce 1 - fi - - echo '>> Restarting shell (asynchronous)' - adb_shell stop - adb_shell start - - echo '>> Please wait until the device restarts' -else - echo '>> Device is up to date' -fi - -rm -r "$TMPDIRBASE" diff --git a/contrib/compiler-rt/lib/asan/scripts/asan_symbolize.py b/contrib/compiler-rt/lib/asan/scripts/asan_symbolize.py deleted file mode 100755 index b9d3ad3ad2fe..000000000000 --- a/contrib/compiler-rt/lib/asan/scripts/asan_symbolize.py +++ /dev/null @@ -1,482 +0,0 @@ -#!/usr/bin/env python -#===- lib/asan/scripts/asan_symbolize.py -----------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -import argparse -import bisect -import getopt -import os -import re -import subprocess -import sys - -symbolizers = {} -DEBUG = False -demangle = False -binutils_prefix = None -sysroot_path = None -binary_name_filter = None -fix_filename_patterns = None -logfile = sys.stdin -allow_system_symbolizer = True - -# FIXME: merge the code that calls fix_filename(). -def fix_filename(file_name): - if fix_filename_patterns: - for path_to_cut in fix_filename_patterns: - file_name = re.sub('.*' + path_to_cut, '', file_name) - file_name = re.sub('.*asan_[a-z_]*.cc:[0-9]*', '_asan_rtl_', file_name) - file_name = re.sub('.*crtstuff.c:0', '???:0', file_name) - return file_name - -def sysroot_path_filter(binary_name): - return sysroot_path + binary_name - -def guess_arch(addr): - # Guess which arch we're running. 10 = len('0x') + 8 hex digits. - if len(addr) > 10: - return 'x86_64' - else: - return 'i386' - -class Symbolizer(object): - def __init__(self): - pass - - def symbolize(self, addr, binary, offset): - """Symbolize the given address (pair of binary and offset). - - Overriden in subclasses. - Args: - addr: virtual address of an instruction. - binary: path to executable/shared object containing this instruction. - offset: instruction offset in the @binary. - Returns: - list of strings (one string for each inlined frame) describing - the code locations for this instruction (that is, function name, file - name, line and column numbers). - """ - return None - - -class LLVMSymbolizer(Symbolizer): - def __init__(self, symbolizer_path, default_arch, system, dsym_hints=[]): - super(LLVMSymbolizer, self).__init__() - self.symbolizer_path = symbolizer_path - self.default_arch = default_arch - self.system = system - self.dsym_hints = dsym_hints - self.pipe = self.open_llvm_symbolizer() - - def open_llvm_symbolizer(self): - cmd = [self.symbolizer_path, - '--use-symbol-table=true', - '--demangle=%s' % demangle, - '--functions=short', - '--inlining=true', - '--default-arch=%s' % self.default_arch] - if self.system == 'Darwin': - for hint in self.dsym_hints: - cmd.append('--dsym-hint=%s' % hint) - if DEBUG: - print ' '.join(cmd) - try: - result = subprocess.Popen(cmd, stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - except OSError: - result = None - return result - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - if not self.pipe: - return None - result = [] - try: - symbolizer_input = '"%s" %s' % (binary, offset) - if DEBUG: - print symbolizer_input - print >> self.pipe.stdin, symbolizer_input - while True: - function_name = self.pipe.stdout.readline().rstrip() - if not function_name: - break - file_name = self.pipe.stdout.readline().rstrip() - file_name = fix_filename(file_name) - if (not function_name.startswith('??') or - not file_name.startswith('??')): - # Append only non-trivial frames. - result.append('%s in %s %s' % (addr, function_name, - file_name)) - except Exception: - result = [] - if not result: - result = None - return result - - -def LLVMSymbolizerFactory(system, default_arch, dsym_hints=[]): - symbolizer_path = os.getenv('LLVM_SYMBOLIZER_PATH') - if not symbolizer_path: - symbolizer_path = os.getenv('ASAN_SYMBOLIZER_PATH') - if not symbolizer_path: - # Assume llvm-symbolizer is in PATH. - symbolizer_path = 'llvm-symbolizer' - return LLVMSymbolizer(symbolizer_path, default_arch, system, dsym_hints) - - -class Addr2LineSymbolizer(Symbolizer): - def __init__(self, binary): - super(Addr2LineSymbolizer, self).__init__() - self.binary = binary - self.pipe = self.open_addr2line() - - def open_addr2line(self): - addr2line_tool = 'addr2line' - if binutils_prefix: - addr2line_tool = binutils_prefix + addr2line_tool - cmd = [addr2line_tool, '-f'] - if demangle: - cmd += ['--demangle'] - cmd += ['-e', self.binary] - if DEBUG: - print ' '.join(cmd) - return subprocess.Popen(cmd, - stdin=subprocess.PIPE, stdout=subprocess.PIPE) - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - if self.binary != binary: - return None - try: - print >> self.pipe.stdin, offset - function_name = self.pipe.stdout.readline().rstrip() - file_name = self.pipe.stdout.readline().rstrip() - except Exception: - function_name = '' - file_name = '' - file_name = fix_filename(file_name) - return ['%s in %s %s' % (addr, function_name, file_name)] - - -class UnbufferedLineConverter(object): - """ - Wrap a child process that responds to each line of input with one line of - output. Uses pty to trick the child into providing unbuffered output. - """ - def __init__(self, args, close_stderr=False): - # Local imports so that the script can start on Windows. - import pty - import termios - pid, fd = pty.fork() - if pid == 0: - # We're the child. Transfer control to command. - if close_stderr: - dev_null = os.open('/dev/null', 0) - os.dup2(dev_null, 2) - os.execvp(args[0], args) - else: - # Disable echoing. - attr = termios.tcgetattr(fd) - attr[3] = attr[3] & ~termios.ECHO - termios.tcsetattr(fd, termios.TCSANOW, attr) - # Set up a file()-like interface to the child process - self.r = os.fdopen(fd, "r", 1) - self.w = os.fdopen(os.dup(fd), "w", 1) - - def convert(self, line): - self.w.write(line + "\n") - return self.readline() - - def readline(self): - return self.r.readline().rstrip() - - -class DarwinSymbolizer(Symbolizer): - def __init__(self, addr, binary): - super(DarwinSymbolizer, self).__init__() - self.binary = binary - self.arch = guess_arch(addr) - self.open_atos() - - def open_atos(self): - if DEBUG: - print 'atos -o %s -arch %s' % (self.binary, self.arch) - cmdline = ['atos', '-o', self.binary, '-arch', self.arch] - self.atos = UnbufferedLineConverter(cmdline, close_stderr=True) - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - if self.binary != binary: - return None - atos_line = self.atos.convert('0x%x' % int(offset, 16)) - while "got symbolicator for" in atos_line: - atos_line = self.atos.readline() - # A well-formed atos response looks like this: - # foo(type1, type2) (in object.name) (filename.cc:80) - match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line) - if DEBUG: - print 'atos_line: ', atos_line - if match: - function_name = match.group(1) - function_name = re.sub('\(.*?\)', '', function_name) - file_name = fix_filename(match.group(3)) - return ['%s in %s %s' % (addr, function_name, file_name)] - else: - return ['%s in %s' % (addr, atos_line)] - - -# Chain several symbolizers so that if one symbolizer fails, we fall back -# to the next symbolizer in chain. -class ChainSymbolizer(Symbolizer): - def __init__(self, symbolizer_list): - super(ChainSymbolizer, self).__init__() - self.symbolizer_list = symbolizer_list - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - for symbolizer in self.symbolizer_list: - if symbolizer: - result = symbolizer.symbolize(addr, binary, offset) - if result: - return result - return None - - def append_symbolizer(self, symbolizer): - self.symbolizer_list.append(symbolizer) - - -def BreakpadSymbolizerFactory(binary): - suffix = os.getenv('BREAKPAD_SUFFIX') - if suffix: - filename = binary + suffix - if os.access(filename, os.F_OK): - return BreakpadSymbolizer(filename) - return None - - -def SystemSymbolizerFactory(system, addr, binary): - if system == 'Darwin': - return DarwinSymbolizer(addr, binary) - elif system == 'Linux': - return Addr2LineSymbolizer(binary) - - -class BreakpadSymbolizer(Symbolizer): - def __init__(self, filename): - super(BreakpadSymbolizer, self).__init__() - self.filename = filename - lines = file(filename).readlines() - self.files = [] - self.symbols = {} - self.address_list = [] - self.addresses = {} - # MODULE mac x86_64 A7001116478B33F18FF9BEDE9F615F190 t - fragments = lines[0].rstrip().split() - self.arch = fragments[2] - self.debug_id = fragments[3] - self.binary = ' '.join(fragments[4:]) - self.parse_lines(lines[1:]) - - def parse_lines(self, lines): - cur_function_addr = '' - for line in lines: - fragments = line.split() - if fragments[0] == 'FILE': - assert int(fragments[1]) == len(self.files) - self.files.append(' '.join(fragments[2:])) - elif fragments[0] == 'PUBLIC': - self.symbols[int(fragments[1], 16)] = ' '.join(fragments[3:]) - elif fragments[0] in ['CFI', 'STACK']: - pass - elif fragments[0] == 'FUNC': - cur_function_addr = int(fragments[1], 16) - if not cur_function_addr in self.symbols.keys(): - self.symbols[cur_function_addr] = ' '.join(fragments[4:]) - else: - # Line starting with an address. - addr = int(fragments[0], 16) - self.address_list.append(addr) - # Tuple of symbol address, size, line, file number. - self.addresses[addr] = (cur_function_addr, - int(fragments[1], 16), - int(fragments[2]), - int(fragments[3])) - self.address_list.sort() - - def get_sym_file_line(self, addr): - key = None - if addr in self.addresses.keys(): - key = addr - else: - index = bisect.bisect_left(self.address_list, addr) - if index == 0: - return None - else: - key = self.address_list[index - 1] - sym_id, size, line_no, file_no = self.addresses[key] - symbol = self.symbols[sym_id] - filename = self.files[file_no] - if addr < key + size: - return symbol, filename, line_no - else: - return None - - def symbolize(self, addr, binary, offset): - if self.binary != binary: - return None - res = self.get_sym_file_line(int(offset, 16)) - if res: - function_name, file_name, line_no = res - result = ['%s in %s %s:%d' % ( - addr, function_name, file_name, line_no)] - print result - return result - else: - return None - - -class SymbolizationLoop(object): - def __init__(self, binary_name_filter=None, dsym_hint_producer=None): - if sys.platform == 'win32': - # ASan on Windows uses dbghelp.dll to symbolize in-process, which works - # even in sandboxed processes. Nothing needs to be done here. - self.process_line = self.process_line_echo - else: - # Used by clients who may want to supply a different binary name. - # E.g. in Chrome several binaries may share a single .dSYM. - self.binary_name_filter = binary_name_filter - self.dsym_hint_producer = dsym_hint_producer - self.system = os.uname()[0] - if self.system not in ['Linux', 'Darwin', 'FreeBSD']: - raise Exception('Unknown system') - self.llvm_symbolizers = {} - self.last_llvm_symbolizer = None - self.dsym_hints = set([]) - self.frame_no = 0 - self.process_line = self.process_line_posix - - def symbolize_address(self, addr, binary, offset): - # On non-Darwin (i.e. on platforms without .dSYM debug info) always use - # a single symbolizer binary. - # On Darwin, if the dsym hint producer is present: - # 1. check whether we've seen this binary already; if so, - # use |llvm_symbolizers[binary]|, which has already loaded the debug - # info for this binary (might not be the case for - # |last_llvm_symbolizer|); - # 2. otherwise check if we've seen all the hints for this binary already; - # if so, reuse |last_llvm_symbolizer| which has the full set of hints; - # 3. otherwise create a new symbolizer and pass all currently known - # .dSYM hints to it. - if not binary in self.llvm_symbolizers: - use_new_symbolizer = True - if self.system == 'Darwin' and self.dsym_hint_producer: - dsym_hints_for_binary = set(self.dsym_hint_producer(binary)) - use_new_symbolizer = bool(dsym_hints_for_binary - self.dsym_hints) - self.dsym_hints |= dsym_hints_for_binary - if self.last_llvm_symbolizer and not use_new_symbolizer: - self.llvm_symbolizers[binary] = self.last_llvm_symbolizer - else: - self.last_llvm_symbolizer = LLVMSymbolizerFactory( - self.system, guess_arch(addr), self.dsym_hints) - self.llvm_symbolizers[binary] = self.last_llvm_symbolizer - # Use the chain of symbolizers: - # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos - # (fall back to next symbolizer if the previous one fails). - if not binary in symbolizers: - symbolizers[binary] = ChainSymbolizer( - [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]]) - result = symbolizers[binary].symbolize(addr, binary, offset) - if result is None: - if not allow_system_symbolizer: - raise Exception('Failed to launch or use llvm-symbolizer.') - # Initialize system symbolizer only if other symbolizers failed. - symbolizers[binary].append_symbolizer( - SystemSymbolizerFactory(self.system, addr, binary)) - result = symbolizers[binary].symbolize(addr, binary, offset) - # The system symbolizer must produce some result. - assert result - return result - - def get_symbolized_lines(self, symbolized_lines): - if not symbolized_lines: - return [self.current_line] - else: - result = [] - for symbolized_frame in symbolized_lines: - result.append(' #%s %s' % (str(self.frame_no), symbolized_frame.rstrip())) - self.frame_no += 1 - return result - - def process_logfile(self): - self.frame_no = 0 - for line in logfile: - processed = self.process_line(line) - print '\n'.join(processed) - - def process_line_echo(self, line): - return [line.rstrip()] - - def process_line_posix(self, line): - self.current_line = line.rstrip() - #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) - stack_trace_line_format = ( - '^( *#([0-9]+) *)(0x[0-9a-f]+) *\((.*)\+(0x[0-9a-f]+)\)') - match = re.match(stack_trace_line_format, line) - if not match: - return [self.current_line] - if DEBUG: - print line - _, frameno_str, addr, binary, offset = match.groups() - if frameno_str == '0': - # Assume that frame #0 is the first frame of new stack trace. - self.frame_no = 0 - original_binary = binary - if self.binary_name_filter: - binary = self.binary_name_filter(binary) - symbolized_line = self.symbolize_address(addr, binary, offset) - if not symbolized_line: - if original_binary != binary: - symbolized_line = self.symbolize_address(addr, binary, offset) - return self.get_symbolized_lines(symbolized_line) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description='ASan symbolization script', - epilog='Example of use:\n' - 'asan_symbolize.py -c "$HOME/opt/cross/bin/arm-linux-gnueabi-" ' - '-s "$HOME/SymbolFiles" < asan.log') - parser.add_argument('path_to_cut', nargs='*', - help='pattern to be cut from the result file path ') - parser.add_argument('-d','--demangle', action='store_true', - help='demangle function names') - parser.add_argument('-s', metavar='SYSROOT', - help='set path to sysroot for sanitized binaries') - parser.add_argument('-c', metavar='CROSS_COMPILE', - help='set prefix for binutils') - parser.add_argument('-l','--logfile', default=sys.stdin, - type=argparse.FileType('r'), - help='set log file name to parse, default is stdin') - args = parser.parse_args() - if args.path_to_cut: - fix_filename_patterns = args.path_to_cut - if args.demangle: - demangle = True - if args.s: - binary_name_filter = sysroot_path_filter - sysroot_path = args.s - if args.c: - binutils_prefix = args.c - if args.logfile: - logfile = args.logfile - else: - logfile = sys.stdin - loop = SymbolizationLoop(binary_name_filter) - loop.process_logfile() diff --git a/contrib/compiler-rt/lib/asan/tests/asan_asm_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_asm_test.cc deleted file mode 100644 index 200de2c137a5..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_asm_test.cc +++ /dev/null @@ -1,267 +0,0 @@ -//===-- asan_asm_test.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -#if defined(__linux__) - -#if defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#include <emmintrin.h> - -namespace { - -template<typename T> void asm_write(T *ptr, T val); -template<typename T> T asm_read(T *ptr); -template<typename T> void asm_rep_movs(T *dst, T *src, size_t n); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#if defined(__x86_64__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write<Type>(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read<Type>(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> void asm_rep_movs<Type>(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : \ - : "D"(dst), "S"(src), "c"(size) \ - : "rsi", "rdi", "rcx", "memory"); \ - } - -DECLARE_ASM_WRITE(U8, "8", "movq", "r"); -DECLARE_ASM_READ(U8, "8", "movq", "=r"); -DECLARE_ASM_REP_MOVS(U8, "movsq"); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) - -#if defined(__i386__) && defined(__SSE2__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write<Type>(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read<Type>(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> void asm_rep_movs<Type>(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : \ - : "D"(dst), "S"(src), "c"(size) \ - : "esi", "edi", "ecx", "memory"); \ - } - -} // End of anonymous namespace - -#endif // defined(__i386__) && defined(__SSE2__) - -#if defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -namespace { - -DECLARE_ASM_WRITE(U1, "1", "movb", "r"); -DECLARE_ASM_WRITE(U2, "2", "movw", "r"); -DECLARE_ASM_WRITE(U4, "4", "movl", "r"); -DECLARE_ASM_WRITE(__m128i, "16", "movaps", "x"); - -DECLARE_ASM_READ(U1, "1", "movb", "=r"); -DECLARE_ASM_READ(U2, "2", "movw", "=r"); -DECLARE_ASM_READ(U4, "4", "movl", "=r"); -DECLARE_ASM_READ(__m128i, "16", "movaps", "=x"); - -DECLARE_ASM_REP_MOVS(U1, "movsb"); -DECLARE_ASM_REP_MOVS(U2, "movsw"); -DECLARE_ASM_REP_MOVS(U4, "movsl"); - -template<typename T> void TestAsmWrite(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_write(&buf[1], static_cast<T>(0)), DeathPattern); - T var = 0x12; - asm_write(&var, static_cast<T>(0x21)); - ASSERT_EQ(static_cast<T>(0x21), var); - delete buf; -} - -template<> void TestAsmWrite<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - __m128i val = _mm_set1_epi16(0x1234); - EXPECT_DEATH(asm_write<__m128i>((__m128i*) p, val), DeathPattern); - __m128i var = _mm_set1_epi16(0x4321); - asm_write(&var, val); - ASSERT_EQ(0x1234, _mm_extract_epi16(var, 0)); - delete [] buf; -} - -template<typename T> void TestAsmRead(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_read(&buf[1]), DeathPattern); - T var = 0x12; - ASSERT_EQ(static_cast<T>(0x12), asm_read(&var)); - delete buf; -} - -template<> void TestAsmRead<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - EXPECT_DEATH(asm_read<__m128i>((__m128i*) p), DeathPattern); - __m128i val = _mm_set1_epi16(0x1234); - ASSERT_EQ(0x1234, _mm_extract_epi16(asm_read(&val), 0)); - delete [] buf; -} - -U4 AsmLoad(U4 *a) { - U4 r; - __asm__("movl (%[a]), %[r] \n\t" : [r] "=r" (r) : [a] "r" (a) : "memory"); - return r; -} - -void AsmStore(U4 r, U4 *a) { - __asm__("movl %[r], (%[a]) \n\t" : : [a] "r" (a), [r] "r" (r) : "memory"); -} - -template <typename T> -void TestAsmRepMovs(const char *DeathPatternRead, - const char *DeathPatternWrite) { - T src_good[4] = { 0x0, 0x1, 0x2, 0x3 }; - T dst_good[4] = {}; - asm_rep_movs(dst_good, src_good, 4); - ASSERT_EQ(static_cast<T>(0x0), dst_good[0]); - ASSERT_EQ(static_cast<T>(0x1), dst_good[1]); - ASSERT_EQ(static_cast<T>(0x2), dst_good[2]); - ASSERT_EQ(static_cast<T>(0x3), dst_good[3]); - - T dst_bad[3]; - EXPECT_DEATH(asm_rep_movs(dst_bad, src_good, 4), DeathPatternWrite); - - T src_bad[3] = { 0x0, 0x1, 0x2 }; - EXPECT_DEATH(asm_rep_movs(dst_good, src_bad, 4), DeathPatternRead); - - T* dp = dst_bad + 4; - T* sp = src_bad + 4; - asm_rep_movs(dp, sp, 0); -} - -} // End of anonymous namespace - -TEST(AddressSanitizer, asm_load_store) { - U4* buf = new U4[2]; - EXPECT_DEATH(AsmLoad(&buf[3]), "READ of size 4"); - EXPECT_DEATH(AsmStore(0x1234, &buf[3]), "WRITE of size 4"); - delete [] buf; -} - -TEST(AddressSanitizer, asm_rw) { - TestAsmWrite<U1>("WRITE of size 1"); - TestAsmWrite<U2>("WRITE of size 2"); - TestAsmWrite<U4>("WRITE of size 4"); -#if defined(__x86_64__) - TestAsmWrite<U8>("WRITE of size 8"); -#endif // defined(__x86_64__) - TestAsmWrite<__m128i>("WRITE of size 16"); - - TestAsmRead<U1>("READ of size 1"); - TestAsmRead<U2>("READ of size 2"); - TestAsmRead<U4>("READ of size 4"); -#if defined(__x86_64__) - TestAsmRead<U8>("READ of size 8"); -#endif // defined(__x86_64__) - TestAsmRead<__m128i>("READ of size 16"); -} - -TEST(AddressSanitizer, asm_flags) { - long magic = 0x1234; - long r = 0x0; - -#if defined(__x86_64__) && !defined(__ILP32__) - __asm__("xorq %%rax, %%rax \n\t" - "movq (%[p]), %%rax \n\t" - "sete %%al \n\t" - "movzbq %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "rax", "memory"); -#else - __asm__("xorl %%eax, %%eax \n\t" - "movl (%[p]), %%eax \n\t" - "sete %%al \n\t" - "movzbl %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "eax", "memory"); -#endif // defined(__x86_64__) && !defined(__ILP32__) - - ASSERT_EQ(0x1, r); -} - -TEST(AddressSanitizer, asm_rep_movs) { - TestAsmRepMovs<U1>("READ of size 1", "WRITE of size 1"); - TestAsmRepMovs<U2>("READ of size 2", "WRITE of size 2"); - TestAsmRepMovs<U4>("READ of size 4", "WRITE of size 4"); -#if defined(__x86_64__) - TestAsmRepMovs<U8>("READ of size 8", "WRITE of size 8"); -#endif // defined(__x86_64__) -} - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#endif // defined(__linux__) diff --git a/contrib/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc deleted file mode 100644 index fc522de475fa..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_benchmarks_test.cc +++ /dev/null @@ -1,85 +0,0 @@ -//===-- asan_benchmarks_test.cc ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Some benchmarks for the instrumented code. -//===----------------------------------------------------------------------===// - -#include "asan_test_utils.h" - -template<class T> -__attribute__((noinline)) -static void ManyAccessFunc(T *x, size_t n_elements, size_t n_iter) { - for (size_t iter = 0; iter < n_iter; iter++) { - break_optimization(0); - // hand unroll the loop to stress the reg alloc. - for (size_t i = 0; i <= n_elements - 16; i += 16) { - x[i + 0] = i; - x[i + 1] = i; - x[i + 2] = i; - x[i + 3] = i; - x[i + 4] = i; - x[i + 5] = i; - x[i + 6] = i; - x[i + 7] = i; - x[i + 8] = i; - x[i + 9] = i; - x[i + 10] = i; - x[i + 11] = i; - x[i + 12] = i; - x[i + 13] = i; - x[i + 14] = i; - x[i + 15] = i; - } - } -} - -TEST(AddressSanitizer, ManyAccessBenchmark) { - size_t kLen = 1024; - int *int_array = new int[kLen]; - ManyAccessFunc(int_array, kLen, 1 << 24); - delete [] int_array; -} - -// access 7 char elements in a 7 byte array (i.e. on the border). -__attribute__((noinline)) -static void BorderAccessFunc(char *x, size_t n_iter) { - for (size_t iter = 0; iter < n_iter; iter++) { - break_optimization(x); - x[0] = 0; - x[1] = 0; - x[2] = 0; - x[3] = 0; - x[4] = 0; - x[5] = 0; - x[6] = 0; - } -} - -TEST(AddressSanitizer, BorderAccessBenchmark) { - char *char_7_array = new char[7]; - BorderAccessFunc(char_7_array, 1 << 30); - delete [] char_7_array; -} - -static void FunctionWithLargeStack() { - int stack[1000]; - Ident(stack); -} - -TEST(AddressSanitizer, FakeStackBenchmark) { - for (int i = 0; i < 10000000; i++) - Ident(&FunctionWithLargeStack)(); -} - -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_exceptions_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_exceptions_test.cc deleted file mode 100644 index ecd406de7561..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_exceptions_test.cc +++ /dev/null @@ -1,27 +0,0 @@ -// See http://llvm.org/bugs/show_bug.cgi?id=11468 -#include <stdio.h> -#include <string> - -class Action { - public: - Action() {} - void PrintString(const std::string& msg) const { - fprintf(stderr, "%s\n", msg.c_str()); - } - void Throw(const char& arg) const { - PrintString("PrintString called!"); // this line is important - throw arg; - } -}; - -int main() { - const Action a; - fprintf(stderr, "&a before = %p\n", &a); - try { - a.Throw('c'); - } catch(const char&) { - fprintf(stderr, "&a in catch = %p\n", &a); - } - fprintf(stderr, "&a final = %p\n", &a); - return 0; -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc deleted file mode 100644 index 516142f0c3b7..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_fake_stack_test.cc +++ /dev/null @@ -1,152 +0,0 @@ -//===-- asan_fake_stack_test.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Tests for FakeStack. -// This test file should be compiled w/o asan instrumentation. -//===----------------------------------------------------------------------===// - -#include "asan_fake_stack.h" -#include "asan_test_utils.h" -#include "sanitizer_common/sanitizer_common.h" - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> - -#include <map> - -namespace __asan { - -TEST(FakeStack, FlagsSize) { - EXPECT_EQ(FakeStack::SizeRequiredForFlags(10), 1U << 5); - EXPECT_EQ(FakeStack::SizeRequiredForFlags(11), 1U << 6); - EXPECT_EQ(FakeStack::SizeRequiredForFlags(20), 1U << 15); -} - -TEST(FakeStack, RequiredSize) { - // for (int i = 15; i < 20; i++) { - // uptr alloc_size = FakeStack::RequiredSize(i); - // printf("%zdK ==> %zd\n", 1 << (i - 10), alloc_size); - // } - EXPECT_EQ(FakeStack::RequiredSize(15), 365568U); - EXPECT_EQ(FakeStack::RequiredSize(16), 727040U); - EXPECT_EQ(FakeStack::RequiredSize(17), 1449984U); - EXPECT_EQ(FakeStack::RequiredSize(18), 2895872U); - EXPECT_EQ(FakeStack::RequiredSize(19), 5787648U); -} - -TEST(FakeStack, FlagsOffset) { - for (uptr stack_size_log = 15; stack_size_log <= 20; stack_size_log++) { - uptr stack_size = 1UL << stack_size_log; - uptr offset = 0; - for (uptr class_id = 0; class_id < FakeStack::kNumberOfSizeClasses; - class_id++) { - uptr frame_size = FakeStack::BytesInSizeClass(class_id); - uptr num_flags = stack_size / frame_size; - EXPECT_EQ(offset, FakeStack::FlagsOffset(stack_size_log, class_id)); - // printf("%zd: %zd => %zd %zd\n", stack_size_log, class_id, offset, - // FakeStack::FlagsOffset(stack_size_log, class_id)); - offset += num_flags; - } - } -} - -#if !defined(_WIN32) // FIXME: Fails due to OOM on Windows. -TEST(FakeStack, CreateDestroy) { - for (int i = 0; i < 1000; i++) { - for (uptr stack_size_log = 20; stack_size_log <= 22; stack_size_log++) { - FakeStack *fake_stack = FakeStack::Create(stack_size_log); - fake_stack->Destroy(0); - } - } -} -#endif - -TEST(FakeStack, ModuloNumberOfFrames) { - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, 0), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<15)), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<10)), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<9)), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<8)), 1U<<8); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<15) + 1), 1U); - - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 0), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<9), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<8), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<7), 1U<<7); - - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 0), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 1), 1U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 15), 15U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 16), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 17), 1U); -} - -TEST(FakeStack, GetFrame) { - const uptr stack_size_log = 20; - const uptr stack_size = 1 << stack_size_log; - FakeStack *fs = FakeStack::Create(stack_size_log); - u8 *base = fs->GetFrame(stack_size_log, 0, 0); - EXPECT_EQ(base, reinterpret_cast<u8 *>(fs) + - fs->SizeRequiredForFlags(stack_size_log) + 4096); - EXPECT_EQ(base + 0*stack_size + 64 * 7, fs->GetFrame(stack_size_log, 0, 7U)); - EXPECT_EQ(base + 1*stack_size + 128 * 3, fs->GetFrame(stack_size_log, 1, 3U)); - EXPECT_EQ(base + 2*stack_size + 256 * 5, fs->GetFrame(stack_size_log, 2, 5U)); - fs->Destroy(0); -} - -TEST(FakeStack, Allocate) { - const uptr stack_size_log = 19; - FakeStack *fs = FakeStack::Create(stack_size_log); - std::map<FakeFrame *, uptr> s; - for (int iter = 0; iter < 2; iter++) { - s.clear(); - for (uptr cid = 0; cid < FakeStack::kNumberOfSizeClasses; cid++) { - uptr n = FakeStack::NumberOfFrames(stack_size_log, cid); - uptr bytes_in_class = FakeStack::BytesInSizeClass(cid); - for (uptr j = 0; j < n; j++) { - FakeFrame *ff = fs->Allocate(stack_size_log, cid, 0); - uptr x = reinterpret_cast<uptr>(ff); - EXPECT_TRUE(s.insert(std::make_pair(ff, cid)).second); - EXPECT_EQ(x, fs->AddrIsInFakeStack(x)); - EXPECT_EQ(x, fs->AddrIsInFakeStack(x + 1)); - EXPECT_EQ(x, fs->AddrIsInFakeStack(x + bytes_in_class - 1)); - EXPECT_NE(x, fs->AddrIsInFakeStack(x + bytes_in_class)); - } - // We are out of fake stack, so Allocate should return 0. - EXPECT_EQ(0UL, fs->Allocate(stack_size_log, cid, 0)); - } - for (std::map<FakeFrame *, uptr>::iterator it = s.begin(); it != s.end(); - ++it) { - fs->Deallocate(reinterpret_cast<uptr>(it->first), it->second); - } - } - fs->Destroy(0); -} - -static void RecursiveFunction(FakeStack *fs, int depth) { - uptr class_id = depth / 3; - FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, 0); - if (depth) { - RecursiveFunction(fs, depth - 1); - RecursiveFunction(fs, depth - 1); - } - fs->Deallocate(reinterpret_cast<uptr>(ff), class_id); -} - -TEST(FakeStack, RecursiveStressTest) { - const uptr stack_size_log = 16; - FakeStack *fs = FakeStack::Create(stack_size_log); - RecursiveFunction(fs, 22); // with 26 runs for 2-3 seconds. - fs->Destroy(0); -} - -} // namespace __asan diff --git a/contrib/compiler-rt/lib/asan/tests/asan_globals_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_globals_test.cc deleted file mode 100644 index 5042ef07378d..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_globals_test.cc +++ /dev/null @@ -1,45 +0,0 @@ -//===-- asan_globals_test.cc ----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Some globals in a separate file. -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -char glob1[1]; -char glob2[2]; -char glob3[3]; -char glob4[4]; -char glob5[5]; -char glob6[6]; -char glob7[7]; -char glob8[8]; -char glob9[9]; -char glob10[10]; -char glob11[11]; -char glob12[12]; -char glob13[13]; -char glob14[14]; -char glob15[15]; -char glob16[16]; -char glob17[17]; -char glob1000[1000]; -char glob10000[10000]; -char glob100000[100000]; - -static char static10[10]; - -int GlobalsTest(int zero) { - static char func_static15[15]; - glob5[zero] = 0; - static10[zero] = 0; - func_static15[zero] = 0; - return glob5[1] + func_static15[2]; -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_interface_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_interface_test.cc deleted file mode 100644 index a34c8528eae0..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_interface_test.cc +++ /dev/null @@ -1,433 +0,0 @@ -//===-- asan_interface_test.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" -#include <sanitizer/allocator_interface.h> -#include <sanitizer/asan_interface.h> - -TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) { - EXPECT_EQ(0U, __sanitizer_get_estimated_allocated_size(0)); - const size_t sizes[] = { 1, 30, 1<<30 }; - for (size_t i = 0; i < 3; i++) { - EXPECT_EQ(sizes[i], __sanitizer_get_estimated_allocated_size(sizes[i])); - } -} - -static const char* kGetAllocatedSizeErrorMsg = - "attempting to call __sanitizer_get_allocated_size"; - -TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) { - const size_t kArraySize = 100; - char *array = Ident((char*)malloc(kArraySize)); - int *int_ptr = Ident(new int); - - // Allocated memory is owned by allocator. Allocated size should be - // equal to requested size. - EXPECT_EQ(true, __sanitizer_get_ownership(array)); - EXPECT_EQ(kArraySize, __sanitizer_get_allocated_size(array)); - EXPECT_EQ(true, __sanitizer_get_ownership(int_ptr)); - EXPECT_EQ(sizeof(int), __sanitizer_get_allocated_size(int_ptr)); - - // We cannot call GetAllocatedSize from the memory we didn't map, - // and from the interior pointers (not returned by previous malloc). - void *wild_addr = (void*)0x1; - EXPECT_FALSE(__sanitizer_get_ownership(wild_addr)); - EXPECT_DEATH(__sanitizer_get_allocated_size(wild_addr), - kGetAllocatedSizeErrorMsg); - EXPECT_FALSE(__sanitizer_get_ownership(array + kArraySize / 2)); - EXPECT_DEATH(__sanitizer_get_allocated_size(array + kArraySize / 2), - kGetAllocatedSizeErrorMsg); - - // NULL is not owned, but is a valid argument for - // __sanitizer_get_allocated_size(). - EXPECT_FALSE(__sanitizer_get_ownership(NULL)); - EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL)); - - // When memory is freed, it's not owned, and call to GetAllocatedSize - // is forbidden. - free(array); - EXPECT_FALSE(__sanitizer_get_ownership(array)); - EXPECT_DEATH(__sanitizer_get_allocated_size(array), - kGetAllocatedSizeErrorMsg); - delete int_ptr; - - void *zero_alloc = Ident(malloc(0)); - if (zero_alloc != 0) { - // If malloc(0) is not null, this pointer is owned and should have valid - // allocated size. - EXPECT_TRUE(__sanitizer_get_ownership(zero_alloc)); - // Allocated size is 0 or 1 depending on the allocator used. - EXPECT_LT(__sanitizer_get_allocated_size(zero_alloc), 2U); - } - free(zero_alloc); -} - -TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) { - size_t before_malloc, after_malloc, after_free; - char *array; - const size_t kMallocSize = 100; - before_malloc = __sanitizer_get_current_allocated_bytes(); - - array = Ident((char*)malloc(kMallocSize)); - after_malloc = __sanitizer_get_current_allocated_bytes(); - EXPECT_EQ(before_malloc + kMallocSize, after_malloc); - - free(array); - after_free = __sanitizer_get_current_allocated_bytes(); - EXPECT_EQ(before_malloc, after_free); -} - -TEST(AddressSanitizerInterface, GetHeapSizeTest) { - // ASan allocator does not keep huge chunks in free list, but unmaps them. - // The chunk should be greater than the quarantine size, - // otherwise it will be stuck in quarantine instead of being unmaped. - static const size_t kLargeMallocSize = (1 << 28) + 1; // 256M - free(Ident(malloc(kLargeMallocSize))); // Drain quarantine. - size_t old_heap_size = __sanitizer_get_heap_size(); - for (int i = 0; i < 3; i++) { - // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize); - free(Ident(malloc(kLargeMallocSize))); - EXPECT_EQ(old_heap_size, __sanitizer_get_heap_size()); - } -} - -static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357}; -static const size_t kManyThreadsIterations = 250; -static const size_t kManyThreadsNumThreads = - (SANITIZER_WORDSIZE == 32) ? 40 : 200; - -static void *ManyThreadsWithStatsWorker(void *arg) { - (void)arg; - for (size_t iter = 0; iter < kManyThreadsIterations; iter++) { - for (size_t size_index = 0; size_index < 4; size_index++) { - free(Ident(malloc(kManyThreadsMallocSizes[size_index]))); - } - } - // Just one large allocation. - free(Ident(malloc(1 << 20))); - return 0; -} - -TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) { - size_t before_test, after_test, i; - pthread_t threads[kManyThreadsNumThreads]; - before_test = __sanitizer_get_current_allocated_bytes(); - for (i = 0; i < kManyThreadsNumThreads; i++) { - PTHREAD_CREATE(&threads[i], 0, - (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i); - } - for (i = 0; i < kManyThreadsNumThreads; i++) { - PTHREAD_JOIN(threads[i], 0); - } - after_test = __sanitizer_get_current_allocated_bytes(); - // ASan stats also reflect memory usage of internal ASan RTL structs, - // so we can't check for equality here. - EXPECT_LT(after_test, before_test + (1UL<<20)); -} - -static void DoDoubleFree() { - int *x = Ident(new int); - delete Ident(x); - delete Ident(x); -} - -TEST(AddressSanitizerInterface, ExitCode) { - int original_exit_code = __asan_set_error_exit_code(7); - EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), ""); - EXPECT_EQ(7, __asan_set_error_exit_code(8)); - EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), ""); - EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code)); - EXPECT_EXIT(DoDoubleFree(), - ::testing::ExitedWithCode(original_exit_code), ""); -} - -static void MyDeathCallback() { - fprintf(stderr, "MyDeathCallback\n"); - fflush(0); // On Windows, stderr doesn't flush on crash. -} - -TEST(AddressSanitizerInterface, DeathCallbackTest) { - __asan_set_death_callback(MyDeathCallback); - EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback"); - __asan_set_death_callback(NULL); -} - -static const char* kUseAfterPoisonErrorMessage = "use-after-poison"; - -#define GOOD_ACCESS(ptr, offset) \ - EXPECT_FALSE(__asan_address_is_poisoned(ptr + offset)) - -#define BAD_ACCESS(ptr, offset) \ - EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset)) - -TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) { - char *array = Ident((char*)malloc(120)); - // poison array[40..80) - __asan_poison_memory_region(array + 40, 40); - GOOD_ACCESS(array, 39); - GOOD_ACCESS(array, 80); - BAD_ACCESS(array, 40); - BAD_ACCESS(array, 60); - BAD_ACCESS(array, 79); - char value; - EXPECT_DEATH(value = Ident(array[40]), kUseAfterPoisonErrorMessage); - __asan_unpoison_memory_region(array + 40, 40); - // access previously poisoned memory. - GOOD_ACCESS(array, 40); - GOOD_ACCESS(array, 79); - free(array); -} - -TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) { - char *array = Ident((char*)malloc(120)); - // Poison [0..40) and [80..120) - __asan_poison_memory_region(array, 40); - __asan_poison_memory_region(array + 80, 40); - BAD_ACCESS(array, 20); - GOOD_ACCESS(array, 60); - BAD_ACCESS(array, 100); - // Poison whole array - [0..120) - __asan_poison_memory_region(array, 120); - BAD_ACCESS(array, 60); - // Unpoison [24..96) - __asan_unpoison_memory_region(array + 24, 72); - BAD_ACCESS(array, 23); - GOOD_ACCESS(array, 24); - GOOD_ACCESS(array, 60); - GOOD_ACCESS(array, 95); - BAD_ACCESS(array, 96); - free(array); -} - -TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) { - // Vector of capacity 20 - char *vec = Ident((char*)malloc(20)); - __asan_poison_memory_region(vec, 20); - for (size_t i = 0; i < 7; i++) { - // Simulate push_back. - __asan_unpoison_memory_region(vec + i, 1); - GOOD_ACCESS(vec, i); - BAD_ACCESS(vec, i + 1); - } - for (size_t i = 7; i > 0; i--) { - // Simulate pop_back. - __asan_poison_memory_region(vec + i - 1, 1); - BAD_ACCESS(vec, i - 1); - if (i > 1) GOOD_ACCESS(vec, i - 2); - } - free(vec); -} - -// Make sure that each aligned block of size "2^granularity" doesn't have -// "true" value before "false" value. -static void MakeShadowValid(bool *shadow, int length, int granularity) { - bool can_be_poisoned = true; - for (int i = length - 1; i >= 0; i--) { - if (!shadow[i]) - can_be_poisoned = false; - if (!can_be_poisoned) - shadow[i] = false; - if (i % (1 << granularity) == 0) { - can_be_poisoned = true; - } - } -} - -TEST(AddressSanitizerInterface, PoisoningStressTest) { - const size_t kSize = 24; - bool expected[kSize]; - char *arr = Ident((char*)malloc(kSize)); - for (size_t l1 = 0; l1 < kSize; l1++) { - for (size_t s1 = 1; l1 + s1 <= kSize; s1++) { - for (size_t l2 = 0; l2 < kSize; l2++) { - for (size_t s2 = 1; l2 + s2 <= kSize; s2++) { - // Poison [l1, l1+s1), [l2, l2+s2) and check result. - __asan_unpoison_memory_region(arr, kSize); - __asan_poison_memory_region(arr + l1, s1); - __asan_poison_memory_region(arr + l2, s2); - memset(expected, false, kSize); - memset(expected + l1, true, s1); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - memset(expected + l2, true, s2); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - for (size_t i = 0; i < kSize; i++) { - ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i)); - } - // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result. - __asan_poison_memory_region(arr, kSize); - __asan_unpoison_memory_region(arr + l1, s1); - __asan_unpoison_memory_region(arr + l2, s2); - memset(expected, true, kSize); - memset(expected + l1, false, s1); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - memset(expected + l2, false, s2); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - for (size_t i = 0; i < kSize; i++) { - ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i)); - } - } - } - } - } - free(arr); -} - -TEST(AddressSanitizerInterface, GlobalRedzones) { - GOOD_ACCESS(glob1, 1 - 1); - GOOD_ACCESS(glob2, 2 - 1); - GOOD_ACCESS(glob3, 3 - 1); - GOOD_ACCESS(glob4, 4 - 1); - GOOD_ACCESS(glob5, 5 - 1); - GOOD_ACCESS(glob6, 6 - 1); - GOOD_ACCESS(glob7, 7 - 1); - GOOD_ACCESS(glob8, 8 - 1); - GOOD_ACCESS(glob9, 9 - 1); - GOOD_ACCESS(glob10, 10 - 1); - GOOD_ACCESS(glob11, 11 - 1); - GOOD_ACCESS(glob12, 12 - 1); - GOOD_ACCESS(glob13, 13 - 1); - GOOD_ACCESS(glob14, 14 - 1); - GOOD_ACCESS(glob15, 15 - 1); - GOOD_ACCESS(glob16, 16 - 1); - GOOD_ACCESS(glob17, 17 - 1); - GOOD_ACCESS(glob1000, 1000 - 1); - GOOD_ACCESS(glob10000, 10000 - 1); - GOOD_ACCESS(glob100000, 100000 - 1); - - BAD_ACCESS(glob1, 1); - BAD_ACCESS(glob2, 2); - BAD_ACCESS(glob3, 3); - BAD_ACCESS(glob4, 4); - BAD_ACCESS(glob5, 5); - BAD_ACCESS(glob6, 6); - BAD_ACCESS(glob7, 7); - BAD_ACCESS(glob8, 8); - BAD_ACCESS(glob9, 9); - BAD_ACCESS(glob10, 10); - BAD_ACCESS(glob11, 11); - BAD_ACCESS(glob12, 12); - BAD_ACCESS(glob13, 13); - BAD_ACCESS(glob14, 14); - BAD_ACCESS(glob15, 15); - BAD_ACCESS(glob16, 16); - BAD_ACCESS(glob17, 17); - BAD_ACCESS(glob1000, 1000); - BAD_ACCESS(glob1000, 1100); // Redzone is at least 101 bytes. - BAD_ACCESS(glob10000, 10000); - BAD_ACCESS(glob10000, 11000); // Redzone is at least 1001 bytes. - BAD_ACCESS(glob100000, 100000); - BAD_ACCESS(glob100000, 110000); // Redzone is at least 10001 bytes. -} - -TEST(AddressSanitizerInterface, PoisonedRegion) { - size_t rz = 16; - for (size_t size = 1; size <= 64; size++) { - char *p = new char[size]; - for (size_t beg = 0; beg < size + rz; beg++) { - for (size_t end = beg; end < size + rz; end++) { - void *first_poisoned = __asan_region_is_poisoned(p + beg, end - beg); - if (beg == end) { - EXPECT_FALSE(first_poisoned); - } else if (beg < size && end <= size) { - EXPECT_FALSE(first_poisoned); - } else if (beg >= size) { - EXPECT_EQ(p + beg, first_poisoned); - } else { - EXPECT_GT(end, size); - EXPECT_EQ(p + size, first_poisoned); - } - } - } - delete [] p; - } -} - -// This is a performance benchmark for manual runs. -// asan's memset interceptor calls mem_is_zero for the entire shadow region. -// the profile should look like this: -// 89.10% [.] __memset_sse2 -// 10.50% [.] __sanitizer::mem_is_zero -// I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles -// than memset itself. -TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) { - size_t size = 1 << 20; - char *x = new char[size]; - for (int i = 0; i < 100000; i++) - Ident(memset)(x, 0, size); - delete [] x; -} - -// Same here, but we run memset with small sizes. -TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) { - size_t size = 32; - char *x = new char[size]; - for (int i = 0; i < 100000000; i++) - Ident(memset)(x, 0, size); - delete [] x; -} -static const char *kInvalidPoisonMessage = "invalid-poison-memory-range"; -static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range"; - -TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) { - char *array = Ident((char*)malloc(120)); - __asan_unpoison_memory_region(array, 120); - // Try to unpoison not owned memory - EXPECT_DEATH(__asan_unpoison_memory_region(array, 121), - kInvalidUnpoisonMessage); - EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120), - kInvalidUnpoisonMessage); - - __asan_poison_memory_region(array, 120); - // Try to poison not owned memory. - EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage); - EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120), - kInvalidPoisonMessage); - free(array); -} - -#if !defined(_WIN32) // FIXME: This should really be a lit test. -static void ErrorReportCallbackOneToZ(const char *report) { - int report_len = strlen(report); - ASSERT_EQ(6, write(2, "ABCDEF", 6)); - ASSERT_EQ(report_len, write(2, report, report_len)); - ASSERT_EQ(6, write(2, "ABCDEF", 6)); - _exit(1); -} - -TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) { - __asan_set_error_report_callback(ErrorReportCallbackOneToZ); - EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1), - ASAN_PCRE_DOTALL "ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF"); - __asan_set_error_report_callback(NULL); -} -#endif - -TEST(AddressSanitizerInterface, GetOwnershipStressTest) { - std::vector<char *> pointers; - std::vector<size_t> sizes; - const size_t kNumMallocs = 1 << 9; - for (size_t i = 0; i < kNumMallocs; i++) { - size_t size = i * 100 + 1; - pointers.push_back((char*)malloc(size)); - sizes.push_back(size); - } - for (size_t i = 0; i < 4000000; i++) { - EXPECT_FALSE(__sanitizer_get_ownership(&pointers)); - EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234)); - size_t idx = i % kNumMallocs; - EXPECT_TRUE(__sanitizer_get_ownership(pointers[idx])); - EXPECT_EQ(sizes[idx], __sanitizer_get_allocated_size(pointers[idx])); - } - for (size_t i = 0, n = pointers.size(); i < n; i++) - free(pointers[i]); -} - diff --git a/contrib/compiler-rt/lib/asan/tests/asan_mac_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_mac_test.cc deleted file mode 100644 index cabdfd711ea2..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_mac_test.cc +++ /dev/null @@ -1,236 +0,0 @@ -//===-- asan_test_mac.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// - -#include "asan_test_utils.h" - -#include "asan_mac_test.h" - -#include <malloc/malloc.h> -#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_* -#include <CoreFoundation/CFString.h> - -TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree) { - EXPECT_DEATH( - CFAllocatorDefaultDoubleFree(NULL), - "attempting double-free"); -} - -void CFAllocator_DoubleFreeOnPthread() { - pthread_t child; - PTHREAD_CREATE(&child, NULL, CFAllocatorDefaultDoubleFree, NULL); - PTHREAD_JOIN(child, NULL); // Shouldn't be reached. -} - -TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree_ChildPhread) { - EXPECT_DEATH(CFAllocator_DoubleFreeOnPthread(), "attempting double-free"); -} - -namespace { - -void *GLOB; - -void *CFAllocatorAllocateToGlob(void *unused) { - GLOB = CFAllocatorAllocate(NULL, 100, /*hint*/0); - return NULL; -} - -void *CFAllocatorDeallocateFromGlob(void *unused) { - char *p = (char*)GLOB; - p[100] = 'A'; // ASan should report an error here. - CFAllocatorDeallocate(NULL, GLOB); - return NULL; -} - -void CFAllocator_PassMemoryToAnotherThread() { - pthread_t th1, th2; - PTHREAD_CREATE(&th1, NULL, CFAllocatorAllocateToGlob, NULL); - PTHREAD_JOIN(th1, NULL); - PTHREAD_CREATE(&th2, NULL, CFAllocatorDeallocateFromGlob, NULL); - PTHREAD_JOIN(th2, NULL); -} - -TEST(AddressSanitizerMac, CFAllocator_PassMemoryToAnotherThread) { - EXPECT_DEATH(CFAllocator_PassMemoryToAnotherThread(), - "heap-buffer-overflow"); -} - -} // namespace - -// TODO(glider): figure out whether we still need these tests. Is it correct -// to intercept the non-default CFAllocators? -TEST(AddressSanitizerMac, DISABLED_CFAllocatorSystemDefaultDoubleFree) { - EXPECT_DEATH( - CFAllocatorSystemDefaultDoubleFree(), - "attempting double-free"); -} - -// We're intercepting malloc, so kCFAllocatorMalloc is routed to ASan. -TEST(AddressSanitizerMac, CFAllocatorMallocDoubleFree) { - EXPECT_DEATH(CFAllocatorMallocDoubleFree(), "attempting double-free"); -} - -TEST(AddressSanitizerMac, DISABLED_CFAllocatorMallocZoneDoubleFree) { - EXPECT_DEATH(CFAllocatorMallocZoneDoubleFree(), "attempting double-free"); -} - -// For libdispatch tests below we check that ASan got to the shadow byte -// legend, i.e. managed to print the thread stacks (this almost certainly -// means that the libdispatch task creation has been intercepted correctly). -TEST(AddressSanitizerMac, GCDDispatchAsync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDDispatchAsync(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDDispatchSync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDDispatchSync(), "Shadow byte legend"); -} - - -TEST(AddressSanitizerMac, GCDReuseWqthreadsAsync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDReuseWqthreadsAsync(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDReuseWqthreadsSync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDReuseWqthreadsSync(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDDispatchAfter) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDDispatchAfter(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDSourceEvent) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDSourceEvent(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDSourceCancel) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDSourceCancel(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDGroupAsync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDGroupAsync(), "Shadow byte legend"); -} - -void *MallocIntrospectionLockWorker(void *_) { - const int kNumPointers = 100; - int i; - void *pointers[kNumPointers]; - for (i = 0; i < kNumPointers; i++) { - pointers[i] = malloc(i + 1); - } - for (i = 0; i < kNumPointers; i++) { - free(pointers[i]); - } - - return NULL; -} - -void *MallocIntrospectionLockForker(void *_) { - pid_t result = fork(); - if (result == -1) { - perror("fork"); - } - assert(result != -1); - if (result == 0) { - // Call malloc in the child process to make sure we won't deadlock. - void *ptr = malloc(42); - free(ptr); - exit(0); - } else { - // Return in the parent process. - return NULL; - } -} - -TEST(AddressSanitizerMac, MallocIntrospectionLock) { - // Incorrect implementation of force_lock and force_unlock in our malloc zone - // will cause forked processes to deadlock. - // TODO(glider): need to detect that none of the child processes deadlocked. - const int kNumWorkers = 5, kNumIterations = 100; - int i, iter; - for (iter = 0; iter < kNumIterations; iter++) { - pthread_t workers[kNumWorkers], forker; - for (i = 0; i < kNumWorkers; i++) { - PTHREAD_CREATE(&workers[i], 0, MallocIntrospectionLockWorker, 0); - } - PTHREAD_CREATE(&forker, 0, MallocIntrospectionLockForker, 0); - for (i = 0; i < kNumWorkers; i++) { - PTHREAD_JOIN(workers[i], 0); - } - PTHREAD_JOIN(forker, 0); - } -} - -void *TSDAllocWorker(void *test_key) { - if (test_key) { - void *mem = malloc(10); - pthread_setspecific(*(pthread_key_t*)test_key, mem); - } - return NULL; -} - -TEST(AddressSanitizerMac, DISABLED_TSDWorkqueueTest) { - pthread_t th; - pthread_key_t test_key; - pthread_key_create(&test_key, CallFreeOnWorkqueue); - PTHREAD_CREATE(&th, NULL, TSDAllocWorker, &test_key); - PTHREAD_JOIN(th, NULL); - pthread_key_delete(test_key); -} - -// Test that CFStringCreateCopy does not copy constant strings. -TEST(AddressSanitizerMac, CFStringCreateCopy) { - CFStringRef str = CFSTR("Hello world!\n"); - CFStringRef str2 = CFStringCreateCopy(0, str); - EXPECT_EQ(str, str2); -} - -TEST(AddressSanitizerMac, NSObjectOOB) { - // Make sure that our allocators are used for NSObjects. - EXPECT_DEATH(TestOOBNSObjects(), "heap-buffer-overflow"); -} - -// Make sure that correct pointer is passed to free() when deallocating a -// NSURL object. -// See http://code.google.com/p/address-sanitizer/issues/detail?id=70. -TEST(AddressSanitizerMac, NSURLDeallocation) { - TestNSURLDeallocation(); -} - -// See http://code.google.com/p/address-sanitizer/issues/detail?id=109. -TEST(AddressSanitizerMac, Mstats) { - malloc_statistics_t stats1, stats2; - malloc_zone_statistics(/*all zones*/NULL, &stats1); - const size_t kMallocSize = 100000; - void *alloc = Ident(malloc(kMallocSize)); - malloc_zone_statistics(/*all zones*/NULL, &stats2); - EXPECT_GT(stats2.blocks_in_use, stats1.blocks_in_use); - EXPECT_GE(stats2.size_in_use - stats1.size_in_use, kMallocSize); - free(alloc); - // Even the default OSX allocator may not change the stats after free(). -} - diff --git a/contrib/compiler-rt/lib/asan/tests/asan_mac_test.h b/contrib/compiler-rt/lib/asan/tests/asan_mac_test.h deleted file mode 100644 index 441547a5a3dc..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_mac_test.h +++ /dev/null @@ -1,19 +0,0 @@ -extern "C" { - void *CFAllocatorDefaultDoubleFree(void *unused); - void CFAllocatorSystemDefaultDoubleFree(); - void CFAllocatorMallocDoubleFree(); - void CFAllocatorMallocZoneDoubleFree(); - void CallFreeOnWorkqueue(void *mem); - void TestGCDDispatchAsync(); - void TestGCDDispatchSync(); - void TestGCDReuseWqthreadsAsync(); - void TestGCDReuseWqthreadsSync(); - void TestGCDDispatchAfter(); - void TestGCDInTSDDestructor(); - void TestGCDSourceEvent(); - void TestGCDSourceCancel(); - void TestGCDGroupAsync(); - void TestOOBNSObjects(); - void TestNSURLDeallocation(); - void TestPassCFMemoryToAnotherThread(); -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm b/contrib/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm deleted file mode 100644 index a7e4b9d1928b..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_mac_test_helpers.mm +++ /dev/null @@ -1,240 +0,0 @@ -// Mac OS X 10.6 or higher only. -#include <dispatch/dispatch.h> -#include <pthread.h> // for pthread_yield_np() -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#import <CoreFoundation/CFBase.h> -#import <Foundation/NSObject.h> -#import <Foundation/NSURL.h> - -// This is a (void*)(void*) function so it can be passed to pthread_create. -void *CFAllocatorDefaultDoubleFree(void *unused) { - void *mem = CFAllocatorAllocate(kCFAllocatorDefault, 5, 0); - CFAllocatorDeallocate(kCFAllocatorDefault, mem); - CFAllocatorDeallocate(kCFAllocatorDefault, mem); - return 0; -} - -void CFAllocatorSystemDefaultDoubleFree() { - void *mem = CFAllocatorAllocate(kCFAllocatorSystemDefault, 5, 0); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, mem); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, mem); -} - -void CFAllocatorMallocDoubleFree() { - void *mem = CFAllocatorAllocate(kCFAllocatorMalloc, 5, 0); - CFAllocatorDeallocate(kCFAllocatorMalloc, mem); - CFAllocatorDeallocate(kCFAllocatorMalloc, mem); -} - -void CFAllocatorMallocZoneDoubleFree() { - void *mem = CFAllocatorAllocate(kCFAllocatorMallocZone, 5, 0); - CFAllocatorDeallocate(kCFAllocatorMallocZone, mem); - CFAllocatorDeallocate(kCFAllocatorMallocZone, mem); -} - -__attribute__((noinline)) -void access_memory(char *a) { - *a = 0; -} - -// Test the +load instrumentation. -// Because the +load methods are invoked before anything else is initialized, -// it makes little sense to wrap the code below into a gTest test case. -// If AddressSanitizer doesn't instrument the +load method below correctly, -// everything will just crash. - -char kStartupStr[] = - "If your test didn't crash, AddressSanitizer is instrumenting " - "the +load methods correctly."; - -@interface LoadSomething : NSObject { -} -@end - -@implementation LoadSomething - -+(void) load { - for (size_t i = 0; i < strlen(kStartupStr); i++) { - access_memory(&kStartupStr[i]); // make sure no optimizations occur. - } - // Don't print anything here not to interfere with the death tests. -} - -@end - -void worker_do_alloc(int size) { - char * volatile mem = (char * volatile)malloc(size); - mem[0] = 0; // Ok - free(mem); -} - -void worker_do_crash(int size) { - char * volatile mem = (char * volatile)malloc(size); - access_memory(&mem[size]); // BOOM - free(mem); -} - -// Used by the GCD tests to avoid a race between the worker thread reporting a -// memory error and the main thread which may exit with exit code 0 before -// that. -void wait_forever() { - volatile bool infinite = true; - while (infinite) pthread_yield_np(); -} - -// Tests for the Grand Central Dispatch. See -// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html -// for the reference. -void TestGCDDispatchAsync() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block = ^{ worker_do_crash(1024); }; - // dispatch_async() runs the task on a worker thread that does not go through - // pthread_create(). We need to verify that AddressSanitizer notices that the - // thread has started. - dispatch_async(queue, block); - wait_forever(); -} - -void TestGCDDispatchSync() { - dispatch_queue_t queue = dispatch_get_global_queue(2, 0); - dispatch_block_t block = ^{ worker_do_crash(1024); }; - // dispatch_sync() runs the task on a worker thread that does not go through - // pthread_create(). We need to verify that AddressSanitizer notices that the - // thread has started. - dispatch_sync(queue, block); - wait_forever(); -} - -// libdispatch spawns a rather small number of threads and reuses them. We need -// to make sure AddressSanitizer handles the reusing correctly. -void TestGCDReuseWqthreadsAsync() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block_alloc = ^{ worker_do_alloc(1024); }; - dispatch_block_t block_crash = ^{ worker_do_crash(1024); }; - for (int i = 0; i < 100; i++) { - dispatch_async(queue, block_alloc); - } - dispatch_async(queue, block_crash); - wait_forever(); -} - -// Try to trigger abnormal behaviour of dispatch_sync() being unhandled by us. -void TestGCDReuseWqthreadsSync() { - dispatch_queue_t queue[4]; - queue[0] = dispatch_get_global_queue(2, 0); - queue[1] = dispatch_get_global_queue(0, 0); - queue[2] = dispatch_get_global_queue(-2, 0); - queue[3] = dispatch_queue_create("my_queue", NULL); - dispatch_block_t block_alloc = ^{ worker_do_alloc(1024); }; - dispatch_block_t block_crash = ^{ worker_do_crash(1024); }; - for (int i = 0; i < 1000; i++) { - dispatch_sync(queue[i % 4], block_alloc); - } - dispatch_sync(queue[3], block_crash); - wait_forever(); -} - -void TestGCDDispatchAfter() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block_crash = ^{ worker_do_crash(1024); }; - // Schedule the event one second from the current time. - dispatch_time_t milestone = - dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC); - dispatch_after(milestone, queue, block_crash); - wait_forever(); -} - -void worker_do_deallocate(void *ptr) { - free(ptr); -} - -void CallFreeOnWorkqueue(void *tsd) { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block_dealloc = ^{ worker_do_deallocate(tsd); }; - dispatch_async(queue, block_dealloc); - // Do not wait for the worker to free the memory -- nobody is going to touch - // it. -} - -void TestGCDSourceEvent() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_source_t timer = - dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); - // Schedule the timer one second from the current time. - dispatch_time_t milestone = - dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC); - - dispatch_source_set_timer(timer, milestone, DISPATCH_TIME_FOREVER, 0); - char * volatile mem = (char * volatile)malloc(10); - dispatch_source_set_event_handler(timer, ^{ - access_memory(&mem[10]); - }); - dispatch_resume(timer); - wait_forever(); -} - -void TestGCDSourceCancel() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_source_t timer = - dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); - // Schedule the timer one second from the current time. - dispatch_time_t milestone = - dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC); - - dispatch_source_set_timer(timer, milestone, DISPATCH_TIME_FOREVER, 0); - char * volatile mem = (char * volatile)malloc(10); - // Both dispatch_source_set_cancel_handler() and - // dispatch_source_set_event_handler() use dispatch_barrier_async_f(). - // It's tricky to test dispatch_source_set_cancel_handler() separately, - // so we test both here. - dispatch_source_set_event_handler(timer, ^{ - dispatch_source_cancel(timer); - }); - dispatch_source_set_cancel_handler(timer, ^{ - access_memory(&mem[10]); - }); - dispatch_resume(timer); - wait_forever(); -} - -void TestGCDGroupAsync() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_group_t group = dispatch_group_create(); - char * volatile mem = (char * volatile)malloc(10); - dispatch_group_async(group, queue, ^{ - access_memory(&mem[10]); - }); - dispatch_group_wait(group, DISPATCH_TIME_FOREVER); - wait_forever(); -} - -@interface FixedArray : NSObject { - int items[10]; -} -@end - -@implementation FixedArray --(int) access: (int)index { - return items[index]; -} -@end - -void TestOOBNSObjects() { - id anObject = [FixedArray new]; - [anObject access:1]; - [anObject access:11]; - [anObject release]; -} - -void TestNSURLDeallocation() { - NSURL *base = - [[NSURL alloc] initWithString:@"file://localhost/Users/glider/Library/"]; - volatile NSURL *u = - [[NSURL alloc] initWithString:@"Saved Application State" - relativeToURL:base]; - [u release]; -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_mem_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_mem_test.cc deleted file mode 100644 index 4a941faa0430..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_mem_test.cc +++ /dev/null @@ -1,241 +0,0 @@ -//===-- asan_mem_test.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -template<typename T> -void MemSetOOBTestTemplate(size_t length) { - if (length == 0) return; - size_t size = Ident(sizeof(T) * length); - T *array = Ident((T*)malloc(size)); - int element = Ident(42); - int zero = Ident(0); - void *(*MEMSET)(void *s, int c, size_t n) = Ident(memset); - // memset interval inside array - MEMSET(array, element, size); - MEMSET(array, element, size - 1); - MEMSET(array + length - 1, element, sizeof(T)); - MEMSET(array, element, 1); - - // memset 0 bytes - MEMSET(array - 10, element, zero); - MEMSET(array - 1, element, zero); - MEMSET(array, element, zero); - MEMSET(array + length, 0, zero); - MEMSET(array + length + 1, 0, zero); - - // try to memset bytes to the right of array - EXPECT_DEATH(MEMSET(array, 0, size + 1), - RightOOBWriteMessage(0)); - EXPECT_DEATH(MEMSET((char*)(array + length) - 1, element, 6), - RightOOBWriteMessage(0)); - EXPECT_DEATH(MEMSET(array + 1, element, size + sizeof(T)), - RightOOBWriteMessage(0)); - // whole interval is to the right - EXPECT_DEATH(MEMSET(array + length + 1, 0, 10), - RightOOBWriteMessage(sizeof(T))); - - // try to memset bytes to the left of array - EXPECT_DEATH(MEMSET((char*)array - 1, element, size), - LeftOOBWriteMessage(1)); - EXPECT_DEATH(MEMSET((char*)array - 5, 0, 6), - LeftOOBWriteMessage(5)); - if (length >= 100) { - // Large OOB, we find it only if the redzone is large enough. - EXPECT_DEATH(memset(array - 5, element, size + 5 * sizeof(T)), - LeftOOBWriteMessage(5 * sizeof(T))); - } - // whole interval is to the left - EXPECT_DEATH(MEMSET(array - 2, 0, sizeof(T)), - LeftOOBWriteMessage(2 * sizeof(T))); - - // try to memset bytes both to the left & to the right - EXPECT_DEATH(MEMSET((char*)array - 2, element, size + 4), - LeftOOBWriteMessage(2)); - - free(array); -} - -TEST(AddressSanitizer, MemSetOOBTest) { - MemSetOOBTestTemplate<char>(100); - MemSetOOBTestTemplate<int>(5); - MemSetOOBTestTemplate<double>(256); - // We can test arrays of structres/classes here, but what for? -} - -// Try to allocate two arrays of 'size' bytes that are near each other. -// Strictly speaking we are not guaranteed to find such two pointers, -// but given the structure of asan's allocator we will. -static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) { - vector<uintptr_t> v; - bool res = false; - for (size_t i = 0; i < 1000U && !res; i++) { - v.push_back(reinterpret_cast<uintptr_t>(new char[size])); - if (i == 0) continue; - sort(v.begin(), v.end()); - for (size_t j = 1; j < v.size(); j++) { - assert(v[j] > v[j-1]); - if ((size_t)(v[j] - v[j-1]) < size * 2) { - *x2 = reinterpret_cast<char*>(v[j]); - *x1 = reinterpret_cast<char*>(v[j-1]); - res = true; - break; - } - } - } - - for (size_t i = 0; i < v.size(); i++) { - char *p = reinterpret_cast<char *>(v[i]); - if (res && p == *x1) continue; - if (res && p == *x2) continue; - delete [] p; - } - return res; -} - -TEST(AddressSanitizer, LargeOOBInMemset) { - for (size_t size = 200; size < 100000; size += size / 2) { - char *x1, *x2; - if (!Ident(AllocateTwoAdjacentArrays)(&x1, &x2, size)) - continue; - // fprintf(stderr, " large oob memset: %p %p %zd\n", x1, x2, size); - // Do a memset on x1 with huge out-of-bound access that will end up in x2. - EXPECT_DEATH(Ident(memset)(x1, 0, size * 2), - "is located 0 bytes to the right"); - delete [] x1; - delete [] x2; - return; - } - assert(0 && "Did not find two adjacent malloc-ed pointers"); -} - -// Same test for memcpy and memmove functions -template <typename T, class M> -void MemTransferOOBTestTemplate(size_t length) { - if (length == 0) return; - size_t size = Ident(sizeof(T) * length); - T *src = Ident((T*)malloc(size)); - T *dest = Ident((T*)malloc(size)); - int zero = Ident(0); - - // valid transfer of bytes between arrays - M::transfer(dest, src, size); - M::transfer(dest + 1, src, size - sizeof(T)); - M::transfer(dest, src + length - 1, sizeof(T)); - M::transfer(dest, src, 1); - - // transfer zero bytes - M::transfer(dest - 1, src, 0); - M::transfer(dest + length, src, zero); - M::transfer(dest, src - 1, zero); - M::transfer(dest, src, zero); - - // try to change mem to the right of dest - EXPECT_DEATH(M::transfer(dest + 1, src, size), - RightOOBWriteMessage(0)); - EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5), - RightOOBWriteMessage(0)); - - // try to change mem to the left of dest - EXPECT_DEATH(M::transfer(dest - 2, src, size), - LeftOOBWriteMessage(2 * sizeof(T))); - EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4), - LeftOOBWriteMessage(3)); - - // try to access mem to the right of src - EXPECT_DEATH(M::transfer(dest, src + 2, size), - RightOOBReadMessage(0)); - EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6), - RightOOBReadMessage(0)); - - // try to access mem to the left of src - EXPECT_DEATH(M::transfer(dest, src - 1, size), - LeftOOBReadMessage(sizeof(T))); - EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7), - LeftOOBReadMessage(6)); - - // Generally we don't need to test cases where both accessing src and writing - // to dest address to poisoned memory. - - T *big_src = Ident((T*)malloc(size * 2)); - T *big_dest = Ident((T*)malloc(size * 2)); - // try to change mem to both sides of dest - EXPECT_DEATH(M::transfer(dest - 1, big_src, size * 2), - LeftOOBWriteMessage(sizeof(T))); - // try to access mem to both sides of src - EXPECT_DEATH(M::transfer(big_dest, src - 2, size * 2), - LeftOOBReadMessage(2 * sizeof(T))); - - free(src); - free(dest); - free(big_src); - free(big_dest); -} - -class MemCpyWrapper { - public: - static void* transfer(void *to, const void *from, size_t size) { - return Ident(memcpy)(to, from, size); - } -}; - -TEST(AddressSanitizer, MemCpyOOBTest) { - MemTransferOOBTestTemplate<char, MemCpyWrapper>(100); - MemTransferOOBTestTemplate<int, MemCpyWrapper>(1024); -} - -class MemMoveWrapper { - public: - static void* transfer(void *to, const void *from, size_t size) { - return Ident(memmove)(to, from, size); - } -}; - -TEST(AddressSanitizer, MemMoveOOBTest) { - MemTransferOOBTestTemplate<char, MemMoveWrapper>(100); - MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024); -} - - -TEST(AddressSanitizer, MemCmpOOBTest) { - size_t size = Ident(100); - char *s1 = MallocAndMemsetString(size); - char *s2 = MallocAndMemsetString(size); - // Normal memcmp calls. - Ident(memcmp(s1, s2, size)); - Ident(memcmp(s1 + size - 1, s2 + size - 1, 1)); - Ident(memcmp(s1 - 1, s2 - 1, 0)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0)); - // Hit unallocated memory and die. - EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0)); - // Zero bytes are not terminators and don't prevent from OOB. - s1[size - 1] = '\0'; - s2[size - 1] = '\0'; - EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); - - // Even if the buffers differ in the first byte, we still assume that - // memcmp may access the whole buffer and thus reporting the overflow here: - s1[0] = 1; - s2[0] = 123; - EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); - - free(s1); - free(s2); -} - - - diff --git a/contrib/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_noinst_test.cc deleted file mode 100644 index 6a428fbbc2b9..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_noinst_test.cc +++ /dev/null @@ -1,263 +0,0 @@ -//===-- asan_noinst_test.cc -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// This test file should be compiled w/o asan instrumentation. -//===----------------------------------------------------------------------===// - -#include "asan_allocator.h" -#include "asan_internal.h" -#include "asan_mapping.h" -#include "asan_test_utils.h" -#include <sanitizer/allocator_interface.h> - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> // for memset() -#include <algorithm> -#include <vector> -#include <limits> - -// ATTENTION! -// Please don't call intercepted functions (including malloc() and friends) -// in this test. The static runtime library is linked explicitly (without -// -fsanitize=address), thus the interceptors do not work correctly on OS X. - -// Make sure __asan_init is called before any test case is run. -struct AsanInitCaller { - AsanInitCaller() { - __asan::DisableReexec(); - __asan_init(); - } -}; -static AsanInitCaller asan_init_caller; - -TEST(AddressSanitizer, InternalSimpleDeathTest) { - EXPECT_DEATH(exit(1), ""); -} - -static void MallocStress(size_t n) { - u32 seed = my_rand(); - BufferedStackTrace stack1; - stack1.trace_buffer[0] = 0xa123; - stack1.trace_buffer[1] = 0xa456; - stack1.size = 2; - - BufferedStackTrace stack2; - stack2.trace_buffer[0] = 0xb123; - stack2.trace_buffer[1] = 0xb456; - stack2.size = 2; - - BufferedStackTrace stack3; - stack3.trace_buffer[0] = 0xc123; - stack3.trace_buffer[1] = 0xc456; - stack3.size = 2; - - std::vector<void *> vec; - for (size_t i = 0; i < n; i++) { - if ((i % 3) == 0) { - if (vec.empty()) continue; - size_t idx = my_rand_r(&seed) % vec.size(); - void *ptr = vec[idx]; - vec[idx] = vec.back(); - vec.pop_back(); - __asan::asan_free(ptr, &stack1, __asan::FROM_MALLOC); - } else { - size_t size = my_rand_r(&seed) % 1000 + 1; - switch ((my_rand_r(&seed) % 128)) { - case 0: size += 1024; break; - case 1: size += 2048; break; - case 2: size += 4096; break; - } - size_t alignment = 1 << (my_rand_r(&seed) % 10 + 1); - char *ptr = (char*)__asan::asan_memalign(alignment, size, - &stack2, __asan::FROM_MALLOC); - EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, 0, 0)); - vec.push_back(ptr); - ptr[0] = 0; - ptr[size-1] = 0; - ptr[size/2] = 0; - } - } - for (size_t i = 0; i < vec.size(); i++) - __asan::asan_free(vec[i], &stack3, __asan::FROM_MALLOC); -} - - -TEST(AddressSanitizer, NoInstMallocTest) { - MallocStress(ASAN_LOW_MEMORY ? 300000 : 1000000); -} - -TEST(AddressSanitizer, ThreadedMallocStressTest) { - const int kNumThreads = 4; - const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000; - pthread_t t[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))MallocStress, - (void*)kNumIterations); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} - -static void PrintShadow(const char *tag, uptr ptr, size_t size) { - fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size); - uptr prev_shadow = 0; - for (sptr i = -32; i < (sptr)size + 32; i++) { - uptr shadow = __asan::MemToShadow(ptr + i); - if (i == 0 || i == (sptr)size) - fprintf(stderr, "."); - if (shadow != prev_shadow) { - prev_shadow = shadow; - fprintf(stderr, "%02x", (int)*(u8*)shadow); - } - } - fprintf(stderr, "\n"); -} - -TEST(AddressSanitizer, DISABLED_InternalPrintShadow) { - for (size_t size = 1; size <= 513; size++) { - char *ptr = new char[size]; - PrintShadow("m", (uptr)ptr, size); - delete [] ptr; - PrintShadow("f", (uptr)ptr, size); - } -} - -TEST(AddressSanitizer, QuarantineTest) { - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - - const int size = 1024; - void *p = __asan::asan_malloc(size, &stack); - __asan::asan_free(p, &stack, __asan::FROM_MALLOC); - size_t i; - size_t max_i = 1 << 30; - for (i = 0; i < max_i; i++) { - void *p1 = __asan::asan_malloc(size, &stack); - __asan::asan_free(p1, &stack, __asan::FROM_MALLOC); - if (p1 == p) break; - } - EXPECT_GE(i, 10000U); - EXPECT_LT(i, max_i); -} - -void *ThreadedQuarantineTestWorker(void *unused) { - (void)unused; - u32 seed = my_rand(); - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - - for (size_t i = 0; i < 1000; i++) { - void *p = __asan::asan_malloc(1 + (my_rand_r(&seed) % 4000), &stack); - __asan::asan_free(p, &stack, __asan::FROM_MALLOC); - } - return NULL; -} - -// Check that the thread local allocators are flushed when threads are -// destroyed. -TEST(AddressSanitizer, ThreadedQuarantineTest) { - const int n_threads = 3000; - size_t mmaped1 = __sanitizer_get_heap_size(); - for (int i = 0; i < n_threads; i++) { - pthread_t t; - PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0); - PTHREAD_JOIN(t, 0); - size_t mmaped2 = __sanitizer_get_heap_size(); - EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20)); - } -} - -void *ThreadedOneSizeMallocStress(void *unused) { - (void)unused; - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - const size_t kNumMallocs = 1000; - for (int iter = 0; iter < 1000; iter++) { - void *p[kNumMallocs]; - for (size_t i = 0; i < kNumMallocs; i++) { - p[i] = __asan::asan_malloc(32, &stack); - } - for (size_t i = 0; i < kNumMallocs; i++) { - __asan::asan_free(p[i], &stack, __asan::FROM_MALLOC); - } - } - return NULL; -} - -TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) { - const int kNumThreads = 4; - pthread_t t[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, ThreadedOneSizeMallocStress, 0); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} - -TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) { - using __asan::kHighMemEnd; - // Check that __asan_region_is_poisoned works for shadow regions. - uptr ptr = kLowShadowBeg + 200; - EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); - ptr = kShadowGapBeg + 200; - EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); - ptr = kHighShadowBeg + 200; - EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); -} - -// Test __asan_load1 & friends. -TEST(AddressSanitizer, LoadStoreCallbacks) { - typedef void (*CB)(uptr p); - CB cb[2][5] = { - { - __asan_load1, __asan_load2, __asan_load4, __asan_load8, __asan_load16, - }, { - __asan_store1, __asan_store2, __asan_store4, __asan_store8, - __asan_store16, - } - }; - - uptr buggy_ptr; - - __asan_test_only_reported_buggy_pointer = &buggy_ptr; - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - - for (uptr len = 16; len <= 32; len++) { - char *ptr = (char*) __asan::asan_malloc(len, &stack); - uptr p = reinterpret_cast<uptr>(ptr); - for (uptr is_write = 0; is_write <= 1; is_write++) { - for (uptr size_log = 0; size_log <= 4; size_log++) { - uptr size = 1 << size_log; - CB call = cb[is_write][size_log]; - // Iterate only size-aligned offsets. - for (uptr offset = 0; offset <= len; offset += size) { - buggy_ptr = 0; - call(p + offset); - if (offset + size <= len) - EXPECT_EQ(buggy_ptr, 0U); - else - EXPECT_EQ(buggy_ptr, p + offset); - } - } - } - __asan::asan_free(ptr, &stack, __asan::FROM_MALLOC); - } - __asan_test_only_reported_buggy_pointer = 0; -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_oob_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_oob_test.cc deleted file mode 100644 index 0c6bea285864..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_oob_test.cc +++ /dev/null @@ -1,128 +0,0 @@ -//===-- asan_oob_test.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -NOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) { - EXPECT_EQ(0U, ((uintptr_t)p % size)); - if (size == 1) asan_write((uint8_t*)p); - else if (size == 2) asan_write((uint16_t*)p); - else if (size == 4) asan_write((uint32_t*)p); - else if (size == 8) asan_write((uint64_t*)p); -} - -template<typename T> -NOINLINE void oob_test(int size, int off) { - char *p = (char*)malloc_aaa(size); - // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n", - // sizeof(T), p, p + size, off); - asan_write((T*)(p + off)); - free_aaa(p); -} - -template<typename T> -void OOBTest() { - char expected_str[100]; - for (int size = sizeof(T); size < 20; size += 5) { - for (int i = -5; i < 0; i++) { - const char *str = - "is located.*%d byte.*to the left"; - sprintf(expected_str, str, abs(i)); - EXPECT_DEATH(oob_test<T>(size, i), expected_str); - } - - for (int i = 0; i < (int)(size - sizeof(T) + 1); i++) - oob_test<T>(size, i); - - for (int i = size - sizeof(T) + 1; i <= (int)(size + 2 * sizeof(T)); i++) { - const char *str = - "is located.*%d byte.*to the right"; - int off = i >= size ? (i - size) : 0; - // we don't catch unaligned partially OOB accesses. - if (i % sizeof(T)) continue; - sprintf(expected_str, str, off); - EXPECT_DEATH(oob_test<T>(size, i), expected_str); - } - } - - EXPECT_DEATH(oob_test<T>(kLargeMalloc, -1), - "is located.*1 byte.*to the left"); - EXPECT_DEATH(oob_test<T>(kLargeMalloc, kLargeMalloc), - "is located.*0 byte.*to the right"); -} - -// TODO(glider): the following tests are EXTREMELY slow on Darwin: -// AddressSanitizer.OOB_char (125503 ms) -// AddressSanitizer.OOB_int (126890 ms) -// AddressSanitizer.OOBRightTest (315605 ms) -// AddressSanitizer.SimpleStackTest (366559 ms) - -TEST(AddressSanitizer, OOB_char) { - OOBTest<U1>(); -} - -TEST(AddressSanitizer, OOB_int) { - OOBTest<U4>(); -} - -TEST(AddressSanitizer, OOBRightTest) { - size_t max_access_size = SANITIZER_WORDSIZE == 64 ? 8 : 4; - for (size_t access_size = 1; access_size <= max_access_size; - access_size *= 2) { - for (size_t alloc_size = 1; alloc_size <= 8; alloc_size++) { - for (size_t offset = 0; offset <= 8; offset += access_size) { - void *p = malloc(alloc_size); - // allocated: [p, p + alloc_size) - // accessed: [p + offset, p + offset + access_size) - uint8_t *addr = (uint8_t*)p + offset; - if (offset + access_size <= alloc_size) { - asan_write_sized_aligned(addr, access_size); - } else { - int outside_bytes = offset > alloc_size ? (offset - alloc_size) : 0; - const char *str = - "is located.%d *byte.*to the right"; - char expected_str[100]; - sprintf(expected_str, str, outside_bytes); - EXPECT_DEATH(asan_write_sized_aligned(addr, access_size), - expected_str); - } - free(p); - } - } - } -} - -TEST(AddressSanitizer, LargeOOBRightTest) { - size_t large_power_of_two = 1 << 19; - for (size_t i = 16; i <= 256; i *= 2) { - size_t size = large_power_of_two - i; - char *p = Ident(new char[size]); - EXPECT_DEATH(p[size] = 0, "is located 0 bytes to the right"); - delete [] p; - } -} - -TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) { - oob_test<U1>(10, -1); -} - -TEST(AddressSanitizer, DISABLED_DemoOOBLeftHigh) { - oob_test<U1>(kLargeMalloc, -1); -} - -TEST(AddressSanitizer, DISABLED_DemoOOBRightLow) { - oob_test<U1>(10, 10); -} - -TEST(AddressSanitizer, DISABLED_DemoOOBRightHigh) { - oob_test<U1>(kLargeMalloc, kLargeMalloc); -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc deleted file mode 100644 index 23240e714d56..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_racy_double_free_test.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include <pthread.h> -#include <stdlib.h> -#include <stdio.h> - -const int N = 1000; -void *x[N]; - -void *Thread1(void *unused) { - for (int i = 0; i < N; i++) { - fprintf(stderr, "%s %d\n", __func__, i); - free(x[i]); - } - return NULL; -} - -void *Thread2(void *unused) { - for (int i = 0; i < N; i++) { - fprintf(stderr, "%s %d\n", __func__, i); - free(x[i]); - } - return NULL; -} - -int main() { - for (int i = 0; i < N; i++) - x[i] = malloc(128); - pthread_t t[2]; - pthread_create(&t[0], 0, Thread1, 0); - pthread_create(&t[1], 0, Thread2, 0); - pthread_join(t[0], 0); - pthread_join(t[1], 0); -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_str_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_str_test.cc deleted file mode 100644 index 89b0d3d2d0f9..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_str_test.cc +++ /dev/null @@ -1,573 +0,0 @@ -//=-- asan_str_test.cc ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -#if defined(__APPLE__) -#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_* -#endif - -// Used for string functions tests -static char global_string[] = "global"; -static size_t global_string_length = 6; - -// Input to a test is a zero-terminated string str with given length -// Accesses to the bytes to the left and to the right of str -// are presumed to produce OOB errors -void StrLenOOBTestTemplate(char *str, size_t length, bool is_global) { - // Normal strlen calls - EXPECT_EQ(strlen(str), length); - if (length > 0) { - EXPECT_EQ(length - 1, strlen(str + 1)); - EXPECT_EQ(0U, strlen(str + length)); - } - // Arg of strlen is not malloced, OOB access - if (!is_global) { - // We don't insert RedZones to the left of global variables - EXPECT_DEATH(Ident(strlen(str - 1)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strlen(str - 5)), LeftOOBReadMessage(5)); - } - EXPECT_DEATH(Ident(strlen(str + length + 1)), RightOOBReadMessage(0)); - // Overwrite terminator - str[length] = 'a'; - // String is not zero-terminated, strlen will lead to OOB access - EXPECT_DEATH(Ident(strlen(str)), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(strlen(str + length)), RightOOBReadMessage(0)); - // Restore terminator - str[length] = 0; -} -TEST(AddressSanitizer, StrLenOOBTest) { - // Check heap-allocated string - size_t length = Ident(10); - char *heap_string = Ident((char*)malloc(length + 1)); - char stack_string[10 + 1]; - break_optimization(&stack_string); - for (size_t i = 0; i < length; i++) { - heap_string[i] = 'a'; - stack_string[i] = 'b'; - } - heap_string[length] = 0; - stack_string[length] = 0; - StrLenOOBTestTemplate(heap_string, length, false); - // TODO(samsonov): Fix expected messages in StrLenOOBTestTemplate to - // make test for stack_string work. Or move it to output tests. - // StrLenOOBTestTemplate(stack_string, length, false); - StrLenOOBTestTemplate(global_string, global_string_length, true); - free(heap_string); -} - -TEST(AddressSanitizer, WcsLenTest) { - EXPECT_EQ(0U, wcslen(Ident(L""))); - size_t hello_len = 13; - size_t hello_size = (hello_len + 1) * sizeof(wchar_t); - EXPECT_EQ(hello_len, wcslen(Ident(L"Hello, World!"))); - wchar_t *heap_string = Ident((wchar_t*)malloc(hello_size)); - memcpy(heap_string, L"Hello, World!", hello_size); - EXPECT_EQ(hello_len, Ident(wcslen(heap_string))); - EXPECT_DEATH(Ident(wcslen(heap_string + 14)), RightOOBReadMessage(0)); - free(heap_string); -} - -#if SANITIZER_TEST_HAS_STRNLEN -TEST(AddressSanitizer, StrNLenOOBTest) { - size_t size = Ident(123); - char *str = MallocAndMemsetString(size); - // Normal strnlen calls. - Ident(strnlen(str - 1, 0)); - Ident(strnlen(str, size)); - Ident(strnlen(str + size - 1, 1)); - str[size - 1] = '\0'; - Ident(strnlen(str, 2 * size)); - // Argument points to not allocated memory. - EXPECT_DEATH(Ident(strnlen(str - 1, 1)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strnlen(str + size, 1)), RightOOBReadMessage(0)); - // Overwrite the terminating '\0' and hit unallocated memory. - str[size - 1] = 'z'; - EXPECT_DEATH(Ident(strnlen(str, size + 1)), RightOOBReadMessage(0)); - free(str); -} -#endif // SANITIZER_TEST_HAS_STRNLEN - -TEST(AddressSanitizer, StrDupOOBTest) { - size_t size = Ident(42); - char *str = MallocAndMemsetString(size); - char *new_str; - // Normal strdup calls. - str[size - 1] = '\0'; - new_str = strdup(str); - free(new_str); - new_str = strdup(str + size - 1); - free(new_str); - // Argument points to not allocated memory. - EXPECT_DEATH(Ident(strdup(str - 1)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strdup(str + size)), RightOOBReadMessage(0)); - // Overwrite the terminating '\0' and hit unallocated memory. - str[size - 1] = 'z'; - EXPECT_DEATH(Ident(strdup(str)), RightOOBReadMessage(0)); - free(str); -} - -TEST(AddressSanitizer, StrCpyOOBTest) { - size_t to_size = Ident(30); - size_t from_size = Ident(6); // less than to_size - char *to = Ident((char*)malloc(to_size)); - char *from = Ident((char*)malloc(from_size)); - // Normal strcpy calls. - strcpy(from, "hello"); - strcpy(to, from); - strcpy(to + to_size - from_size, from); - // Length of "from" is too small. - EXPECT_DEATH(Ident(strcpy(from, "hello2")), RightOOBWriteMessage(0)); - // "to" or "from" points to not allocated memory. - EXPECT_DEATH(Ident(strcpy(to - 1, from)), LeftOOBWriteMessage(1)); - EXPECT_DEATH(Ident(strcpy(to, from - 1)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strcpy(to, from + from_size)), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(strcpy(to + to_size, from)), RightOOBWriteMessage(0)); - // Overwrite the terminating '\0' character and hit unallocated memory. - from[from_size - 1] = '!'; - EXPECT_DEATH(Ident(strcpy(to, from)), RightOOBReadMessage(0)); - free(to); - free(from); -} - -TEST(AddressSanitizer, StrNCpyOOBTest) { - size_t to_size = Ident(20); - size_t from_size = Ident(6); // less than to_size - char *to = Ident((char*)malloc(to_size)); - // From is a zero-terminated string "hello\0" of length 6 - char *from = Ident((char*)malloc(from_size)); - strcpy(from, "hello"); - // copy 0 bytes - strncpy(to, from, 0); - strncpy(to - 1, from - 1, 0); - // normal strncpy calls - strncpy(to, from, from_size); - strncpy(to, from, to_size); - strncpy(to, from + from_size - 1, to_size); - strncpy(to + to_size - 1, from, 1); - // One of {to, from} points to not allocated memory - EXPECT_DEATH(Ident(strncpy(to, from - 1, from_size)), - LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strncpy(to - 1, from, from_size)), - LeftOOBWriteMessage(1)); - EXPECT_DEATH(Ident(strncpy(to, from + from_size, 1)), - RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(strncpy(to + to_size, from, 1)), - RightOOBWriteMessage(0)); - // Length of "to" is too small - EXPECT_DEATH(Ident(strncpy(to + to_size - from_size + 1, from, from_size)), - RightOOBWriteMessage(0)); - EXPECT_DEATH(Ident(strncpy(to + 1, from, to_size)), - RightOOBWriteMessage(0)); - // Overwrite terminator in from - from[from_size - 1] = '!'; - // normal strncpy call - strncpy(to, from, from_size); - // Length of "from" is too small - EXPECT_DEATH(Ident(strncpy(to, from, to_size)), - RightOOBReadMessage(0)); - free(to); - free(from); -} - -// Users may have different definitions of "strchr" and "index", so provide -// function pointer typedefs and overload RunStrChrTest implementation. -// We can't use macro for RunStrChrTest body here, as this macro would -// confuse EXPECT_DEATH gtest macro. -typedef char*(*PointerToStrChr1)(const char*, int); -typedef char*(*PointerToStrChr2)(char*, int); - -UNUSED static void RunStrChrTest(PointerToStrChr1 StrChr) { - size_t size = Ident(100); - char *str = MallocAndMemsetString(size); - str[10] = 'q'; - str[11] = '\0'; - EXPECT_EQ(str, StrChr(str, 'z')); - EXPECT_EQ(str + 10, StrChr(str, 'q')); - EXPECT_EQ(NULL, StrChr(str, 'a')); - // StrChr argument points to not allocated memory. - EXPECT_DEATH(Ident(StrChr(str - 1, 'z')), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrChr(str + size, 'z')), RightOOBReadMessage(0)); - // Overwrite the terminator and hit not allocated memory. - str[11] = 'z'; - EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0)); - free(str); -} -UNUSED static void RunStrChrTest(PointerToStrChr2 StrChr) { - size_t size = Ident(100); - char *str = MallocAndMemsetString(size); - str[10] = 'q'; - str[11] = '\0'; - EXPECT_EQ(str, StrChr(str, 'z')); - EXPECT_EQ(str + 10, StrChr(str, 'q')); - EXPECT_EQ(NULL, StrChr(str, 'a')); - // StrChr argument points to not allocated memory. - EXPECT_DEATH(Ident(StrChr(str - 1, 'z')), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrChr(str + size, 'z')), RightOOBReadMessage(0)); - // Overwrite the terminator and hit not allocated memory. - str[11] = 'z'; - EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0)); - free(str); -} - -TEST(AddressSanitizer, StrChrAndIndexOOBTest) { - RunStrChrTest(&strchr); -// No index() on Windows and on Android L. -#if !defined(_WIN32) && !defined(__ANDROID__) - RunStrChrTest(&index); -#endif -} - -TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) { - // strcmp - EXPECT_EQ(0, strcmp("", "")); - EXPECT_EQ(0, strcmp("abcd", "abcd")); - EXPECT_GT(0, strcmp("ab", "ac")); - EXPECT_GT(0, strcmp("abc", "abcd")); - EXPECT_LT(0, strcmp("acc", "abc")); - EXPECT_LT(0, strcmp("abcd", "abc")); - - // strncmp - EXPECT_EQ(0, strncmp("a", "b", 0)); - EXPECT_EQ(0, strncmp("abcd", "abcd", 10)); - EXPECT_EQ(0, strncmp("abcd", "abcef", 3)); - EXPECT_GT(0, strncmp("abcde", "abcfa", 4)); - EXPECT_GT(0, strncmp("a", "b", 5)); - EXPECT_GT(0, strncmp("bc", "bcde", 4)); - EXPECT_LT(0, strncmp("xyz", "xyy", 10)); - EXPECT_LT(0, strncmp("baa", "aaa", 1)); - EXPECT_LT(0, strncmp("zyx", "", 2)); - -#if !defined(_WIN32) // no str[n]casecmp on Windows. - // strcasecmp - EXPECT_EQ(0, strcasecmp("", "")); - EXPECT_EQ(0, strcasecmp("zzz", "zzz")); - EXPECT_EQ(0, strcasecmp("abCD", "ABcd")); - EXPECT_GT(0, strcasecmp("aB", "Ac")); - EXPECT_GT(0, strcasecmp("ABC", "ABCd")); - EXPECT_LT(0, strcasecmp("acc", "abc")); - EXPECT_LT(0, strcasecmp("ABCd", "abc")); - - // strncasecmp - EXPECT_EQ(0, strncasecmp("a", "b", 0)); - EXPECT_EQ(0, strncasecmp("abCD", "ABcd", 10)); - EXPECT_EQ(0, strncasecmp("abCd", "ABcef", 3)); - EXPECT_GT(0, strncasecmp("abcde", "ABCfa", 4)); - EXPECT_GT(0, strncasecmp("a", "B", 5)); - EXPECT_GT(0, strncasecmp("bc", "BCde", 4)); - EXPECT_LT(0, strncasecmp("xyz", "xyy", 10)); - EXPECT_LT(0, strncasecmp("Baa", "aaa", 1)); - EXPECT_LT(0, strncasecmp("zyx", "", 2)); -#endif - - // memcmp - EXPECT_EQ(0, memcmp("a", "b", 0)); - EXPECT_EQ(0, memcmp("ab\0c", "ab\0c", 4)); - EXPECT_GT(0, memcmp("\0ab", "\0ac", 3)); - EXPECT_GT(0, memcmp("abb\0", "abba", 4)); - EXPECT_LT(0, memcmp("ab\0cd", "ab\0c\0", 5)); - EXPECT_LT(0, memcmp("zza", "zyx", 3)); -} - -typedef int(*PointerToStrCmp)(const char*, const char*); -void RunStrCmpTest(PointerToStrCmp StrCmp) { - size_t size = Ident(100); - int fill = 'o'; - char *s1 = MallocAndMemsetString(size, fill); - char *s2 = MallocAndMemsetString(size, fill); - s1[size - 1] = '\0'; - s2[size - 1] = '\0'; - // Normal StrCmp calls - Ident(StrCmp(s1, s2)); - Ident(StrCmp(s1, s2 + size - 1)); - Ident(StrCmp(s1 + size - 1, s2 + size - 1)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(Ident(StrCmp)(s1 - 1, s2), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrCmp)(s1, s2 - 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrCmp)(s1 + size, s2), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrCmp)(s1, s2 + size), RightOOBReadMessage(0)); - // Hit unallocated memory and die. - s1[size - 1] = fill; - EXPECT_DEATH(Ident(StrCmp)(s1, s1), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrCmp)(s1 + size - 1, s2), RightOOBReadMessage(0)); - free(s1); - free(s2); -} - -TEST(AddressSanitizer, StrCmpOOBTest) { - RunStrCmpTest(&strcmp); -} - -#if !defined(_WIN32) // no str[n]casecmp on Windows. -TEST(AddressSanitizer, StrCaseCmpOOBTest) { - RunStrCmpTest(&strcasecmp); -} -#endif - -typedef int(*PointerToStrNCmp)(const char*, const char*, size_t); -void RunStrNCmpTest(PointerToStrNCmp StrNCmp) { - size_t size = Ident(100); - char *s1 = MallocAndMemsetString(size); - char *s2 = MallocAndMemsetString(size); - s1[size - 1] = '\0'; - s2[size - 1] = '\0'; - // Normal StrNCmp calls - Ident(StrNCmp(s1, s2, size + 2)); - s1[size - 1] = 'z'; - s2[size - 1] = 'x'; - Ident(StrNCmp(s1 + size - 2, s2 + size - 2, size)); - s2[size - 1] = 'z'; - Ident(StrNCmp(s1 - 1, s2 - 1, 0)); - Ident(StrNCmp(s1 + size - 1, s2 + size - 1, 1)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(Ident(StrNCmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrNCmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrNCmp)(s1 + size, s2, 1), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrNCmp)(s1, s2 + size, 1), RightOOBReadMessage(0)); - // Hit unallocated memory and die. - EXPECT_DEATH(Ident(StrNCmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrNCmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0)); - free(s1); - free(s2); -} - -TEST(AddressSanitizer, StrNCmpOOBTest) { - RunStrNCmpTest(&strncmp); -} - -#if !defined(_WIN32) // no str[n]casecmp on Windows. -TEST(AddressSanitizer, StrNCaseCmpOOBTest) { - RunStrNCmpTest(&strncasecmp); -} -#endif - -TEST(AddressSanitizer, StrCatOOBTest) { - // strcat() reads strlen(to) bytes from |to| before concatenating. - size_t to_size = Ident(100); - char *to = MallocAndMemsetString(to_size); - to[0] = '\0'; - size_t from_size = Ident(20); - char *from = MallocAndMemsetString(from_size); - from[from_size - 1] = '\0'; - // Normal strcat calls. - strcat(to, from); - strcat(to, from); - strcat(to + from_size, from + from_size - 2); - // Passing an invalid pointer is an error even when concatenating an empty - // string. - EXPECT_DEATH(strcat(to - 1, from + from_size - 1), LeftOOBAccessMessage(1)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(strcat(to - 1, from), LeftOOBAccessMessage(1)); - EXPECT_DEATH(strcat(to, from - 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(strcat(to, from + from_size), RightOOBReadMessage(0)); - - // "from" is not zero-terminated. - from[from_size - 1] = 'z'; - EXPECT_DEATH(strcat(to, from), RightOOBReadMessage(0)); - from[from_size - 1] = '\0'; - // "to" is too short to fit "from". - memset(to, 'z', to_size); - to[to_size - from_size + 1] = '\0'; - EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(0)); - // length of "to" is just enough. - strcat(to, from + 1); - - free(to); - free(from); -} - -TEST(AddressSanitizer, StrNCatOOBTest) { - // strncat() reads strlen(to) bytes from |to| before concatenating. - size_t to_size = Ident(100); - char *to = MallocAndMemsetString(to_size); - to[0] = '\0'; - size_t from_size = Ident(20); - char *from = MallocAndMemsetString(from_size); - // Normal strncat calls. - strncat(to, from, 0); - strncat(to, from, from_size); - from[from_size - 1] = '\0'; - strncat(to, from, 2 * from_size); - // Catenating empty string with an invalid string is still an error. - EXPECT_DEATH(strncat(to - 1, from, 0), LeftOOBAccessMessage(1)); - strncat(to, from + from_size - 1, 10); - // One of arguments points to not allocated memory. - EXPECT_DEATH(strncat(to - 1, from, 2), LeftOOBAccessMessage(1)); - EXPECT_DEATH(strncat(to, from - 1, 2), LeftOOBReadMessage(1)); - EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBReadMessage(0)); - - memset(from, 'z', from_size); - memset(to, 'z', to_size); - to[0] = '\0'; - // "from" is too short. - EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBReadMessage(0)); - // "to" is too short to fit "from". - to[0] = 'z'; - to[to_size - from_size + 1] = '\0'; - EXPECT_DEATH(strncat(to, from, from_size - 1), RightOOBWriteMessage(0)); - // "to" is just enough. - strncat(to, from, from_size - 2); - - free(to); - free(from); -} - -static string OverlapErrorMessage(const string &func) { - return func + "-param-overlap"; -} - -TEST(AddressSanitizer, StrArgsOverlapTest) { - size_t size = Ident(100); - char *str = Ident((char*)malloc(size)); - -// Do not check memcpy() on OS X 10.7 and later, where it actually aliases -// memmove(). -#if !defined(__APPLE__) || !defined(MAC_OS_X_VERSION_10_7) || \ - (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7) - // Check "memcpy". Use Ident() to avoid inlining. - memset(str, 'z', size); - Ident(memcpy)(str + 1, str + 11, 10); - Ident(memcpy)(str, str, 0); - EXPECT_DEATH(Ident(memcpy)(str, str + 14, 15), OverlapErrorMessage("memcpy")); - EXPECT_DEATH(Ident(memcpy)(str + 14, str, 15), OverlapErrorMessage("memcpy")); -#endif - - // We do not treat memcpy with to==from as a bug. - // See http://llvm.org/bugs/show_bug.cgi?id=11763. - // EXPECT_DEATH(Ident(memcpy)(str + 20, str + 20, 1), - // OverlapErrorMessage("memcpy")); - - // Check "strcpy". - memset(str, 'z', size); - str[9] = '\0'; - strcpy(str + 10, str); - EXPECT_DEATH(strcpy(str + 9, str), OverlapErrorMessage("strcpy")); - EXPECT_DEATH(strcpy(str, str + 4), OverlapErrorMessage("strcpy")); - strcpy(str, str + 5); - - // Check "strncpy". - memset(str, 'z', size); - strncpy(str, str + 10, 10); - EXPECT_DEATH(strncpy(str, str + 9, 10), OverlapErrorMessage("strncpy")); - EXPECT_DEATH(strncpy(str + 9, str, 10), OverlapErrorMessage("strncpy")); - str[10] = '\0'; - strncpy(str + 11, str, 20); - EXPECT_DEATH(strncpy(str + 10, str, 20), OverlapErrorMessage("strncpy")); - - // Check "strcat". - memset(str, 'z', size); - str[10] = '\0'; - str[20] = '\0'; - strcat(str, str + 10); - EXPECT_DEATH(strcat(str, str + 11), OverlapErrorMessage("strcat")); - str[10] = '\0'; - strcat(str + 11, str); - EXPECT_DEATH(strcat(str, str + 9), OverlapErrorMessage("strcat")); - EXPECT_DEATH(strcat(str + 9, str), OverlapErrorMessage("strcat")); - EXPECT_DEATH(strcat(str + 10, str), OverlapErrorMessage("strcat")); - - // Check "strncat". - memset(str, 'z', size); - str[10] = '\0'; - strncat(str, str + 10, 10); // from is empty - EXPECT_DEATH(strncat(str, str + 11, 10), OverlapErrorMessage("strncat")); - str[10] = '\0'; - str[20] = '\0'; - strncat(str + 5, str, 5); - str[10] = '\0'; - EXPECT_DEATH(strncat(str + 5, str, 6), OverlapErrorMessage("strncat")); - EXPECT_DEATH(strncat(str, str + 9, 10), OverlapErrorMessage("strncat")); - - free(str); -} - -typedef void(*PointerToCallAtoi)(const char*); - -void RunAtoiOOBTest(PointerToCallAtoi Atoi) { - char *array = MallocAndMemsetString(10, '1'); - // Invalid pointer to the string. - EXPECT_DEATH(Atoi(array + 11), RightOOBReadMessage(1)); - EXPECT_DEATH(Atoi(array - 1), LeftOOBReadMessage(1)); - // Die if a buffer doesn't have terminating NULL. - EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0)); - // Make last symbol a terminating NULL - array[9] = '\0'; - Atoi(array); - // Sometimes we need to detect overflow if no digits are found. - memset(array, ' ', 10); - EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0)); - array[9] = '-'; - EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0)); - EXPECT_DEATH(Atoi(array + 9), RightOOBReadMessage(0)); - free(array); -} - -#if !defined(_WIN32) // FIXME: Fix and enable on Windows. -void CallAtoi(const char *nptr) { - Ident(atoi(nptr)); -} -void CallAtol(const char *nptr) { - Ident(atol(nptr)); -} -void CallAtoll(const char *nptr) { - Ident(atoll(nptr)); -} -TEST(AddressSanitizer, AtoiAndFriendsOOBTest) { - RunAtoiOOBTest(&CallAtoi); - RunAtoiOOBTest(&CallAtol); - RunAtoiOOBTest(&CallAtoll); -} -#endif - -typedef void(*PointerToCallStrtol)(const char*, char**, int); - -void RunStrtolOOBTest(PointerToCallStrtol Strtol) { - char *array = MallocAndMemsetString(3); - array[0] = '1'; - array[1] = '2'; - array[2] = '3'; - // Invalid pointer to the string. - EXPECT_DEATH(Strtol(array + 3, NULL, 0), RightOOBReadMessage(0)); - EXPECT_DEATH(Strtol(array - 1, NULL, 0), LeftOOBReadMessage(1)); - // Buffer overflow if there is no terminating null (depends on base). - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - array[2] = 'z'; - EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBReadMessage(0)); - // Add terminating zero to get rid of overflow. - array[2] = '\0'; - Strtol(array, NULL, 36); - // Sometimes we need to detect overflow if no digits are found. - array[0] = array[1] = array[2] = ' '; - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - array[2] = '+'; - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - array[2] = '-'; - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - free(array); -} - -#if !defined(_WIN32) // FIXME: Fix and enable on Windows. -void CallStrtol(const char *nptr, char **endptr, int base) { - Ident(strtol(nptr, endptr, base)); -} -void CallStrtoll(const char *nptr, char **endptr, int base) { - Ident(strtoll(nptr, endptr, base)); -} -TEST(AddressSanitizer, StrtollOOBTest) { - RunStrtolOOBTest(&CallStrtoll); -} -TEST(AddressSanitizer, StrtolOOBTest) { - RunStrtolOOBTest(&CallStrtol); -} -#endif - - diff --git a/contrib/compiler-rt/lib/asan/tests/asan_test.cc b/contrib/compiler-rt/lib/asan/tests/asan_test.cc deleted file mode 100644 index 07d59e09a72f..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_test.cc +++ /dev/null @@ -1,1319 +0,0 @@ -//===-- asan_test.cc ------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -NOINLINE void *malloc_fff(size_t size) { - void *res = malloc/**/(size); break_optimization(0); return res;} -NOINLINE void *malloc_eee(size_t size) { - void *res = malloc_fff(size); break_optimization(0); return res;} -NOINLINE void *malloc_ddd(size_t size) { - void *res = malloc_eee(size); break_optimization(0); return res;} -NOINLINE void *malloc_ccc(size_t size) { - void *res = malloc_ddd(size); break_optimization(0); return res;} -NOINLINE void *malloc_bbb(size_t size) { - void *res = malloc_ccc(size); break_optimization(0); return res;} -NOINLINE void *malloc_aaa(size_t size) { - void *res = malloc_bbb(size); break_optimization(0); return res;} - -NOINLINE void free_ccc(void *p) { free(p); break_optimization(0);} -NOINLINE void free_bbb(void *p) { free_ccc(p); break_optimization(0);} -NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);} - -template<typename T> -NOINLINE void uaf_test(int size, int off) { - void *p = malloc_aaa(size); - free_aaa(p); - for (int i = 1; i < 100; i++) - free_aaa(malloc_aaa(i)); - fprintf(stderr, "writing %ld byte(s) at %p with offset %d\n", - (long)sizeof(T), p, off); - asan_write((T *)((char *)p + off)); -} - -TEST(AddressSanitizer, HasFeatureAddressSanitizerTest) { -#if defined(__has_feature) && __has_feature(address_sanitizer) - bool asan = 1; -#elif defined(__SANITIZE_ADDRESS__) - bool asan = 1; -#else - bool asan = 0; -#endif - EXPECT_EQ(true, asan); -} - -TEST(AddressSanitizer, SimpleDeathTest) { - EXPECT_DEATH(exit(1), ""); -} - -TEST(AddressSanitizer, VariousMallocsTest) { - int *a = (int*)malloc(100 * sizeof(int)); - a[50] = 0; - free(a); - - int *r = (int*)malloc(10); - r = (int*)realloc(r, 2000 * sizeof(int)); - r[1000] = 0; - free(r); - - int *b = new int[100]; - b[50] = 0; - delete [] b; - - int *c = new int; - *c = 0; - delete c; - -#if SANITIZER_TEST_HAS_POSIX_MEMALIGN - int *pm; - int pm_res = posix_memalign((void**)&pm, kPageSize, kPageSize); - EXPECT_EQ(0, pm_res); - free(pm); -#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN - -#if SANITIZER_TEST_HAS_MEMALIGN - int *ma = (int*)memalign(kPageSize, kPageSize); - EXPECT_EQ(0U, (uintptr_t)ma % kPageSize); - ma[123] = 0; - free(ma); -#endif // SANITIZER_TEST_HAS_MEMALIGN -} - -TEST(AddressSanitizer, CallocTest) { - int *a = (int*)calloc(100, sizeof(int)); - EXPECT_EQ(0, a[10]); - free(a); -} - -TEST(AddressSanitizer, CallocReturnsZeroMem) { - size_t sizes[] = {16, 1000, 10000, 100000, 2100000}; - for (size_t s = 0; s < sizeof(sizes)/sizeof(sizes[0]); s++) { - size_t size = sizes[s]; - for (size_t iter = 0; iter < 5; iter++) { - char *x = Ident((char*)calloc(1, size)); - EXPECT_EQ(x[0], 0); - EXPECT_EQ(x[size - 1], 0); - EXPECT_EQ(x[size / 2], 0); - EXPECT_EQ(x[size / 3], 0); - EXPECT_EQ(x[size / 4], 0); - memset(x, 0x42, size); - free(Ident(x)); -#if !defined(_WIN32) - // FIXME: OOM on Windows. We should just make this a lit test - // with quarantine size set to 1. - free(Ident(malloc(Ident(1 << 27)))); // Try to drain the quarantine. -#endif - } - } -} - -// No valloc on Windows or Android. -#if !defined(_WIN32) && !defined(__ANDROID__) -TEST(AddressSanitizer, VallocTest) { - void *a = valloc(100); - EXPECT_EQ(0U, (uintptr_t)a % kPageSize); - free(a); -} -#endif - -#if SANITIZER_TEST_HAS_PVALLOC -TEST(AddressSanitizer, PvallocTest) { - char *a = (char*)pvalloc(kPageSize + 100); - EXPECT_EQ(0U, (uintptr_t)a % kPageSize); - a[kPageSize + 101] = 1; // we should not report an error here. - free(a); - - a = (char*)pvalloc(0); // pvalloc(0) should allocate at least one page. - EXPECT_EQ(0U, (uintptr_t)a % kPageSize); - a[101] = 1; // we should not report an error here. - free(a); -} -#endif // SANITIZER_TEST_HAS_PVALLOC - -#if !defined(_WIN32) -// FIXME: Use an equivalent of pthread_setspecific on Windows. -void *TSDWorker(void *test_key) { - if (test_key) { - pthread_setspecific(*(pthread_key_t*)test_key, (void*)0xfeedface); - } - return NULL; -} - -void TSDDestructor(void *tsd) { - // Spawning a thread will check that the current thread id is not -1. - pthread_t th; - PTHREAD_CREATE(&th, NULL, TSDWorker, NULL); - PTHREAD_JOIN(th, NULL); -} - -// This tests triggers the thread-specific data destruction fiasco which occurs -// if we don't manage the TSD destructors ourselves. We create a new pthread -// key with a non-NULL destructor which is likely to be put after the destructor -// of AsanThread in the list of destructors. -// In this case the TSD for AsanThread will be destroyed before TSDDestructor -// is called for the child thread, and a CHECK will fail when we call -// pthread_create() to spawn the grandchild. -TEST(AddressSanitizer, DISABLED_TSDTest) { - pthread_t th; - pthread_key_t test_key; - pthread_key_create(&test_key, TSDDestructor); - PTHREAD_CREATE(&th, NULL, TSDWorker, &test_key); - PTHREAD_JOIN(th, NULL); - pthread_key_delete(test_key); -} -#endif - -TEST(AddressSanitizer, UAF_char) { - const char *uaf_string = "AddressSanitizer:.*heap-use-after-free"; - EXPECT_DEATH(uaf_test<U1>(1, 0), uaf_string); - EXPECT_DEATH(uaf_test<U1>(10, 0), uaf_string); - EXPECT_DEATH(uaf_test<U1>(10, 10), uaf_string); - EXPECT_DEATH(uaf_test<U1>(kLargeMalloc, 0), uaf_string); - EXPECT_DEATH(uaf_test<U1>(kLargeMalloc, kLargeMalloc / 2), uaf_string); -} - -TEST(AddressSanitizer, UAF_long_double) { - if (sizeof(long double) == sizeof(double)) return; - long double *p = Ident(new long double[10]); - EXPECT_DEATH(Ident(p)[12] = 0, "WRITE of size 1[026]"); - EXPECT_DEATH(Ident(p)[0] = Ident(p)[12], "READ of size 1[026]"); - delete [] Ident(p); -} - -#if !defined(_WIN32) -struct Packed5 { - int x; - char c; -} __attribute__((packed)); -#else -# pragma pack(push, 1) -struct Packed5 { - int x; - char c; -}; -# pragma pack(pop) -#endif - -TEST(AddressSanitizer, UAF_Packed5) { - static_assert(sizeof(Packed5) == 5, "Please check the keywords used"); - Packed5 *p = Ident(new Packed5[2]); - EXPECT_DEATH(p[0] = p[3], "READ of size 5"); - EXPECT_DEATH(p[3] = p[0], "WRITE of size 5"); - delete [] Ident(p); -} - -#if ASAN_HAS_BLACKLIST -TEST(AddressSanitizer, IgnoreTest) { - int *x = Ident(new int); - delete Ident(x); - *x = 0; -} -#endif // ASAN_HAS_BLACKLIST - -struct StructWithBitField { - int bf1:1; - int bf2:1; - int bf3:1; - int bf4:29; -}; - -TEST(AddressSanitizer, BitFieldPositiveTest) { - StructWithBitField *x = new StructWithBitField; - delete Ident(x); - EXPECT_DEATH(x->bf1 = 0, "use-after-free"); - EXPECT_DEATH(x->bf2 = 0, "use-after-free"); - EXPECT_DEATH(x->bf3 = 0, "use-after-free"); - EXPECT_DEATH(x->bf4 = 0, "use-after-free"); -} - -struct StructWithBitFields_8_24 { - int a:8; - int b:24; -}; - -TEST(AddressSanitizer, BitFieldNegativeTest) { - StructWithBitFields_8_24 *x = Ident(new StructWithBitFields_8_24); - x->a = 0; - x->b = 0; - delete Ident(x); -} - -#if ASAN_NEEDS_SEGV -namespace { - -const char kUnknownCrash[] = "AddressSanitizer: SEGV on unknown address"; -const char kOverriddenHandler[] = "ASan signal handler has been overridden\n"; - -TEST(AddressSanitizer, WildAddressTest) { - char *c = (char*)0x123; - EXPECT_DEATH(*c = 0, kUnknownCrash); -} - -void my_sigaction_sighandler(int, siginfo_t*, void*) { - fprintf(stderr, kOverriddenHandler); - exit(1); -} - -void my_signal_sighandler(int signum) { - fprintf(stderr, kOverriddenHandler); - exit(1); -} - -TEST(AddressSanitizer, SignalTest) { - struct sigaction sigact; - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_sigaction = my_sigaction_sighandler; - sigact.sa_flags = SA_SIGINFO; - // ASan should silently ignore sigaction()... - EXPECT_EQ(0, sigaction(SIGSEGV, &sigact, 0)); -#ifdef __APPLE__ - EXPECT_EQ(0, sigaction(SIGBUS, &sigact, 0)); -#endif - char *c = (char*)0x123; - EXPECT_DEATH(*c = 0, kUnknownCrash); - // ... and signal(). - EXPECT_EQ(0, signal(SIGSEGV, my_signal_sighandler)); - EXPECT_DEATH(*c = 0, kUnknownCrash); -} -} // namespace -#endif - -static void TestLargeMalloc(size_t size) { - char buff[1024]; - sprintf(buff, "is located 1 bytes to the left of %lu-byte", (long)size); - EXPECT_DEATH(Ident((char*)malloc(size))[-1] = 0, buff); -} - -TEST(AddressSanitizer, LargeMallocTest) { - const int max_size = (SANITIZER_WORDSIZE == 32) ? 1 << 26 : 1 << 28; - for (int i = 113; i < max_size; i = i * 2 + 13) { - TestLargeMalloc(i); - } -} - -TEST(AddressSanitizer, HugeMallocTest) { - if (SANITIZER_WORDSIZE != 64 || ASAN_AVOID_EXPENSIVE_TESTS) return; - size_t n_megs = 4100; - EXPECT_DEATH(Ident((char*)malloc(n_megs << 20))[-1] = 0, - "is located 1 bytes to the left|" - "AddressSanitizer failed to allocate"); -} - -#if SANITIZER_TEST_HAS_MEMALIGN -void MemalignRun(size_t align, size_t size, int idx) { - char *p = (char *)memalign(align, size); - Ident(p)[idx] = 0; - free(p); -} - -TEST(AddressSanitizer, memalign) { - for (int align = 16; align <= (1 << 23); align *= 2) { - size_t size = align * 5; - EXPECT_DEATH(MemalignRun(align, size, -1), - "is located 1 bytes to the left"); - EXPECT_DEATH(MemalignRun(align, size, size + 1), - "is located 1 bytes to the right"); - } -} -#endif // SANITIZER_TEST_HAS_MEMALIGN - -void *ManyThreadsWorker(void *a) { - for (int iter = 0; iter < 100; iter++) { - for (size_t size = 100; size < 2000; size *= 2) { - free(Ident(malloc(size))); - } - } - return 0; -} - -TEST(AddressSanitizer, ManyThreadsTest) { - const size_t kNumThreads = - (SANITIZER_WORDSIZE == 32 || ASAN_AVOID_EXPENSIVE_TESTS) ? 30 : 1000; - pthread_t t[kNumThreads]; - for (size_t i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, ManyThreadsWorker, (void*)i); - } - for (size_t i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} - -TEST(AddressSanitizer, ReallocTest) { - const int kMinElem = 5; - int *ptr = (int*)malloc(sizeof(int) * kMinElem); - ptr[3] = 3; - for (int i = 0; i < 10000; i++) { - ptr = (int*)realloc(ptr, - (my_rand() % 1000 + kMinElem) * sizeof(int)); - EXPECT_EQ(3, ptr[3]); - } - free(ptr); - // Realloc pointer returned by malloc(0). - int *ptr2 = Ident((int*)malloc(0)); - ptr2 = Ident((int*)realloc(ptr2, sizeof(*ptr2))); - *ptr2 = 42; - EXPECT_EQ(42, *ptr2); - free(ptr2); -} - -TEST(AddressSanitizer, ReallocFreedPointerTest) { - void *ptr = Ident(malloc(42)); - ASSERT_TRUE(NULL != ptr); - free(ptr); - EXPECT_DEATH(ptr = realloc(ptr, 77), "attempting double-free"); -} - -TEST(AddressSanitizer, ReallocInvalidPointerTest) { - void *ptr = Ident(malloc(42)); - EXPECT_DEATH(ptr = realloc((int*)ptr + 1, 77), "attempting free.*not malloc"); - free(ptr); -} - -TEST(AddressSanitizer, ZeroSizeMallocTest) { - // Test that malloc(0) and similar functions don't return NULL. - void *ptr = Ident(malloc(0)); - EXPECT_TRUE(NULL != ptr); - free(ptr); -#if SANITIZER_TEST_HAS_POSIX_MEMALIGN - int pm_res = posix_memalign(&ptr, 1<<20, 0); - EXPECT_EQ(0, pm_res); - EXPECT_TRUE(NULL != ptr); - free(ptr); -#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN - int *int_ptr = new int[0]; - int *int_ptr2 = new int[0]; - EXPECT_TRUE(NULL != int_ptr); - EXPECT_TRUE(NULL != int_ptr2); - EXPECT_NE(int_ptr, int_ptr2); - delete[] int_ptr; - delete[] int_ptr2; -} - -#if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE -static const char *kMallocUsableSizeErrorMsg = - "AddressSanitizer: attempting to call malloc_usable_size()"; - -TEST(AddressSanitizer, MallocUsableSizeTest) { - const size_t kArraySize = 100; - char *array = Ident((char*)malloc(kArraySize)); - int *int_ptr = Ident(new int); - EXPECT_EQ(0U, malloc_usable_size(NULL)); - EXPECT_EQ(kArraySize, malloc_usable_size(array)); - EXPECT_EQ(sizeof(int), malloc_usable_size(int_ptr)); - EXPECT_DEATH(malloc_usable_size((void*)0x123), kMallocUsableSizeErrorMsg); - EXPECT_DEATH(malloc_usable_size(array + kArraySize / 2), - kMallocUsableSizeErrorMsg); - free(array); - EXPECT_DEATH(malloc_usable_size(array), kMallocUsableSizeErrorMsg); - delete int_ptr; -} -#endif // SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE - -void WrongFree() { - int *x = (int*)malloc(100 * sizeof(int)); - // Use the allocated memory, otherwise Clang will optimize it out. - Ident(x); - free(x + 1); -} - -#if !defined(_WIN32) // FIXME: This should be a lit test. -TEST(AddressSanitizer, WrongFreeTest) { - EXPECT_DEATH(WrongFree(), ASAN_PCRE_DOTALL - "ERROR: AddressSanitizer: attempting free.*not malloc" - ".*is located 4 bytes inside of 400-byte region" - ".*allocated by thread"); -} -#endif - -void DoubleFree() { - int *x = (int*)malloc(100 * sizeof(int)); - fprintf(stderr, "DoubleFree: x=%p\n", (void *)x); - free(x); - free(x); - fprintf(stderr, "should have failed in the second free(%p)\n", (void *)x); - abort(); -} - -#if !defined(_WIN32) // FIXME: This should be a lit test. -TEST(AddressSanitizer, DoubleFreeTest) { - EXPECT_DEATH(DoubleFree(), ASAN_PCRE_DOTALL - "ERROR: AddressSanitizer: attempting double-free" - ".*is located 0 bytes inside of 400-byte region" - ".*freed by thread T0 here" - ".*previously allocated by thread T0 here"); -} -#endif - -template<int kSize> -NOINLINE void SizedStackTest() { - char a[kSize]; - char *A = Ident((char*)&a); - const char *expected_death = "AddressSanitizer: stack-buffer-"; - for (size_t i = 0; i < kSize; i++) - A[i] = i; - EXPECT_DEATH(A[-1] = 0, expected_death); - EXPECT_DEATH(A[-5] = 0, expected_death); - EXPECT_DEATH(A[kSize] = 0, expected_death); - EXPECT_DEATH(A[kSize + 1] = 0, expected_death); - EXPECT_DEATH(A[kSize + 5] = 0, expected_death); - if (kSize > 16) - EXPECT_DEATH(A[kSize + 31] = 0, expected_death); -} - -TEST(AddressSanitizer, SimpleStackTest) { - SizedStackTest<1>(); - SizedStackTest<2>(); - SizedStackTest<3>(); - SizedStackTest<4>(); - SizedStackTest<5>(); - SizedStackTest<6>(); - SizedStackTest<7>(); - SizedStackTest<16>(); - SizedStackTest<25>(); - SizedStackTest<34>(); - SizedStackTest<43>(); - SizedStackTest<51>(); - SizedStackTest<62>(); - SizedStackTest<64>(); - SizedStackTest<128>(); -} - -#if !defined(_WIN32) -// FIXME: It's a bit hard to write multi-line death test expectations -// in a portable way. Anyways, this should just be turned into a lit test. -TEST(AddressSanitizer, ManyStackObjectsTest) { - char XXX[10]; - char YYY[20]; - char ZZZ[30]; - Ident(XXX); - Ident(YYY); - EXPECT_DEATH(Ident(ZZZ)[-1] = 0, ASAN_PCRE_DOTALL "XXX.*YYY.*ZZZ"); -} -#endif - -#if 0 // This test requires online symbolizer. -// Moved to lit_tests/stack-oob-frames.cc. -// Reenable here once we have online symbolizer by default. -NOINLINE static void Frame0(int frame, char *a, char *b, char *c) { - char d[4] = {0}; - char *D = Ident(d); - switch (frame) { - case 3: a[5]++; break; - case 2: b[5]++; break; - case 1: c[5]++; break; - case 0: D[5]++; break; - } -} -NOINLINE static void Frame1(int frame, char *a, char *b) { - char c[4] = {0}; Frame0(frame, a, b, c); - break_optimization(0); -} -NOINLINE static void Frame2(int frame, char *a) { - char b[4] = {0}; Frame1(frame, a, b); - break_optimization(0); -} -NOINLINE static void Frame3(int frame) { - char a[4] = {0}; Frame2(frame, a); - break_optimization(0); -} - -TEST(AddressSanitizer, GuiltyStackFrame0Test) { - EXPECT_DEATH(Frame3(0), "located .*in frame <.*Frame0"); -} -TEST(AddressSanitizer, GuiltyStackFrame1Test) { - EXPECT_DEATH(Frame3(1), "located .*in frame <.*Frame1"); -} -TEST(AddressSanitizer, GuiltyStackFrame2Test) { - EXPECT_DEATH(Frame3(2), "located .*in frame <.*Frame2"); -} -TEST(AddressSanitizer, GuiltyStackFrame3Test) { - EXPECT_DEATH(Frame3(3), "located .*in frame <.*Frame3"); -} -#endif - -NOINLINE void LongJmpFunc1(jmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - longjmp(buf, 1); -} - -NOINLINE void TouchStackFunc() { - int a[100]; // long array will intersect with redzones from LongJmpFunc1. - int *A = Ident(a); - for (int i = 0; i < 100; i++) - A[i] = i*i; -} - -// Test that we handle longjmp and do not report false positives on stack. -TEST(AddressSanitizer, LongJmpTest) { - static jmp_buf buf; - if (!setjmp(buf)) { - LongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} - -#if !defined(_WIN32) // Only basic longjmp is available on Windows. -NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - _longjmp(buf, 1); -} - -NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - siglongjmp(buf, 1); -} - -#if !defined(__ANDROID__) && !defined(__arm__) && \ - !defined(__powerpc64__) && !defined(__powerpc__) && \ - !defined(__aarch64__) && !defined(__mips__) && \ - !defined(__mips64) -NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - __builtin_longjmp((void**)buf, 1); -} - -// Does not work on Power and ARM: -// https://code.google.com/p/address-sanitizer/issues/detail?id=185 -TEST(AddressSanitizer, BuiltinLongJmpTest) { - static jmp_buf buf; - if (!__builtin_setjmp((void**)buf)) { - BuiltinLongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} -#endif // !defined(__ANDROID__) && !defined(__powerpc64__) && - // !defined(__powerpc__) && !defined(__arm__) && - // !defined(__mips__) && !defined(__mips64) - -TEST(AddressSanitizer, UnderscopeLongJmpTest) { - static jmp_buf buf; - if (!_setjmp(buf)) { - UnderscopeLongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} - -TEST(AddressSanitizer, SigLongJmpTest) { - static sigjmp_buf buf; - if (!sigsetjmp(buf, 1)) { - SigLongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} -#endif - -// FIXME: Why does clang-cl define __EXCEPTIONS? -#if defined(__EXCEPTIONS) && !defined(_WIN32) -NOINLINE void ThrowFunc() { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - ASAN_THROW(1); -} - -TEST(AddressSanitizer, CxxExceptionTest) { - if (ASAN_UAR) return; - // TODO(kcc): this test crashes on 32-bit for some reason... - if (SANITIZER_WORDSIZE == 32) return; - try { - ThrowFunc(); - } catch(...) {} - TouchStackFunc(); -} -#endif - -void *ThreadStackReuseFunc1(void *unused) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - pthread_exit(0); - return 0; -} - -void *ThreadStackReuseFunc2(void *unused) { - TouchStackFunc(); - return 0; -} - -TEST(AddressSanitizer, ThreadStackReuseTest) { - pthread_t t; - PTHREAD_CREATE(&t, 0, ThreadStackReuseFunc1, 0); - PTHREAD_JOIN(t, 0); - PTHREAD_CREATE(&t, 0, ThreadStackReuseFunc2, 0); - PTHREAD_JOIN(t, 0); -} - -#if defined(__i686__) || defined(__x86_64__) -#include <emmintrin.h> -TEST(AddressSanitizer, Store128Test) { - char *a = Ident((char*)malloc(Ident(12))); - char *p = a; - if (((uintptr_t)a % 16) != 0) - p = a + 8; - assert(((uintptr_t)p % 16) == 0); - __m128i value_wide = _mm_set1_epi16(0x1234); - EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), - "AddressSanitizer: heap-buffer-overflow"); - EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), - "WRITE of size 16"); - EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), - "located 0 bytes to the right of 12-byte"); - free(a); -} -#endif - -// FIXME: All tests that use this function should be turned into lit tests. -string RightOOBErrorMessage(int oob_distance, bool is_write) { - assert(oob_distance >= 0); - char expected_str[100]; - sprintf(expected_str, ASAN_PCRE_DOTALL -#if !GTEST_USES_SIMPLE_RE - "buffer-overflow.*%s.*" -#endif - "located %d bytes to the right", -#if !GTEST_USES_SIMPLE_RE - is_write ? "WRITE" : "READ", -#endif - oob_distance); - return string(expected_str); -} - -string RightOOBWriteMessage(int oob_distance) { - return RightOOBErrorMessage(oob_distance, /*is_write*/true); -} - -string RightOOBReadMessage(int oob_distance) { - return RightOOBErrorMessage(oob_distance, /*is_write*/false); -} - -// FIXME: All tests that use this function should be turned into lit tests. -string LeftOOBErrorMessage(int oob_distance, bool is_write) { - assert(oob_distance > 0); - char expected_str[100]; - sprintf(expected_str, -#if !GTEST_USES_SIMPLE_RE - ASAN_PCRE_DOTALL "%s.*" -#endif - "located %d bytes to the left", -#if !GTEST_USES_SIMPLE_RE - is_write ? "WRITE" : "READ", -#endif - oob_distance); - return string(expected_str); -} - -string LeftOOBWriteMessage(int oob_distance) { - return LeftOOBErrorMessage(oob_distance, /*is_write*/true); -} - -string LeftOOBReadMessage(int oob_distance) { - return LeftOOBErrorMessage(oob_distance, /*is_write*/false); -} - -string LeftOOBAccessMessage(int oob_distance) { - assert(oob_distance > 0); - char expected_str[100]; - sprintf(expected_str, "located %d bytes to the left", oob_distance); - return string(expected_str); -} - -char* MallocAndMemsetString(size_t size, char ch) { - char *s = Ident((char*)malloc(size)); - memset(s, ch, size); - return s; -} - -char* MallocAndMemsetString(size_t size) { - return MallocAndMemsetString(size, 'z'); -} - -#if defined(__linux__) && !defined(__ANDROID__) -#define READ_TEST(READ_N_BYTES) \ - char *x = new char[10]; \ - int fd = open("/proc/self/stat", O_RDONLY); \ - ASSERT_GT(fd, 0); \ - EXPECT_DEATH(READ_N_BYTES, \ - ASAN_PCRE_DOTALL \ - "AddressSanitizer: heap-buffer-overflow" \ - ".* is located 0 bytes to the right of 10-byte region"); \ - close(fd); \ - delete [] x; \ - -TEST(AddressSanitizer, pread) { - READ_TEST(pread(fd, x, 15, 0)); -} - -TEST(AddressSanitizer, pread64) { - READ_TEST(pread64(fd, x, 15, 0)); -} - -TEST(AddressSanitizer, read) { - READ_TEST(read(fd, x, 15)); -} -#endif // defined(__linux__) && !defined(__ANDROID__) - -// This test case fails -// Clang optimizes memcpy/memset calls which lead to unaligned access -TEST(AddressSanitizer, DISABLED_MemIntrinsicUnalignedAccessTest) { - int size = Ident(4096); - char *s = Ident((char*)malloc(size)); - EXPECT_DEATH(memset(s + size - 1, 0, 2), RightOOBWriteMessage(0)); - free(s); -} - -// TODO(samsonov): Add a test with malloc(0) -// TODO(samsonov): Add tests for str* and mem* functions. - -NOINLINE static int LargeFunction(bool do_bad_access) { - int *x = new int[100]; - x[0]++; - x[1]++; - x[2]++; - x[3]++; - x[4]++; - x[5]++; - x[6]++; - x[7]++; - x[8]++; - x[9]++; - - x[do_bad_access ? 100 : 0]++; int res = __LINE__; - - x[10]++; - x[11]++; - x[12]++; - x[13]++; - x[14]++; - x[15]++; - x[16]++; - x[17]++; - x[18]++; - x[19]++; - - delete[] x; - return res; -} - -// Test the we have correct debug info for the failing instruction. -// This test requires the in-process symbolizer to be enabled by default. -TEST(AddressSanitizer, DISABLED_LargeFunctionSymbolizeTest) { - int failing_line = LargeFunction(false); - char expected_warning[128]; - sprintf(expected_warning, "LargeFunction.*asan_test.*:%d", failing_line); - EXPECT_DEATH(LargeFunction(true), expected_warning); -} - -// Check that we unwind and symbolize correctly. -TEST(AddressSanitizer, DISABLED_MallocFreeUnwindAndSymbolizeTest) { - int *a = (int*)malloc_aaa(sizeof(int)); - *a = 1; - free_aaa(a); - EXPECT_DEATH(*a = 1, "free_ccc.*free_bbb.*free_aaa.*" - "malloc_fff.*malloc_eee.*malloc_ddd"); -} - -static bool TryToSetThreadName(const char *name) { -#if defined(__linux__) && defined(PR_SET_NAME) - return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); -#else - return false; -#endif -} - -void *ThreadedTestAlloc(void *a) { - EXPECT_EQ(true, TryToSetThreadName("AllocThr")); - int **p = (int**)a; - *p = new int; - return 0; -} - -void *ThreadedTestFree(void *a) { - EXPECT_EQ(true, TryToSetThreadName("FreeThr")); - int **p = (int**)a; - delete *p; - return 0; -} - -void *ThreadedTestUse(void *a) { - EXPECT_EQ(true, TryToSetThreadName("UseThr")); - int **p = (int**)a; - **p = 1; - return 0; -} - -void ThreadedTestSpawn() { - pthread_t t; - int *x; - PTHREAD_CREATE(&t, 0, ThreadedTestAlloc, &x); - PTHREAD_JOIN(t, 0); - PTHREAD_CREATE(&t, 0, ThreadedTestFree, &x); - PTHREAD_JOIN(t, 0); - PTHREAD_CREATE(&t, 0, ThreadedTestUse, &x); - PTHREAD_JOIN(t, 0); -} - -#if !defined(_WIN32) // FIXME: This should be a lit test. -TEST(AddressSanitizer, ThreadedTest) { - EXPECT_DEATH(ThreadedTestSpawn(), - ASAN_PCRE_DOTALL - "Thread T.*created" - ".*Thread T.*created" - ".*Thread T.*created"); -} -#endif - -void *ThreadedTestFunc(void *unused) { - // Check if prctl(PR_SET_NAME) is supported. Return if not. - if (!TryToSetThreadName("TestFunc")) - return 0; - EXPECT_DEATH(ThreadedTestSpawn(), - ASAN_PCRE_DOTALL - "WRITE .*thread T. .UseThr." - ".*freed by thread T. .FreeThr. here:" - ".*previously allocated by thread T. .AllocThr. here:" - ".*Thread T. .UseThr. created by T.*TestFunc" - ".*Thread T. .FreeThr. created by T" - ".*Thread T. .AllocThr. created by T" - ""); - return 0; -} - -TEST(AddressSanitizer, ThreadNamesTest) { - // Run ThreadedTestFunc in a separate thread because it tries to set a - // thread name and we don't want to change the main thread's name. - pthread_t t; - PTHREAD_CREATE(&t, 0, ThreadedTestFunc, 0); - PTHREAD_JOIN(t, 0); -} - -#if ASAN_NEEDS_SEGV -TEST(AddressSanitizer, ShadowGapTest) { -#if SANITIZER_WORDSIZE == 32 - char *addr = (char*)0x22000000; -#else -# if defined(__powerpc64__) - char *addr = (char*)0x024000800000; -# else - char *addr = (char*)0x0000100000080000; -# endif -#endif - EXPECT_DEATH(*addr = 1, "AddressSanitizer: SEGV on unknown"); -} -#endif // ASAN_NEEDS_SEGV - -extern "C" { -NOINLINE static void UseThenFreeThenUse() { - char *x = Ident((char*)malloc(8)); - *x = 1; - free_aaa(x); - *x = 2; -} -} - -TEST(AddressSanitizer, UseThenFreeThenUseTest) { - EXPECT_DEATH(UseThenFreeThenUse(), "freed by thread"); -} - -TEST(AddressSanitizer, StrDupTest) { - free(strdup(Ident("123"))); -} - -// Currently we create and poison redzone at right of global variables. -static char static110[110]; -const char ConstGlob[7] = {1, 2, 3, 4, 5, 6, 7}; -static const char StaticConstGlob[3] = {9, 8, 7}; - -TEST(AddressSanitizer, GlobalTest) { - static char func_static15[15]; - - static char fs1[10]; - static char fs2[10]; - static char fs3[10]; - - glob5[Ident(0)] = 0; - glob5[Ident(1)] = 0; - glob5[Ident(2)] = 0; - glob5[Ident(3)] = 0; - glob5[Ident(4)] = 0; - - EXPECT_DEATH(glob5[Ident(5)] = 0, - "0 bytes to the right of global variable.*glob5.* size 5"); - EXPECT_DEATH(glob5[Ident(5+6)] = 0, - "6 bytes to the right of global variable.*glob5.* size 5"); - Ident(static110); // avoid optimizations - static110[Ident(0)] = 0; - static110[Ident(109)] = 0; - EXPECT_DEATH(static110[Ident(110)] = 0, - "0 bytes to the right of global variable"); - EXPECT_DEATH(static110[Ident(110+7)] = 0, - "7 bytes to the right of global variable"); - - Ident(func_static15); // avoid optimizations - func_static15[Ident(0)] = 0; - EXPECT_DEATH(func_static15[Ident(15)] = 0, - "0 bytes to the right of global variable"); - EXPECT_DEATH(func_static15[Ident(15 + 9)] = 0, - "9 bytes to the right of global variable"); - - Ident(fs1); - Ident(fs2); - Ident(fs3); - - // We don't create left redzones, so this is not 100% guaranteed to fail. - // But most likely will. - EXPECT_DEATH(fs2[Ident(-1)] = 0, "is located.*of global variable"); - - EXPECT_DEATH(Ident(Ident(ConstGlob)[8]), - "is located 1 bytes to the right of .*ConstGlob"); - EXPECT_DEATH(Ident(Ident(StaticConstGlob)[5]), - "is located 2 bytes to the right of .*StaticConstGlob"); - - // call stuff from another file. - GlobalsTest(0); -} - -TEST(AddressSanitizer, GlobalStringConstTest) { - static const char *zoo = "FOOBAR123"; - const char *p = Ident(zoo); - EXPECT_DEATH(Ident(p[15]), "is ascii string 'FOOBAR123'"); -} - -TEST(AddressSanitizer, FileNameInGlobalReportTest) { - static char zoo[10]; - const char *p = Ident(zoo); - // The file name should be present in the report. - EXPECT_DEATH(Ident(p[15]), "zoo.*asan_test."); -} - -int *ReturnsPointerToALocalObject() { - int a = 0; - return Ident(&a); -} - -#if ASAN_UAR == 1 -TEST(AddressSanitizer, LocalReferenceReturnTest) { - int *(*f)() = Ident(ReturnsPointerToALocalObject); - int *p = f(); - // Call 'f' a few more times, 'p' should still be poisoned. - for (int i = 0; i < 32; i++) - f(); - EXPECT_DEATH(*p = 1, "AddressSanitizer: stack-use-after-return"); - EXPECT_DEATH(*p = 1, "is located.*in frame .*ReturnsPointerToALocal"); -} -#endif - -template <int kSize> -NOINLINE static void FuncWithStack() { - char x[kSize]; - Ident(x)[0] = 0; - Ident(x)[kSize-1] = 0; -} - -static void LotsOfStackReuse() { - int LargeStack[10000]; - Ident(LargeStack)[0] = 0; - for (int i = 0; i < 10000; i++) { - FuncWithStack<128 * 1>(); - FuncWithStack<128 * 2>(); - FuncWithStack<128 * 4>(); - FuncWithStack<128 * 8>(); - FuncWithStack<128 * 16>(); - FuncWithStack<128 * 32>(); - FuncWithStack<128 * 64>(); - FuncWithStack<128 * 128>(); - FuncWithStack<128 * 256>(); - FuncWithStack<128 * 512>(); - Ident(LargeStack)[0] = 0; - } -} - -TEST(AddressSanitizer, StressStackReuseTest) { - LotsOfStackReuse(); -} - -TEST(AddressSanitizer, ThreadedStressStackReuseTest) { - const int kNumThreads = 20; - pthread_t t[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))LotsOfStackReuse, 0); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} - -static void *PthreadExit(void *a) { - pthread_exit(0); - return 0; -} - -TEST(AddressSanitizer, PthreadExitTest) { - pthread_t t; - for (int i = 0; i < 1000; i++) { - PTHREAD_CREATE(&t, 0, PthreadExit, 0); - PTHREAD_JOIN(t, 0); - } -} - -// FIXME: Why does clang-cl define __EXCEPTIONS? -#if defined(__EXCEPTIONS) && !defined(_WIN32) -NOINLINE static void StackReuseAndException() { - int large_stack[1000]; - Ident(large_stack); - ASAN_THROW(1); -} - -// TODO(kcc): support exceptions with use-after-return. -TEST(AddressSanitizer, DISABLED_StressStackReuseAndExceptionsTest) { - for (int i = 0; i < 10000; i++) { - try { - StackReuseAndException(); - } catch(...) { - } - } -} -#endif - -#if !defined(_WIN32) -TEST(AddressSanitizer, MlockTest) { - EXPECT_EQ(0, mlockall(MCL_CURRENT)); - EXPECT_EQ(0, mlock((void*)0x12345, 0x5678)); - EXPECT_EQ(0, munlockall()); - EXPECT_EQ(0, munlock((void*)0x987, 0x654)); -} -#endif - -struct LargeStruct { - int foo[100]; -}; - -// Test for bug http://llvm.org/bugs/show_bug.cgi?id=11763. -// Struct copy should not cause asan warning even if lhs == rhs. -TEST(AddressSanitizer, LargeStructCopyTest) { - LargeStruct a; - *Ident(&a) = *Ident(&a); -} - -ATTRIBUTE_NO_SANITIZE_ADDRESS -static void NoSanitizeAddress() { - char *foo = new char[10]; - Ident(foo)[10] = 0; - delete [] foo; -} - -TEST(AddressSanitizer, AttributeNoSanitizeAddressTest) { - Ident(NoSanitizeAddress)(); -} - -// The new/delete/etc mismatch checks don't work on Android, -// as calls to new/delete go through malloc/free. -// OS X support is tracked here: -// https://code.google.com/p/address-sanitizer/issues/detail?id=131 -// Windows support is tracked here: -// https://code.google.com/p/address-sanitizer/issues/detail?id=309 -#if !defined(__ANDROID__) && \ - !defined(__APPLE__) && \ - !defined(_WIN32) -static string MismatchStr(const string &str) { - return string("AddressSanitizer: alloc-dealloc-mismatch \\(") + str; -} - -TEST(AddressSanitizer, AllocDeallocMismatch) { - EXPECT_DEATH(free(Ident(new int)), - MismatchStr("operator new vs free")); - EXPECT_DEATH(free(Ident(new int[2])), - MismatchStr("operator new \\[\\] vs free")); - EXPECT_DEATH(delete (Ident(new int[2])), - MismatchStr("operator new \\[\\] vs operator delete")); - EXPECT_DEATH(delete (Ident((int*)malloc(2 * sizeof(int)))), - MismatchStr("malloc vs operator delete")); - EXPECT_DEATH(delete [] (Ident(new int)), - MismatchStr("operator new vs operator delete \\[\\]")); - EXPECT_DEATH(delete [] (Ident((int*)malloc(2 * sizeof(int)))), - MismatchStr("malloc vs operator delete \\[\\]")); -} -#endif - -// ------------------ demo tests; run each one-by-one ------------- -// e.g. --gtest_filter=*DemoOOBLeftHigh --gtest_also_run_disabled_tests -TEST(AddressSanitizer, DISABLED_DemoThreadedTest) { - ThreadedTestSpawn(); -} - -void *SimpleBugOnSTack(void *x = 0) { - char a[20]; - Ident(a)[20] = 0; - return 0; -} - -TEST(AddressSanitizer, DISABLED_DemoStackTest) { - SimpleBugOnSTack(); -} - -TEST(AddressSanitizer, DISABLED_DemoThreadStackTest) { - pthread_t t; - PTHREAD_CREATE(&t, 0, SimpleBugOnSTack, 0); - PTHREAD_JOIN(t, 0); -} - -TEST(AddressSanitizer, DISABLED_DemoUAFLowIn) { - uaf_test<U1>(10, 0); -} -TEST(AddressSanitizer, DISABLED_DemoUAFLowLeft) { - uaf_test<U1>(10, -2); -} -TEST(AddressSanitizer, DISABLED_DemoUAFLowRight) { - uaf_test<U1>(10, 10); -} - -TEST(AddressSanitizer, DISABLED_DemoUAFHigh) { - uaf_test<U1>(kLargeMalloc, 0); -} - -TEST(AddressSanitizer, DISABLED_DemoOOM) { - size_t size = SANITIZER_WORDSIZE == 64 ? (size_t)(1ULL << 40) : (0xf0000000); - printf("%p\n", malloc(size)); -} - -TEST(AddressSanitizer, DISABLED_DemoDoubleFreeTest) { - DoubleFree(); -} - -TEST(AddressSanitizer, DISABLED_DemoNullDerefTest) { - int *a = 0; - Ident(a)[10] = 0; -} - -TEST(AddressSanitizer, DISABLED_DemoFunctionStaticTest) { - static char a[100]; - static char b[100]; - static char c[100]; - Ident(a); - Ident(b); - Ident(c); - Ident(a)[5] = 0; - Ident(b)[105] = 0; - Ident(a)[5] = 0; -} - -TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) { - const size_t kAllocSize = (1 << 28) - 1024; - size_t total_size = 0; - while (true) { - void *x = malloc(kAllocSize); - memset(x, 0, kAllocSize); - total_size += kAllocSize; - fprintf(stderr, "total: %ldM %p\n", (long)total_size >> 20, x); - } -} - -// http://code.google.com/p/address-sanitizer/issues/detail?id=66 -TEST(AddressSanitizer, BufferOverflowAfterManyFrees) { - for (int i = 0; i < 1000000; i++) { - delete [] (Ident(new char [8644])); - } - char *x = new char[8192]; - EXPECT_DEATH(x[Ident(8192)] = 0, "AddressSanitizer: heap-buffer-overflow"); - delete [] Ident(x); -} - - -// Test that instrumentation of stack allocations takes into account -// AllocSize of a type, and not its StoreSize (16 vs 10 bytes for long double). -// See http://llvm.org/bugs/show_bug.cgi?id=12047 for more details. -TEST(AddressSanitizer, LongDoubleNegativeTest) { - long double a, b; - static long double c; - memcpy(Ident(&a), Ident(&b), sizeof(long double)); - memcpy(Ident(&c), Ident(&b), sizeof(long double)); -} - -#if !defined(_WIN32) -TEST(AddressSanitizer, pthread_getschedparam) { - int policy; - struct sched_param param; - EXPECT_DEATH( - pthread_getschedparam(pthread_self(), &policy, Ident(¶m) + 2), - "AddressSanitizer: stack-buffer-.*flow"); - EXPECT_DEATH( - pthread_getschedparam(pthread_self(), Ident(&policy) - 1, ¶m), - "AddressSanitizer: stack-buffer-.*flow"); - int res = pthread_getschedparam(pthread_self(), &policy, ¶m); - ASSERT_EQ(0, res); -} -#endif - -#if SANITIZER_TEST_HAS_PRINTF_L -static int vsnprintf_l_wrapper(char *s, size_t n, - locale_t l, const char *format, ...) { - va_list va; - va_start(va, format); - int res = vsnprintf_l(s, n , l, format, va); - va_end(va); - return res; -} - -TEST(AddressSanitizer, snprintf_l) { - char buff[5]; - // Check that snprintf_l() works fine with Asan. - int res = snprintf_l(buff, 5, - _LIBCPP_GET_C_LOCALE, "%s", "snprintf_l()"); - EXPECT_EQ(12, res); - // Check that vsnprintf_l() works fine with Asan. - res = vsnprintf_l_wrapper(buff, 5, - _LIBCPP_GET_C_LOCALE, "%s", "vsnprintf_l()"); - EXPECT_EQ(13, res); - - EXPECT_DEATH(snprintf_l(buff, 10, - _LIBCPP_GET_C_LOCALE, "%s", "snprintf_l()"), - "AddressSanitizer: stack-buffer-overflow"); - EXPECT_DEATH(vsnprintf_l_wrapper(buff, 10, - _LIBCPP_GET_C_LOCALE, "%s", "vsnprintf_l()"), - "AddressSanitizer: stack-buffer-overflow"); -} -#endif diff --git a/contrib/compiler-rt/lib/asan/tests/asan_test.ignore b/contrib/compiler-rt/lib/asan/tests/asan_test.ignore deleted file mode 100644 index ea5c26099e75..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_test.ignore +++ /dev/null @@ -1,3 +0,0 @@ -# blacklisted functions for instrumented ASan unit test -fun:*IgnoreTest* -fun:*SomeOtherFunc* diff --git a/contrib/compiler-rt/lib/asan/tests/asan_test_config.h b/contrib/compiler-rt/lib/asan/tests/asan_test_config.h deleted file mode 100644 index 92f276307481..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_test_config.h +++ /dev/null @@ -1,54 +0,0 @@ -//===-- asan_test_config.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#if !defined(INCLUDED_FROM_ASAN_TEST_UTILS_H) -# error "This file should be included into asan_test_utils.h only" -#endif - -#ifndef ASAN_TEST_CONFIG_H -#define ASAN_TEST_CONFIG_H - -#include <vector> -#include <string> -#include <map> - -using std::string; -using std::vector; -using std::map; - -#ifndef ASAN_UAR -# error "please define ASAN_UAR" -#endif - -#ifndef ASAN_HAS_EXCEPTIONS -# error "please define ASAN_HAS_EXCEPTIONS" -#endif - -#ifndef ASAN_HAS_BLACKLIST -# error "please define ASAN_HAS_BLACKLIST" -#endif - -#ifndef ASAN_NEEDS_SEGV -# if defined(_WIN32) -# define ASAN_NEEDS_SEGV 0 -# else -# define ASAN_NEEDS_SEGV 1 -# endif -#endif - -#ifndef ASAN_AVOID_EXPENSIVE_TESTS -# define ASAN_AVOID_EXPENSIVE_TESTS 0 -#endif - -#define ASAN_PCRE_DOTALL "" - -#endif // ASAN_TEST_CONFIG_H diff --git a/contrib/compiler-rt/lib/asan/tests/asan_test_main.cc b/contrib/compiler-rt/lib/asan/tests/asan_test_main.cc deleted file mode 100644 index 1746c5f4837b..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_test_main.cc +++ /dev/null @@ -1,19 +0,0 @@ -//===-- asan_test_main.cc -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -int main(int argc, char **argv) { - testing::GTEST_FLAG(death_test_style) = "threadsafe"; - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/contrib/compiler-rt/lib/asan/tests/asan_test_utils.h b/contrib/compiler-rt/lib/asan/tests/asan_test_utils.h deleted file mode 100644 index 03d17cfb26a7..000000000000 --- a/contrib/compiler-rt/lib/asan/tests/asan_test_utils.h +++ /dev/null @@ -1,107 +0,0 @@ -//===-- asan_test_utils.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// - -#ifndef ASAN_TEST_UTILS_H -#define ASAN_TEST_UTILS_H - -#if !defined(SANITIZER_EXTERNAL_TEST_CONFIG) -# define INCLUDED_FROM_ASAN_TEST_UTILS_H -# include "asan_test_config.h" -# undef INCLUDED_FROM_ASAN_TEST_UTILS_H -#endif - -#include "sanitizer_test_utils.h" -#include "sanitizer_pthread_wrappers.h" - -#include <stdio.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <assert.h> -#include <algorithm> - -#if !defined(_WIN32) -# include <strings.h> -# include <sys/mman.h> -# include <setjmp.h> -#endif - -#ifdef __linux__ -# include <sys/prctl.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <fcntl.h> -#include <unistd.h> -#endif - -#if !defined(__APPLE__) && !defined(__FreeBSD__) -#include <malloc.h> -#endif - -#if ASAN_HAS_EXCEPTIONS -# define ASAN_THROW(x) throw (x) -#else -# define ASAN_THROW(x) -#endif - -typedef uint8_t U1; -typedef uint16_t U2; -typedef uint32_t U4; -typedef uint64_t U8; - -static const int kPageSize = 4096; - -const size_t kLargeMalloc = 1 << 24; - -extern void free_aaa(void *p); -extern void *malloc_aaa(size_t size); - -template<typename T> -NOINLINE void asan_write(T *a) { - *a = 0; -} - -string RightOOBErrorMessage(int oob_distance, bool is_write); -string RightOOBWriteMessage(int oob_distance); -string RightOOBReadMessage(int oob_distance); -string LeftOOBErrorMessage(int oob_distance, bool is_write); -string LeftOOBWriteMessage(int oob_distance); -string LeftOOBReadMessage(int oob_distance); -string LeftOOBAccessMessage(int oob_distance); -char* MallocAndMemsetString(size_t size, char ch); -char* MallocAndMemsetString(size_t size); - -extern char glob1[1]; -extern char glob2[2]; -extern char glob3[3]; -extern char glob4[4]; -extern char glob5[5]; -extern char glob6[6]; -extern char glob7[7]; -extern char glob8[8]; -extern char glob9[9]; -extern char glob10[10]; -extern char glob11[11]; -extern char glob12[12]; -extern char glob13[13]; -extern char glob14[14]; -extern char glob15[15]; -extern char glob16[16]; -extern char glob17[17]; -extern char glob1000[1000]; -extern char glob10000[10000]; -extern char glob100000[100000]; -extern int GlobalsTest(int x); - -#endif // ASAN_TEST_UTILS_H |