diff options
Diffstat (limited to 'lib/asan')
32 files changed, 687 insertions, 579 deletions
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt index d4c5c17d36a2f..28611a8a46596 100644 --- a/lib/asan/CMakeLists.txt +++ b/lib/asan/CMakeLists.txt @@ -37,9 +37,22 @@ append_no_rtti_flag(ASAN_CFLAGS)  set(ASAN_COMMON_DEFINITIONS    ASAN_HAS_EXCEPTIONS=1) +set(ASAN_DYNAMIC_LINK_FLAGS) +  if(ANDROID)    list(APPEND ASAN_COMMON_DEFINITIONS      ASAN_LOW_MEMORY=1) +# On Android, -z global does not do what it is documented to do. +# On Android, -z global moves the library ahead in the lookup order, +# placing it right after the LD_PRELOADs. This is used to compensate for the fact +# that Android linker does not look at the dependencies of the main executable +# that aren't dependencies of the current DSO when resolving symbols from said DSO. +# As a net result, this allows running ASan executables without LD_PRELOAD-ing the +# ASan runtime library. +# The above is applicable to L MR1 or newer. +  if (COMPILER_RT_HAS_Z_GLOBAL) +    list(APPEND ASAN_DYNAMIC_LINK_FLAGS -Wl,-z,global) +  endif()  endif()  set(ASAN_DYNAMIC_DEFINITIONS @@ -53,6 +66,7 @@ append_list_if(MSVC /DEBUG ASAN_DYNAMIC_CFLAGS)  append_list_if(COMPILER_RT_HAS_LIBC c ASAN_DYNAMIC_LIBS)  append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS) +append_list_if(COMPILER_RT_HAS_LIBRT rt ASAN_DYNAMIC_LIBS)  append_list_if(COMPILER_RT_HAS_LIBM m ASAN_DYNAMIC_LIBS)  append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread ASAN_DYNAMIC_LIBS)  append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ ASAN_DYNAMIC_LIBS) @@ -61,41 +75,50 @@ append_list_if(ANDROID log ASAN_DYNAMIC_LIBS)  # Compile ASan sources into an object library.  if(APPLE) -  foreach(os ${SANITIZER_COMMON_SUPPORTED_DARWIN_OS}) -    add_compiler_rt_darwin_object_library(RTAsan ${os} -      ARCH ${ASAN_SUPPORTED_ARCH} -      SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} -      CFLAGS ${ASAN_DYNAMIC_CFLAGS} -      DEFS ${ASAN_DYNAMIC_DEFINITIONS}) -  endforeach() +  add_compiler_rt_object_libraries(RTAsan +    OS ${SANITIZER_COMMON_SUPPORTED_OS} +    ARCHS ${ASAN_SUPPORTED_ARCH} +    SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} +    CFLAGS ${ASAN_DYNAMIC_CFLAGS} +    DEFS ${ASAN_DYNAMIC_DEFINITIONS})  else() -  foreach(arch ${ASAN_SUPPORTED_ARCH}) -    add_compiler_rt_object_library(RTAsan ${arch} -      SOURCES ${ASAN_SOURCES} CFLAGS ${ASAN_CFLAGS} -      DEFS ${ASAN_COMMON_DEFINITIONS}) -    add_compiler_rt_object_library(RTAsan_cxx ${arch} -      SOURCES ${ASAN_CXX_SOURCES} CFLAGS ${ASAN_CFLAGS} -      DEFS ${ASAN_COMMON_DEFINITIONS}) -    add_compiler_rt_object_library(RTAsan_preinit ${arch} -      SOURCES ${ASAN_PREINIT_SOURCES} CFLAGS ${ASAN_CFLAGS} -      DEFS ${ASAN_COMMON_DEFINITIONS}) -    add_compiler_rt_object_library(RTAsan_dynamic ${arch} -      SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} -      CFLAGS ${ASAN_DYNAMIC_CFLAGS} -      DEFS ${ASAN_DYNAMIC_DEFINITIONS}) -  endforeach() +  add_compiler_rt_object_libraries(RTAsan  +    ARCHS ${ASAN_SUPPORTED_ARCH} +    SOURCES ${ASAN_SOURCES} CFLAGS ${ASAN_CFLAGS} +    DEFS ${ASAN_COMMON_DEFINITIONS}) +  add_compiler_rt_object_libraries(RTAsan_cxx  +    ARCHS ${ASAN_SUPPORTED_ARCH} +    SOURCES ${ASAN_CXX_SOURCES} CFLAGS ${ASAN_CFLAGS} +    DEFS ${ASAN_COMMON_DEFINITIONS}) +  add_compiler_rt_object_libraries(RTAsan_preinit  +    ARCHS ${ASAN_SUPPORTED_ARCH} +    SOURCES ${ASAN_PREINIT_SOURCES} CFLAGS ${ASAN_CFLAGS} +    DEFS ${ASAN_COMMON_DEFINITIONS}) +  add_compiler_rt_object_libraries(RTAsan_dynamic  +    ARCHS ${ASAN_SUPPORTED_ARCH} +    SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} +    CFLAGS ${ASAN_DYNAMIC_CFLAGS} +    DEFS ${ASAN_DYNAMIC_DEFINITIONS}) + +  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc "") +  add_compiler_rt_object_libraries(RTAsan_dynamic_version_script_dummy +    ARCHS ${ASAN_SUPPORTED_ARCH} +    SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc +    CFLAGS ${ASAN_DYNAMIC_CFLAGS} +    DEFS ${ASAN_DYNAMIC_DEFINITIONS})  endif()  # Build ASan runtimes shipped with Clang.  add_custom_target(asan)  if(APPLE) -  foreach (os ${SANITIZER_COMMON_SUPPORTED_DARWIN_OS}) +  foreach (os ${SANITIZER_COMMON_SUPPORTED_OS})      add_compiler_rt_darwin_dynamic_runtime(clang_rt.asan_${os}_dynamic ${os} -      ARCH ${ASAN_SUPPORTED_ARCH} +      ARCHS ${ASAN_SUPPORTED_ARCH}        SOURCES $<TARGET_OBJECTS:RTAsan.${os}>                $<TARGET_OBJECTS:RTInterception.${os}>                $<TARGET_OBJECTS:RTSanitizerCommon.${os}>                $<TARGET_OBJECTS:RTLSanCommon.${os}> +              $<TARGET_OBJECTS:RTUbsan.${os}>        CFLAGS ${ASAN_DYNAMIC_CFLAGS}        DEFS ${ASAN_DYNAMIC_DEFINITIONS})      add_dependencies(asan clang_rt.asan_${os}_dynamic) @@ -106,12 +129,9 @@ else()      set(ASAN_COMMON_RUNTIME_OBJECTS        $<TARGET_OBJECTS:RTInterception.${arch}>        $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> -      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>) -    if(NOT WIN32) -      # We can't build Leak Sanitizer on Windows yet. -      list(APPEND ASAN_COMMON_RUNTIME_OBJECTS -           $<TARGET_OBJECTS:RTLSanCommon.${arch}>) -    endif() +      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> +      $<TARGET_OBJECTS:RTLSanCommon.${arch}> +      $<TARGET_OBJECTS:RTUbsan.${arch}>)      add_compiler_rt_runtime(clang_rt.asan-${arch} ${arch} STATIC        SOURCES $<TARGET_OBJECTS:RTAsan_preinit.${arch}> @@ -123,6 +143,7 @@ else()      add_compiler_rt_runtime(clang_rt.asan_cxx-${arch} ${arch} STATIC        SOURCES $<TARGET_OBJECTS:RTAsan_cxx.${arch}> +              $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>        CFLAGS ${ASAN_CFLAGS}        DEFS ${ASAN_COMMON_DEFINITIONS})      add_dependencies(asan clang_rt.asan_cxx-${arch}) @@ -133,6 +154,20 @@ else()        DEFS ${ASAN_COMMON_DEFINITIONS})      add_dependencies(asan clang_rt.asan-preinit-${arch}) +    if (UNIX AND NOT ${arch} MATCHES "i386|i686") +      add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch} +                                    LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch} +                                    EXTRA asan.syms.extra) +      set(VERSION_SCRIPT_FLAG +           -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers) +      set_source_files_properties( +        ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc +	PROPERTIES +	OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers) +    else() +      set(VERSION_SCRIPT_FLAG) +    endif() +      if (WIN32)        set(SHARED_ASAN_NAME clang_rt.asan_dynamic-${arch}${COMPILER_RT_OS_SUFFIX})      else() @@ -141,13 +176,21 @@ else()      add_compiler_rt_runtime(clang_rt.asan-dynamic-${arch} ${arch} SHARED        OUTPUT_NAME ${SHARED_ASAN_NAME}        SOURCES $<TARGET_OBJECTS:RTAsan_dynamic.${arch}> +              # The only purpose of RTAsan_dynamic_version_script_dummy is to carry +              # a dependency of the shared runtime on the version script. With CMake +              # 3.1 or later it can be replaced with a straightforward +              # add_dependencies(clang_rt.asan-dynamic-${arch} clang_rt.asan-dynamic-${arch}-version-list) +              $<TARGET_OBJECTS:RTAsan_dynamic_version_script_dummy.${arch}> +              $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>                ${ASAN_COMMON_RUNTIME_OBJECTS}        CFLAGS ${ASAN_DYNAMIC_CFLAGS} +      LINKFLAGS ${ASAN_DYNAMIC_LINK_FLAGS} +                ${VERSION_SCRIPT_FLAG}        DEFS ${ASAN_DYNAMIC_DEFINITIONS})      target_link_libraries(clang_rt.asan-dynamic-${arch} ${ASAN_DYNAMIC_LIBS})      add_dependencies(asan clang_rt.asan-dynamic-${arch}) -    if (UNIX AND NOT ${arch} STREQUAL "i386" AND NOT ${arch} STREQUAL "i686") +    if (UNIX AND NOT ${arch} MATCHES "i386|i686")        add_sanitizer_rt_symbols(clang_rt.asan_cxx-${arch})        add_dependencies(asan clang_rt.asan_cxx-${arch}-symbols)        add_sanitizer_rt_symbols(clang_rt.asan-${arch} asan.syms.extra) diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc index fd63ac68c09e3..2df9a510bd9a1 100644 --- a/lib/asan/asan_allocator.cc +++ b/lib/asan/asan_allocator.cc @@ -223,7 +223,7 @@ void AllocatorOptions::CopyTo(Flags *f, CommonFlags *cf) {  struct Allocator {    static const uptr kMaxAllowedMallocSize = -      FIRST_32_SECOND_64(3UL << 30, 64UL << 30); +      FIRST_32_SECOND_64(3UL << 30, 1UL << 40);    static const uptr kMaxThreadLocalQuarantine =        FIRST_32_SECOND_64(1 << 18, 1 << 20); @@ -354,7 +354,7 @@ struct Allocator {      }      CHECK(IsAligned(needed_size, min_alignment));      if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) { -      Report("WARNING: AddressSanitizer failed to allocate %p bytes\n", +      Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n",               (void*)size);        return allocator.ReturnNullOrDie();      } @@ -437,11 +437,10 @@ struct Allocator {      thread_stats.mallocs++;      thread_stats.malloced += size;      thread_stats.malloced_redzones += needed_size - size; -    uptr class_id = -        Min(kNumberOfSizeClasses, SizeClassMap::ClassID(needed_size)); -    thread_stats.malloced_by_size[class_id]++;      if (needed_size > SizeClassMap::kMaxSize)        thread_stats.malloc_large++; +    else +      thread_stats.malloced_by_size[SizeClassMap::ClassID(needed_size)]++;      void *res = reinterpret_cast<void *>(user_beg);      if (can_fill && fl.max_malloc_fill_size) { diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h index 3208d1f950cdc..5ccd00c97bab9 100644 --- a/lib/asan/asan_allocator.h +++ b/lib/asan/asan_allocator.h @@ -29,7 +29,6 @@ enum AllocType {    FROM_NEW_BR = 3   // Memory block came from operator new [ ]  }; -static const uptr kNumberOfSizeClasses = 255;  struct AsanChunk;  struct AllocatorOptions { @@ -137,6 +136,7 @@ typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16,    AsanMapUnmapCallback> PrimaryAllocator;  #endif  // SANITIZER_CAN_USE_ALLOCATOR64 +static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;  typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;  typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;  typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, diff --git a/lib/asan/asan_fake_stack.cc b/lib/asan/asan_fake_stack.cc index bf4f1eb4c781c..d20641155b881 100644 --- a/lib/asan/asan_fake_stack.cc +++ b/lib/asan/asan_fake_stack.cc @@ -22,6 +22,9 @@ static const u64 kMagic2 = (kMagic1 << 8) | kMagic1;  static const u64 kMagic4 = (kMagic2 << 16) | kMagic2;  static const u64 kMagic8 = (kMagic4 << 32) | kMagic4; +static const u64 kAllocaRedzoneSize = 32UL; +static const u64 kAllocaRedzoneMask = 31UL; +  // For small size classes inline PoisonShadow for better performance.  ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) {    CHECK_EQ(SHADOW_SCALE, 3);  // This code expects SHADOW_SCALE=3. @@ -253,4 +256,24 @@ void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,    if (end) *end = reinterpret_cast<void*>(frame_end);    return reinterpret_cast<void*>(frame->real_stack);  } + +SANITIZER_INTERFACE_ATTRIBUTE +void __asan_alloca_poison(uptr addr, uptr size) { +  uptr LeftRedzoneAddr = addr - kAllocaRedzoneSize; +  uptr PartialRzAddr = addr + size; +  uptr RightRzAddr = (PartialRzAddr + kAllocaRedzoneMask) & ~kAllocaRedzoneMask; +  uptr PartialRzAligned = PartialRzAddr & ~(SHADOW_GRANULARITY - 1); +  FastPoisonShadow(LeftRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaLeftMagic); +  FastPoisonShadowPartialRightRedzone( +      PartialRzAligned, PartialRzAddr % SHADOW_GRANULARITY, +      RightRzAddr - PartialRzAligned, kAsanAllocaRightMagic); +  FastPoisonShadow(RightRzAddr, kAllocaRedzoneSize, kAsanAllocaRightMagic); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void __asan_allocas_unpoison(uptr top, uptr bottom) { +  if ((!top) || (top > bottom)) return; +  REAL(memset)(reinterpret_cast<void*>(MemToShadow(top)), 0, +               (bottom - top) / SHADOW_GRANULARITY); +}  }  // extern "C" diff --git a/lib/asan/asan_flags.cc b/lib/asan/asan_flags.cc index efb7767d5d91b..e8ea549b62e32 100644 --- a/lib/asan/asan_flags.cc +++ b/lib/asan/asan_flags.cc @@ -20,6 +20,8 @@  #include "sanitizer_common/sanitizer_common.h"  #include "sanitizer_common/sanitizer_flags.h"  #include "sanitizer_common/sanitizer_flag_parser.h" +#include "ubsan/ubsan_flags.h" +#include "ubsan/ubsan_platform.h"  namespace __asan { @@ -72,8 +74,8 @@ void InitializeFlags() {    RegisterAsanFlags(&asan_parser, f);    RegisterCommonFlags(&asan_parser); -  // Set the default values and prepare for parsing LSan flags (which can also -  // overwrite common flags). +  // Set the default values and prepare for parsing LSan and UBSan flags +  // (which can also overwrite common flags).  #if CAN_SANITIZE_LEAKS    __lsan::Flags *lf = __lsan::flags();    lf->SetDefaults(); @@ -83,6 +85,15 @@ void InitializeFlags() {    RegisterCommonFlags(&lsan_parser);  #endif +#if CAN_SANITIZE_UB +  __ubsan::Flags *uf = __ubsan::flags(); +  uf->SetDefaults(); + +  FlagParser ubsan_parser; +  __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); +  RegisterCommonFlags(&ubsan_parser); +#endif +    // Override from ASan compile definition.    const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();    asan_parser.ParseString(asan_compile_def); @@ -90,12 +101,19 @@ void InitializeFlags() {    // Override from user-specified string.    const char *asan_default_options = MaybeCallAsanDefaultOptions();    asan_parser.ParseString(asan_default_options); +#if CAN_SANITIZE_UB +  const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); +  ubsan_parser.ParseString(ubsan_default_options); +#endif    // Override from command line.    asan_parser.ParseString(GetEnv("ASAN_OPTIONS"));  #if CAN_SANITIZE_LEAKS    lsan_parser.ParseString(GetEnv("LSAN_OPTIONS"));  #endif +#if CAN_SANITIZE_UB +  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. diff --git a/lib/asan/asan_globals.cc b/lib/asan/asan_globals.cc index 06140bbb360ae..c34b1d3cedf20 100644 --- a/lib/asan/asan_globals.cc +++ b/lib/asan/asan_globals.cc @@ -18,6 +18,7 @@  #include "asan_report.h"  #include "asan_stack.h"  #include "asan_stats.h" +#include "asan_suppressions.h"  #include "asan_thread.h"  #include "sanitizer_common/sanitizer_common.h"  #include "sanitizer_common/sanitizer_mutex.h" @@ -73,7 +74,7 @@ ALWAYS_INLINE void PoisonRedZones(const Global &g) {  const uptr kMinimalDistanceFromAnotherGlobal = 64; -bool IsAddressNearGlobal(uptr addr, const __asan_global &g) { +static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {    if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;    if (addr >= g.beg + g.size_with_redzone) return false;    return true; @@ -90,36 +91,40 @@ static void ReportGlobal(const Global &g, const char *prefix) {    }  } -static bool DescribeOrGetInfoIfGlobal(uptr addr, uptr size, bool print, -                                      Global *output_global) { -  if (!flags()->report_globals) return false; +static u32 FindRegistrationSite(const Global *g) { +  mu_for_globals.CheckLocked(); +  CHECK(global_registration_site_vector); +  for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) { +    GlobalRegistrationSite &grs = (*global_registration_site_vector)[i]; +    if (g >= grs.g_first && g <= grs.g_last) +      return grs.stack_id; +  } +  return 0; +} + +int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites, +                         int max_globals) { +  if (!flags()->report_globals) return 0;    BlockingMutexLock lock(&mu_for_globals); -  bool res = false; +  int res = 0;    for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {      const Global &g = *l->g; -    if (print) { -      if (flags()->report_globals >= 2) -        ReportGlobal(g, "Search"); -      res |= DescribeAddressRelativeToGlobal(addr, size, g); -    } else { -      if (IsAddressNearGlobal(addr, g)) { -        CHECK(output_global); -        *output_global = g; -        return true; -      } +    if (flags()->report_globals >= 2) +      ReportGlobal(g, "Search"); +    if (IsAddressNearGlobal(addr, g)) { +      globals[res] = g; +      if (reg_sites) +        reg_sites[res] = FindRegistrationSite(&g); +      res++; +      if (res == max_globals) break;      }    }    return res;  } -bool DescribeAddressIfGlobal(uptr addr, uptr size) { -  return DescribeOrGetInfoIfGlobal(addr, size, /* print */ true, -                                   /* output_global */ nullptr); -} -  bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {    Global g = {}; -  if (DescribeOrGetInfoIfGlobal(addr, /* size */ 1, /* print */ false, &g)) { +  if (GetGlobalsForAddress(addr, &g, nullptr, 1)) {      internal_strncpy(descr->name, g.name, descr->name_size);      descr->region_address = g.beg;      descr->region_size = g.size; @@ -129,16 +134,6 @@ bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {    return false;  } -u32 FindRegistrationSite(const Global *g) { -  CHECK(global_registration_site_vector); -  for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) { -    GlobalRegistrationSite &grs = (*global_registration_site_vector)[i]; -    if (g >= grs.g_first && g <= grs.g_last) -      return grs.stack_id; -  } -  return 0; -} -  // Register a global variable.  // This function may be called more than once for every global  // so we store the globals in a map. @@ -158,7 +153,8 @@ static void RegisterGlobal(const Global *g) {        // the entire redzone of the second global may be within the first global.        for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {          if (g->beg == l->g->beg && -            (flags()->detect_odr_violation >= 2 || g->size != l->g->size)) +            (flags()->detect_odr_violation >= 2 || g->size != l->g->size) && +            !IsODRViolationSuppressed(g->name))            ReportODRViolation(g, FindRegistrationSite(g),                               l->g, FindRegistrationSite(l->g));        } @@ -210,20 +206,6 @@ void StopInitOrderChecking() {    }  } -#if SANITIZER_WINDOWS  // Should only be called on Windows. -SANITIZER_INTERFACE_ATTRIBUTE -void UnregisterGlobalsInRange(void *beg, void *end) { -  if (!flags()->report_globals) -    return; -  BlockingMutexLock lock(&mu_for_globals); -  for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) { -    void *address = (void *)l->g->beg; -    if (beg <= address && address < end) -      UnregisterGlobal(l->g); -  } -} -#endif -  }  // namespace __asan  // ---------------------- Interface ---------------- {{{1 @@ -232,7 +214,7 @@ using namespace __asan;  // NOLINT  // Register an array of globals.  void __asan_register_globals(__asan_global *globals, uptr n) {    if (!flags()->report_globals) return; -  GET_STACK_TRACE_FATAL_HERE; +  GET_STACK_TRACE_MALLOC;    u32 stack_id = StackDepotPut(stack);    BlockingMutexLock lock(&mu_for_globals);    if (!global_registration_site_vector) diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index 3dc7ec67a3e52..d8b48d391ab8b 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -23,6 +23,10 @@  #include "asan_suppressions.h"  #include "sanitizer_common/sanitizer_libc.h" +#if SANITIZER_POSIX +#include "sanitizer_common/sanitizer_posix.h" +#endif +  namespace __asan {  // Return true if we can quickly decide that the region is unpoisoned. @@ -65,7 +69,7 @@ struct AsanInterceptorContext {        }                                                                 \        if (!suppressed) {                                                \          GET_CURRENT_PC_BP_SP;                                           \ -        __asan_report_error(pc, bp, sp, __bad, isWrite, __size);        \ +        __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);     \        }                                                                 \      }                                                                   \    } while (0) @@ -75,6 +79,13 @@ struct AsanInterceptorContext {  #define ASAN_WRITE_RANGE(ctx, offset, size) \    ACCESS_MEMORY_RANGE(ctx, offset, size, true) +#define ASAN_READ_STRING_OF_LEN(ctx, s, len, n)                 \ +  ASAN_READ_RANGE((ctx), (s),                                   \ +    common_flags()->strict_string_checks ? (len) + 1 : (n)) + +#define ASAN_READ_STRING(ctx, s, n)                             \ +  ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n)) +  // Behavior of functions like "memcpy" or "strcpy" is undefined  // if memory intervals overlap. We report error in this case.  // Macro is used to avoid creation of new frames. @@ -120,17 +131,6 @@ using namespace __asan;  // NOLINT  DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)  DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) -#if !SANITIZER_MAC -#define ASAN_INTERCEPT_FUNC(name)                                        \ -  do {                                                                   \ -    if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                      \ -      VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \ -  } while (0) -#else -// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. -#define ASAN_INTERCEPT_FUNC(name) -#endif  // SANITIZER_MAC -  #define ASAN_INTERCEPTOR_ENTER(ctx, func)                                      \    AsanInterceptorContext _ctx = {#func};                                       \    ctx = (void *)&_ctx;                                                         \ @@ -171,11 +171,24 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)    do {                                                         \    } 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 +#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                           \ +  if (flags()->strict_init_order) {                                            \ +    StopInitOrderChecking();                                                   \ +  }  #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()  #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \    CoverageUpdateMapping()  #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()  #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) +#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \ +  if (AsanThread *t = GetCurrentThread()) {                                    \ +    *begin = t->tls_begin();                                                   \ +    *end = t->tls_end();                                                       \ +  } else {                                                                     \ +    *begin = *end = 0;                                                         \ +  }  #include "sanitizer_common/sanitizer_common_interceptors.inc"  // Syscall interceptors don't have contexts, we don't support suppressions @@ -200,12 +213,6 @@ struct ThreadStartParam {  };  static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { -#if SANITIZER_WINDOWS -  // FIXME: this is a bandaid fix for PR22025. -  AsanThread *t = (AsanThread*)arg; -  SetCurrentThread(t); -  return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr); -#else    ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);    AsanThread *t = nullptr;    while ((t = reinterpret_cast<AsanThread *>( @@ -213,7 +220,6 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {      internal_sched_yield();    SetCurrentThread(t);    return t->ThreadStart(GetTid(), ¶m->is_registered); -#endif  }  #if ASAN_INTERCEPT_PTHREAD_CREATE @@ -302,7 +308,7 @@ static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {    ssize += stack - bottom;    ssize = RoundUpTo(ssize, PageSize);    static const uptr kMaxSaneContextStackSize = 1 << 22;  // 4 Mb -  if (ssize && ssize <= kMaxSaneContextStackSize) { +  if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {      PoisonShadow(bottom, ssize, 0);    }  } @@ -357,30 +363,6 @@ INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {  }  #endif -#if SANITIZER_WINDOWS -INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) { -  CHECK(REAL(RaiseException)); -  __asan_handle_no_return(); -  REAL(RaiseException)(a, b, c, d); -} - -INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) { -  CHECK(REAL(_except_handler3)); -  __asan_handle_no_return(); -  return REAL(_except_handler3)(a, b, c, d); -} - -#if ASAN_DYNAMIC -// This handler is named differently in -MT and -MD CRTs. -#define _except_handler4 _except_handler4_common -#endif -INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { -  CHECK(REAL(_except_handler4)); -  __asan_handle_no_return(); -  return REAL(_except_handler4)(a, b, c, d); -} -#endif -  static inline int CharCmp(unsigned char c1, unsigned char c2) {    return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;  } @@ -511,8 +493,9 @@ INTERCEPTOR(char*, strchr, const char *str, int c) {    ENSURE_ASAN_INITED();    char *result = REAL(strchr)(str, c);    if (flags()->replace_str) { -    uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; -    ASAN_READ_RANGE(ctx, str, bytes_read); +    uptr len = REAL(strlen)(str); +    uptr bytes_read = (result ? result - str : len) + 1; +    ASAN_READ_STRING_OF_LEN(ctx, str, len, bytes_read);    }    return result;  } @@ -541,7 +524,7 @@ INTERCEPTOR(char*, strcat, char *to, const char *from) {  // NOLINT      uptr from_length = REAL(strlen)(from);      ASAN_READ_RANGE(ctx, from, from_length + 1);      uptr to_length = REAL(strlen)(to); -    ASAN_READ_RANGE(ctx, to, to_length); +    ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);      ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);      // If the copying actually happens, the |from| string should not overlap      // with the resulting string starting at |to|, which has a length of @@ -563,7 +546,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {      uptr copy_length = Min(size, from_length + 1);      ASAN_READ_RANGE(ctx, from, copy_length);      uptr to_length = REAL(strlen)(to); -    ASAN_READ_RANGE(ctx, to, to_length); +    ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);      ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);      if (from_length > 0) {        CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, @@ -665,23 +648,6 @@ INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {  }  #endif  // ASAN_INTERCEPT_STRNLEN -static inline bool IsValidStrtolBase(int base) { -  return (base == 0) || (2 <= base && base <= 36); -} - -static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { -  CHECK(endptr); -  if (nptr == *endptr) { -    // No digits were found at strtol call, we need to find out the last -    // symbol accessed by strtoll on our own. -    // We get this symbol by skipping leading blanks and optional +/- sign. -    while (IsSpace(*nptr)) nptr++; -    if (*nptr == '+' || *nptr == '-') nptr++; -    *endptr = const_cast<char *>(nptr); -  } -  CHECK(*endptr >= nptr); -} -  INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT              char **endptr, int base) {    void *ctx; @@ -692,13 +658,7 @@ INTERCEPTOR(long, strtol, const char *nptr,  // NOLINT    }    char *real_endptr;    long result = REAL(strtol)(nptr, &real_endptr, base);  // NOLINT -  if (endptr != 0) { -    *endptr = real_endptr; -  } -  if (IsValidStrtolBase(base)) { -    FixRealStrtolEndptr(nptr, &real_endptr); -    ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1); -  } +  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);    return result;  } @@ -719,7 +679,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {    // different from int). So, we just imitate this behavior.    int result = REAL(strtol)(nptr, &real_endptr, 10);    FixRealStrtolEndptr(nptr, &real_endptr); -  ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1); +  ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);    return result;  } @@ -736,7 +696,7 @@ INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT    char *real_endptr;    long result = REAL(strtol)(nptr, &real_endptr, 10);  // NOLINT    FixRealStrtolEndptr(nptr, &real_endptr); -  ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1); +  ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);    return result;  } @@ -751,16 +711,7 @@ INTERCEPTOR(long long, strtoll, const char *nptr,  // NOLINT    }    char *real_endptr;    long long result = REAL(strtoll)(nptr, &real_endptr, base);  // NOLINT -  if (endptr != 0) { -    *endptr = real_endptr; -  } -  // If base has unsupported value, strtoll can exit with EINVAL -  // without reading any characters. So do additional checks only -  // if base is valid. -  if (IsValidStrtolBase(base)) { -    FixRealStrtolEndptr(nptr, &real_endptr); -    ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1); -  } +  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);    return result;  } @@ -774,7 +725,7 @@ INTERCEPTOR(long long, atoll, const char *nptr) {  // NOLINT    char *real_endptr;    long long result = REAL(strtoll)(nptr, &real_endptr, 10);  // NOLINT    FixRealStrtolEndptr(nptr, &real_endptr); -  ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1); +  ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);    return result;  }  #endif  // ASAN_INTERCEPT_ATOLL_AND_STRTOLL @@ -807,36 +758,6 @@ INTERCEPTOR(int, fork, void) {  }  #endif  // ASAN_INTERCEPT_FORK -#if SANITIZER_WINDOWS -INTERCEPTOR_WINAPI(DWORD, CreateThread, -                   void* security, uptr stack_size, -                   DWORD (__stdcall *start_routine)(void*), void* arg, -                   DWORD thr_flags, void* tid) { -  // Strict init-order checking is thread-hostile. -  if (flags()->strict_init_order) -    StopInitOrderChecking(); -  GET_STACK_TRACE_THREAD; -  // FIXME: The CreateThread interceptor is not the same as a pthread_create -  // one.  This is a bandaid fix for PR22025. -  bool detached = false;  // FIXME: how can we determine it on Windows? -  u32 current_tid = GetCurrentTidOrInvalid(); -  AsanThread *t = -        AsanThread::Create(start_routine, arg, current_tid, &stack, detached); -  return REAL(CreateThread)(security, stack_size, -                            asan_thread_start, t, thr_flags, tid); -} - -namespace __asan { -void InitializeWindowsInterceptors() { -  ASAN_INTERCEPT_FUNC(CreateThread); -  ASAN_INTERCEPT_FUNC(RaiseException); -  ASAN_INTERCEPT_FUNC(_except_handler3); -  ASAN_INTERCEPT_FUNC(_except_handler4); -} - -}  // namespace __asan -#endif -  // ---------------------- InitializeAsanInterceptors ---------------- {{{1  namespace __asan {  void InitializeAsanInterceptors() { @@ -919,10 +840,7 @@ void InitializeAsanInterceptors() {    ASAN_INTERCEPT_FUNC(fork);  #endif -  // Some Windows-specific interceptors. -#if SANITIZER_WINDOWS -  InitializeWindowsInterceptors(); -#endif +  InitializePlatformInterceptors();    VReport(1, "AddressSanitizer: libc interceptors initialized\n");  } diff --git a/lib/asan/asan_interceptors.h b/lib/asan/asan_interceptors.h index ee3b82aa7ef93..488ada78ab8bb 100644 --- a/lib/asan/asan_interceptors.h +++ b/lib/asan/asan_interceptors.h @@ -92,9 +92,21 @@ struct sigaction;  DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,                               struct sigaction *oldact) +#if !SANITIZER_MAC +#define ASAN_INTERCEPT_FUNC(name)                                        \ +  do {                                                                   \ +    if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                      \ +      VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \ +  } while (0) +#else +// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. +#define ASAN_INTERCEPT_FUNC(name) +#endif  // SANITIZER_MAC +  namespace __asan {  void InitializeAsanInterceptors(); +void InitializePlatformInterceptors();  #define ENSURE_ASAN_INITED() do { \    CHECK(!asan_init_is_running); \ diff --git a/lib/asan/asan_interface_internal.h b/lib/asan/asan_interface_internal.h index ea7540f6bb56a..ad8ebcd91ad98 100644 --- a/lib/asan/asan_interface_internal.h +++ b/lib/asan/asan_interface_internal.h @@ -128,7 +128,7 @@ extern "C" {    SANITIZER_INTERFACE_ATTRIBUTE    void __asan_report_error(uptr pc, uptr bp, uptr sp, -                           uptr addr, int is_write, uptr access_size); +                           uptr addr, int is_write, uptr access_size, u32 exp);    SANITIZER_INTERFACE_ATTRIBUTE    int __asan_set_error_exit_code(int exit_code); @@ -165,6 +165,21 @@ 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_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); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load8(uptr p, u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load16(uptr p, u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store1(uptr p, u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store2(uptr p, u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store4(uptr p, u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store8(uptr p, u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store16(uptr p, u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr p, uptr size, +                                                      u32 exp); +  SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr p, uptr size, +                                                       u32 exp); +    SANITIZER_INTERFACE_ATTRIBUTE        void* __asan_memcpy(void *dst, const void *src, uptr size);    SANITIZER_INTERFACE_ATTRIBUTE @@ -180,6 +195,10 @@ extern "C" {    void __asan_poison_intra_object_redzone(uptr p, uptr size);    SANITIZER_INTERFACE_ATTRIBUTE    void __asan_unpoison_intra_object_redzone(uptr p, uptr size); +  SANITIZER_INTERFACE_ATTRIBUTE +  void __asan_alloca_poison(uptr addr, uptr size); +  SANITIZER_INTERFACE_ATTRIBUTE +  void __asan_allocas_unpoison(uptr top, uptr bottom);  }  // extern "C"  #endif  // ASAN_INTERFACE_INTERNAL_H diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h index ffd3ff82d71e0..107e16ee31b94 100644 --- a/lib/asan/asan_internal.h +++ b/lib/asan/asan_internal.h @@ -62,21 +62,6 @@ namespace __asan {  class AsanThread;  using __sanitizer::StackTrace; -struct SignalContext { -  void *context; -  uptr addr; -  uptr pc; -  uptr sp; -  uptr bp; - -  SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) : -      context(context), addr(addr), pc(pc), sp(sp), bp(bp) { -  } - -  // Creates signal context in a platform-specific manner. -  static SignalContext Create(void *siginfo, void *context); -}; -  void AsanInitFromRtl();  // asan_rtl.cc @@ -90,7 +75,6 @@ void *AsanDoesNotSupportStaticLinkage();  void AsanCheckDynamicRTPrereqs();  void AsanCheckIncompatibleRT(); -void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);  void AsanOnSIGSEGV(int, void *siginfo, void *context);  void DisableReexec(); @@ -109,7 +93,7 @@ void AppendToErrorMessageBuffer(const char *buffer);  void *AsanDlSymNext(const char *sym); -void ReserveShadowMemoryRange(uptr beg, uptr end); +void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name);  // Platform-specific options.  #if SANITIZER_MAC diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc index 8e8bafd47af67..9580fc7c06d44 100644 --- a/lib/asan/asan_linux.cc +++ b/lib/asan/asan_linux.cc @@ -68,6 +68,8 @@ asan_rt_version_t  __asan_rt_version;  namespace __asan { +void InitializePlatformInterceptors() {} +  void DisableReexec() {    // No need to re-exec on Linux.  } @@ -111,6 +113,9 @@ static void ReportIncompatibleRT() {  }  void AsanCheckDynamicRTPrereqs() { +  if (!ASAN_DYNAMIC) +    return; +    // Ensure that dynamic RT is the first DSO in the list    const char *first_dso_name = 0;    dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name); @@ -152,78 +157,6 @@ void AsanCheckIncompatibleRT() {  }  #endif  // SANITIZER_ANDROID -void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { -#if defined(__arm__) -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.arm_pc; -  *bp = ucontext->uc_mcontext.arm_fp; -  *sp = ucontext->uc_mcontext.arm_sp; -#elif defined(__aarch64__) -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.pc; -  *bp = ucontext->uc_mcontext.regs[29]; -  *sp = ucontext->uc_mcontext.sp; -#elif defined(__hppa__) -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.sc_iaoq[0]; -  /* GCC uses %r3 whenever a frame pointer is needed.  */ -  *bp = ucontext->uc_mcontext.sc_gr[3]; -  *sp = ucontext->uc_mcontext.sc_gr[30]; -#elif defined(__x86_64__) -# if SANITIZER_FREEBSD -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.mc_rip; -  *bp = ucontext->uc_mcontext.mc_rbp; -  *sp = ucontext->uc_mcontext.mc_rsp; -# else -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.gregs[REG_RIP]; -  *bp = ucontext->uc_mcontext.gregs[REG_RBP]; -  *sp = ucontext->uc_mcontext.gregs[REG_RSP]; -# endif -#elif defined(__i386__) -# if SANITIZER_FREEBSD -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.mc_eip; -  *bp = ucontext->uc_mcontext.mc_ebp; -  *sp = ucontext->uc_mcontext.mc_esp; -# else -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.gregs[REG_EIP]; -  *bp = ucontext->uc_mcontext.gregs[REG_EBP]; -  *sp = ucontext->uc_mcontext.gregs[REG_ESP]; -# endif -#elif defined(__powerpc__) || defined(__powerpc64__) -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.regs->nip; -  *sp = ucontext->uc_mcontext.regs->gpr[PT_R1]; -  // The powerpc{,64}-linux ABIs do not specify r31 as the frame -  // pointer, but GCC always uses r31 when we need a frame pointer. -  *bp = ucontext->uc_mcontext.regs->gpr[PT_R31]; -#elif defined(__sparc__) -  ucontext_t *ucontext = (ucontext_t*)context; -  uptr *stk_ptr; -# if defined (__arch64__) -  *pc = ucontext->uc_mcontext.mc_gregs[MC_PC]; -  *sp = ucontext->uc_mcontext.mc_gregs[MC_O6]; -  stk_ptr = (uptr *) (*sp + 2047); -  *bp = stk_ptr[15]; -# else -  *pc = ucontext->uc_mcontext.gregs[REG_PC]; -  *sp = ucontext->uc_mcontext.gregs[REG_O6]; -  stk_ptr = (uptr *) *sp; -  *bp = stk_ptr[15]; -# endif -#elif defined(__mips__) -  ucontext_t *ucontext = (ucontext_t*)context; -  *pc = ucontext->uc_mcontext.gregs[31]; -  *bp = ucontext->uc_mcontext.gregs[30]; -  *sp = ucontext->uc_mcontext.gregs[29]; -#else -# error "Unsupported arch" -#endif -} -  void AsanPlatformThreadInit() {    // Nothing here for now.  } diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc index b35368617dcab..3e028378df28f 100644 --- a/lib/asan/asan_mac.cc +++ b/lib/asan/asan_mac.cc @@ -24,7 +24,14 @@  #include "sanitizer_common/sanitizer_libc.h"  #include "sanitizer_common/sanitizer_mac.h" -#include <crt_externs.h>  // for _NSGetArgv +#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 <mach-o/dyld.h>  #include <mach-o/loader.h> @@ -40,19 +47,7 @@  namespace __asan { -void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { -  ucontext_t *ucontext = (ucontext_t*)context; -# if SANITIZER_WORDSIZE == 64 -  *pc = ucontext->uc_mcontext->__ss.__rip; -  *bp = ucontext->uc_mcontext->__ss.__rbp; -  *sp = ucontext->uc_mcontext->__ss.__rsp; -# else -  *pc = ucontext->uc_mcontext->__ss.__eip; -  *bp = ucontext->uc_mcontext->__ss.__ebp; -  *sp = ucontext->uc_mcontext->__ss.__esp; -# endif  // SANITIZER_WORDSIZE -} - +void InitializePlatformInterceptors() {}  bool PlatformHasDifferentMemcpyAndMemmove() {    // On OS X 10.7 memcpy() and memmove() are both resolved @@ -74,30 +69,27 @@ LowLevelAllocator allocator_for_env;  // otherwise the corresponding "NAME=value" string is replaced with  // |name_value|.  void LeakyResetEnv(const char *name, const char *name_value) { -  char ***env_ptr = _NSGetEnviron(); -  CHECK(env_ptr); -  char **environ = *env_ptr; -  CHECK(environ); +  char **env = GetEnviron();    uptr name_len = internal_strlen(name); -  while (*environ != 0) { -    uptr len = internal_strlen(*environ); +  while (*env != 0) { +    uptr len = internal_strlen(*env);      if (len > name_len) { -      const char *p = *environ; +      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. -          *environ = const_cast<char*>(name_value); +          *env = const_cast<char*>(name_value);          } else {            // Shift the subsequent pointers back. -          char **del = environ; +          char **del = env;            do {              del[0] = del[1];            } while (*del++);          }        }      } -    environ++; +    env++;    }  } @@ -107,6 +99,23 @@ 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; @@ -122,8 +131,10 @@ void MaybeReexec() {    uptr fname_len = internal_strlen(info.dli_fname);    const char *dylib_name = StripModuleName(info.dli_fname);    uptr dylib_name_len = internal_strlen(dylib_name); -  if (!dyld_insert_libraries || -      !REAL(strstr)(dyld_insert_libraries, 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]; @@ -160,6 +171,9 @@ void MaybeReexec() {      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. diff --git a/lib/asan/asan_mapping.h b/lib/asan/asan_mapping.h index 5cb011d683d30..f9e1a527de184 100644 --- a/lib/asan/asan_mapping.h +++ b/lib/asan/asan_mapping.h @@ -98,9 +98,12 @@  static const u64 kDefaultShadowScale = 3;  static const u64 kDefaultShadowOffset32 = 1ULL << 29;  // 0x20000000 -static const u64 kIosShadowOffset32 = 1ULL << 30;  // 0x40000000  static const u64 kDefaultShadowOffset64 = 1ULL << 44;  static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000;  // < 2G. +static const u64 kIosShadowOffset32 = 1ULL << 30;  // 0x40000000 +static const u64 kIosShadowOffset64 = 0x130000000; +static const u64 kIosSimShadowOffset32 = 1ULL << 30; +static const u64 kIosSimShadowOffset64 = kDefaultShadowOffset64;  static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;  static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;  static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; @@ -118,10 +121,12 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28;  // 0x30000000  #    define SHADOW_OFFSET kMIPS32_ShadowOffset32  #  elif SANITIZER_FREEBSD  #    define SHADOW_OFFSET kFreeBSD_ShadowOffset32 -#  elif SANITIZER_IOS -#    define SHADOW_OFFSET kIosShadowOffset32  #  elif SANITIZER_WINDOWS  #    define SHADOW_OFFSET kWindowsShadowOffset32 +#  elif SANITIZER_IOSSIM +#    define SHADOW_OFFSET kIosSimShadowOffset32 +#  elif SANITIZER_IOS +#    define SHADOW_OFFSET kIosShadowOffset32  #  else  #    define SHADOW_OFFSET kDefaultShadowOffset32  #  endif @@ -136,6 +141,10 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28;  // 0x30000000  #   define SHADOW_OFFSET kDefaultShadowOffset64  #  elif defined(__mips64)  #   define SHADOW_OFFSET kMIPS64_ShadowOffset64 +#  elif SANITIZER_IOSSIM +#    define SHADOW_OFFSET kIosSimShadowOffset64 +#  elif SANITIZER_IOS +#    define SHADOW_OFFSET kIosShadowOffset64  #  else  #   define SHADOW_OFFSET kDefaultShort64bitShadowOffset  #  endif diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc index e2b1f4dc4d5e4..569d359aa4255 100644 --- a/lib/asan/asan_poisoning.cc +++ b/lib/asan/asan_poisoning.cc @@ -112,7 +112,7 @@ void __asan_poison_memory_region(void const volatile *addr, uptr size) {    if (!flags()->allow_user_poisoning || size == 0) return;    uptr beg_addr = (uptr)addr;    uptr end_addr = beg_addr + size; -  VPrintf(1, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr, +  VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,            (void *)end_addr);    ShadowSegmentEndpoint beg(beg_addr);    ShadowSegmentEndpoint end(end_addr); @@ -152,7 +152,7 @@ void __asan_unpoison_memory_region(void const volatile *addr, uptr size) {    if (!flags()->allow_user_poisoning || size == 0) return;    uptr beg_addr = (uptr)addr;    uptr end_addr = beg_addr + size; -  VPrintf(1, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr, +  VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,            (void *)end_addr);    ShadowSegmentEndpoint beg(beg_addr);    ShadowSegmentEndpoint end(end_addr); @@ -218,7 +218,7 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) {          __asan::AddressIsPoisoned(__p + __size - 1))) {       \        GET_CURRENT_PC_BP_SP;                                   \        uptr __bad = __asan_region_is_poisoned(__p, __size);    \ -      __asan_report_error(pc, bp, sp, __bad, isWrite, __size);\ +      __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\      }                                                         \    } while (false);                                            \ diff --git a/lib/asan/asan_poisoning.h b/lib/asan/asan_poisoning.h index 3fc94649fb39f..6344225f0f64e 100644 --- a/lib/asan/asan_poisoning.h +++ b/lib/asan/asan_poisoning.h @@ -64,7 +64,7 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,        if (page_end != shadow_end) {          REAL(memset)((void *)page_end, 0, shadow_end - page_end);        } -      ReserveShadowMemoryRange(page_beg, page_end - 1); +      ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);      }    }  } diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc index ad31458df28db..2e857f6f624c7 100644 --- a/lib/asan/asan_posix.cc +++ b/lib/asan/asan_posix.cc @@ -21,6 +21,7 @@  #include "asan_report.h"  #include "asan_stack.h"  #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_posix.h"  #include "sanitizer_common/sanitizer_procmaps.h"  #include <pthread.h> @@ -32,13 +33,6 @@  namespace __asan { -SignalContext SignalContext::Create(void *siginfo, void *context) { -  uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr; -  uptr pc, sp, bp; -  GetPcSpBp(context, &pc, &sp, &bp); -  return SignalContext(context, addr, pc, sp, bp); -} -  void AsanOnSIGSEGV(int, void *siginfo, void *context) {    ScopedDeadlySignal signal_scope(GetCurrentThread());    int code = (int)((siginfo_t*)siginfo)->si_code; diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 8706d5decc0b5..c1681e6444647 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -281,9 +281,8 @@ static void PrintGlobalLocation(InternalScopedString *str,      str->append(":%d", g.location->column_no);  } -bool DescribeAddressRelativeToGlobal(uptr addr, uptr size, -                                     const __asan_global &g) { -  if (!IsAddressNearGlobal(addr, g)) return false; +static void DescribeAddressRelativeToGlobal(uptr addr, uptr size, +                                            const __asan_global &g) {    InternalScopedString str(4096);    Decorator d;    str.append("%s", d.Location()); @@ -306,6 +305,26 @@ bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,    str.append("%s", d.EndLocation());    PrintGlobalNameIfASCII(&str, g);    Printf("%s", str.data()); +} + +static bool DescribeAddressIfGlobal(uptr addr, uptr size, +                                    const char *bug_type) { +  // Assume address is close to at most four globals. +  const int kMaxGlobalsInReport = 4; +  __asan_global globals[kMaxGlobalsInReport]; +  u32 reg_sites[kMaxGlobalsInReport]; +  int globals_num = +      GetGlobalsForAddress(addr, globals, reg_sites, ARRAY_SIZE(globals)); +  if (globals_num == 0) +    return false; +  for (int i = 0; i < globals_num; i++) { +    DescribeAddressRelativeToGlobal(addr, size, globals[i]); +    if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") && +        reg_sites[i]) { +      Printf("  registered at:\n"); +      StackDepotGet(reg_sites[i]).Print(); +    } +  }    return true;  } @@ -551,12 +570,12 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {    DescribeThread(alloc_thread);  } -void DescribeAddress(uptr addr, uptr access_size) { +static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {    // Check if this is shadow or shadow gap.    if (DescribeAddressIfShadow(addr))      return;    CHECK(AddrIsInMem(addr)); -  if (DescribeAddressIfGlobal(addr, access_size)) +  if (DescribeAddressIfGlobal(addr, access_size, bug_type))      return;    if (DescribeAddressIfStack(addr, access_size))      return; @@ -578,6 +597,11 @@ void DescribeThread(AsanThreadContext *context) {    InternalScopedString str(1024);    str.append("Thread T%d%s", context->tid,               ThreadNameWithParenthesis(context->tid, tname, sizeof(tname))); +  if (context->parent_tid == kInvalidTid) { +    str.append(" created by unknown thread\n"); +    Printf("%s", str.data()); +    return; +  }    str.append(        " created by T%d%s here:\n", context->parent_tid,        ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname))); @@ -805,8 +829,8 @@ void ReportStringFunctionMemoryRangesOverlap(const char *function,               bug_type, offset1, offset1 + length1, offset2, offset2 + length2);    Printf("%s", d.EndWarning());    stack->Print(); -  DescribeAddress((uptr)offset1, length1); -  DescribeAddress((uptr)offset2, length2); +  DescribeAddress((uptr)offset1, length1, bug_type); +  DescribeAddress((uptr)offset2, length2, bug_type);    ReportErrorSummary(bug_type, stack);  } @@ -819,7 +843,7 @@ void ReportStringFunctionSizeOverflow(uptr offset, uptr size,    Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);    Printf("%s", d.EndWarning());    stack->Print(); -  DescribeAddress(offset, size); +  DescribeAddress(offset, size, bug_type);    ReportErrorSummary(bug_type, stack);  } @@ -834,6 +858,9 @@ void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,           "      old_mid : %p\n"           "      new_mid : %p\n",           beg, end, old_mid, new_mid); +  uptr granularity = SHADOW_GRANULARITY; +  if (!IsAligned(beg, granularity)) +    Report("ERROR: beg is not aligned by %d\n", granularity);    stack->Print();    ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);  } @@ -871,15 +898,16 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1,  static NOINLINE void  ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {    ScopedInErrorReport in_report; +  const char *bug_type = "invalid-pointer-pair";    Decorator d;    Printf("%s", d.Warning());    Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2);    Printf("%s", d.EndWarning());    GET_STACK_TRACE_FATAL(pc, bp);    stack.Print(); -  DescribeAddress(a1, 1); -  DescribeAddress(a2, 1); -  ReportErrorSummary("invalid-pointer-pair", &stack); +  DescribeAddress(a1, 1, bug_type); +  DescribeAddress(a2, 1, bug_type); +  ReportErrorSummary(bug_type, &stack);  }  static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { @@ -936,9 +964,18 @@ void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,  using namespace __asan;  // NOLINT  void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, -                         uptr access_size) { +                         uptr access_size, u32 exp) {    ENABLE_FRAME_POINTER; +  // Optimization experiments. +  // The experiments can be used to evaluate potential optimizations that remove +  // instrumentation (assess false negatives). Instead of completely removing +  // some instrumentation, compiler can emit special calls into runtime +  // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass +  // mask of experiments (exp). +  // The reaction to a non-zero value of exp is to be defined. +  (void)exp; +    // Determine the error type.    const char *bug_descr = "unknown-crash";    if (AddrIsInMem(addr)) { @@ -1017,7 +1054,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,    GET_STACK_TRACE_FATAL(pc, bp);    stack.Print(); -  DescribeAddress(addr, access_size); +  DescribeAddress(addr, access_size, bug_descr);    ReportErrorSummary(bug_descr, &stack);    PrintShadowMemoryForAddress(addr);  } @@ -1035,7 +1072,7 @@ void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {  void __asan_describe_address(uptr addr) {    // Thread registry must be locked while we're describing an address.    asanThreadRegistry().Lock(); -  DescribeAddress(addr, 1); +  DescribeAddress(addr, 1, "");    asanThreadRegistry().Unlock();  } diff --git a/lib/asan/asan_report.h b/lib/asan/asan_report.h index 029c914b8a04d..e2786b0f260ce 100644 --- a/lib/asan/asan_report.h +++ b/lib/asan/asan_report.h @@ -33,22 +33,19 @@ struct AddressDescription {    const char *region_kind;  }; +// Returns the number of globals close to the provided address and copies +// them to "globals" array. +int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites, +                         int max_globals); +bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);  // The following functions prints address description depending  // on the memory type (shadow/heap/stack/global).  void DescribeHeapAddress(uptr addr, uptr access_size); -bool DescribeAddressIfGlobal(uptr addr, uptr access_size); -bool DescribeAddressRelativeToGlobal(uptr addr, uptr access_size, -                                     const __asan_global &g); -bool IsAddressNearGlobal(uptr addr, const __asan_global &g); -bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);  bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr = nullptr,                               bool print = true);  bool ParseFrameDescription(const char *frame_descr,                             InternalMmapVector<StackVarDescr> *vars);  bool DescribeAddressIfStack(uptr addr, uptr access_size); -// Determines memory type on its own. -void DescribeAddress(uptr addr, uptr access_size); -  void DescribeThread(AsanThreadContext *context);  // Different kinds of error reports. diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index 9126e71a64378..a8d92b915a9a8 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -28,6 +28,8 @@  #include "sanitizer_common/sanitizer_libc.h"  #include "sanitizer_common/sanitizer_symbolizer.h"  #include "lsan/lsan_common.h" +#include "ubsan/ubsan_init.h" +#include "ubsan/ubsan_platform.h"  int __asan_option_detect_stack_use_after_return;  // Global interface symbol.  uptr *__asan_test_only_reported_buggy_pointer;  // Used only for testing asan. @@ -87,12 +89,12 @@ void ShowStatsAndAbort() {  // ---------------------- mmap -------------------- {{{1  // Reserve memory range [beg, end].  // We need to use inclusive range because end+1 may not be representable. -void ReserveShadowMemoryRange(uptr beg, uptr end) { +void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {    CHECK_EQ((beg % GetPageSizeCached()), 0);    CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);    uptr size = end - beg + 1;    DecreaseTotalMmap(size);  // Don't count the shadow against mmap_limit_mb. -  void *res = MmapFixedNoReserve(beg, size); +  void *res = MmapFixedNoReserve(beg, size, name);    if (res != (void*)beg) {      Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "             "Perhaps you're using ulimit -v\n", size); @@ -112,11 +114,15 @@ static void OnLowLevelAllocate(uptr ptr, uptr size) {  // -------------------------- Run-time entry ------------------- {{{1  // exported functions  #define ASAN_REPORT_ERROR(type, is_write, size)                     \ -extern "C" NOINLINE INTERFACE_ATTRIBUTE                        \ -void __asan_report_ ## type ## size(uptr addr);                \ -void __asan_report_ ## type ## size(uptr addr) {               \ +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);         \ +}                                                                   \ +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);            \ +  __asan_report_error(pc, bp, sp, addr, is_write, size, exp);       \  }  ASAN_REPORT_ERROR(load, false, 1) @@ -132,18 +138,20 @@ 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);       \  void __asan_report_ ## type ## _n(uptr addr, uptr size) {      \    GET_CALLER_PC_BP_SP;                                         \ -  __asan_report_error(pc, bp, sp, addr, is_write, size);       \ +  __asan_report_error(pc, bp, sp, addr, is_write, size, 0);    \ +}                                                              \ +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);               \  }  ASAN_REPORT_ERROR_N(load, false)  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); \ -  void __asan_##type##size(uptr addr) {                                        \ +#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg)        \      uptr sp = MEM_TO_SHADOW(addr);                                             \      uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp)          \                                          : *reinterpret_cast<u16 *>(sp);        \ @@ -155,10 +163,19 @@ 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);               \ +          __asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg);      \          }                                                                      \        }                                                                        \ -    }                                                                          \ +    } + +#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)                  \ +  }                                                                            \ +  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(load, false, 1) @@ -173,18 +190,38 @@ ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8)  ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)  extern "C" -NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) { +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); +    __asan_report_error(pc, bp, sp, addr, false, size, 0);    }  }  extern "C" -NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) { +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, true, size); +    __asan_report_error(pc, bp, sp, addr, false, size, exp); +  } +} + +extern "C" +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); +  } +} + +extern "C" +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);    }  } @@ -203,26 +240,40 @@ static NOINLINE void force_interface_symbols() {      case 3: __asan_report_load4(0); break;      case 4: __asan_report_load8(0); break;      case 5: __asan_report_load16(0); break; -    case 6: __asan_report_store1(0); break; -    case 7: __asan_report_store2(0); break; -    case 8: __asan_report_store4(0); break; -    case 9: __asan_report_store8(0); break; -    case 10: __asan_report_store16(0); break; -    case 12: __asan_register_globals(0, 0); break; -    case 13: __asan_unregister_globals(0, 0); break; -    case 14: __asan_set_death_callback(0); break; -    case 15: __asan_set_error_report_callback(0); break; -    case 16: __asan_handle_no_return(); break; -    case 17: __asan_address_is_poisoned(0); break; -    case 25: __asan_poison_memory_region(0, 0); break; -    case 26: __asan_unpoison_memory_region(0, 0); break; -    case 27: __asan_set_error_exit_code(0); break; -    case 30: __asan_before_dynamic_init(0); break; -    case 31: __asan_after_dynamic_init(); break; -    case 32: __asan_poison_stack_memory(0, 0); break; -    case 33: __asan_unpoison_stack_memory(0, 0); break; -    case 34: __asan_region_is_poisoned(0, 0); break; -    case 35: __asan_describe_address(0); break; +    case 6: __asan_report_load_n(0, 0); break; +    case 7: __asan_report_store1(0); break; +    case 8: __asan_report_store2(0); break; +    case 9: __asan_report_store4(0); break; +    case 10: __asan_report_store8(0); break; +    case 11: __asan_report_store16(0); break; +    case 12: __asan_report_store_n(0, 0); break; +    case 13: __asan_report_exp_load1(0, 0); break; +    case 14: __asan_report_exp_load2(0, 0); break; +    case 15: __asan_report_exp_load4(0, 0); break; +    case 16: __asan_report_exp_load8(0, 0); break; +    case 17: __asan_report_exp_load16(0, 0); break; +    case 18: __asan_report_exp_load_n(0, 0, 0); break; +    case 19: __asan_report_exp_store1(0, 0); break; +    case 20: __asan_report_exp_store2(0, 0); break; +    case 21: __asan_report_exp_store4(0, 0); break; +    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 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 35: __asan_after_dynamic_init(); break; +    case 36: __asan_poison_stack_memory(0, 0); break; +    case 37: __asan_unpoison_stack_memory(0, 0); break; +    case 38: __asan_region_is_poisoned(0, 0); break; +    case 39: __asan_describe_address(0); break;    }  } @@ -246,9 +297,9 @@ static void InitializeHighMemEnd() {    CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0);  } -static void ProtectGap(uptr a, uptr size) { -  void *res = Mprotect(a, size); -  if (a == (uptr)res) +static void ProtectGap(uptr addr, uptr size) { +  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"); @@ -296,9 +347,9 @@ static void PrintAddressSpaceLayout() {    Printf("malloc_context_size=%zu\n",           (uptr)common_flags()->malloc_context_size); -  Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE); -  Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); -  Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); +  Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE); +  Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY); +  Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET);    CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);    if (kMidMemBeg)      CHECK(kMidShadowBeg > kLowShadowEnd && @@ -316,6 +367,11 @@ static void AsanInitInternal() {    // initialization steps look at flags().    InitializeFlags(); +  CacheBinaryName(); + +  AsanCheckIncompatibleRT(); +  AsanCheckDynamicRTPrereqs(); +    SetCanPoisonMemory(flags()->poison_heap);    SetMallocContextSize(common_flags()->malloc_context_size); @@ -371,9 +427,9 @@ static void AsanInitInternal() {    if (full_shadow_is_available) {      // mmap the low shadow plus at least one page at the left.      if (kLowShadowBeg) -      ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); +      ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");      // mmap the high shadow. -    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); +    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");      // protect the gap.      ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);      CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1); @@ -382,11 +438,11 @@ static void AsanInitInternal() {        MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {      CHECK(kLowShadowBeg != kLowShadowEnd);      // mmap the low shadow plus at least one page at the left. -    ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); +    ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");      // mmap the mid shadow. -    ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd); +    ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");      // mmap the high shadow. -    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); +    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");      // protect the gaps.      ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);      ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); @@ -446,6 +502,10 @@ static void AsanInitInternal() {    }  #endif  // CAN_SANITIZE_LEAKS +#if CAN_SANITIZE_UB +  __ubsan::InitAsPlugin(); +#endif +    InitializeSuppressions();    VReport(1, "AddressSanitizer Init done\n"); @@ -459,13 +519,11 @@ void AsanInitFromRtl() {  #if ASAN_DYNAMIC  // Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable -// (and thus normal initializer from .preinit_array haven't run). +// (and thus normal initializers from .preinit_array or modules haven't run).  class AsanInitializer {  public:  // NOLINT    AsanInitializer() { -    AsanCheckIncompatibleRT(); -    AsanCheckDynamicRTPrereqs();      AsanInitFromRtl();    }  }; @@ -517,7 +575,6 @@ void NOINLINE __asan_set_death_callback(void (*callback)(void)) {  // Initialize as requested from instrumented application code.  // We use this call as a trigger to wake up ASan from deactivated state.  void __asan_init() { -  AsanCheckIncompatibleRT();    AsanActivate();    AsanInitInternal();  } diff --git a/lib/asan/asan_stats.cc b/lib/asan/asan_stats.cc index a78b7b1e926d8..b8c68c32dfbfa 100644 --- a/lib/asan/asan_stats.cc +++ b/lib/asan/asan_stats.cc @@ -51,12 +51,8 @@ void AsanStats::Print() {               (mmaped-munmaped)>>20, mmaped>>20, munmaped>>20,               mmaps, munmaps); -  PrintMallocStatsArray("  mmaps   by size class: ", mmaped_by_size);    PrintMallocStatsArray("  mallocs by size class: ", malloced_by_size); -  PrintMallocStatsArray("  frees   by size class: ", freed_by_size); -  PrintMallocStatsArray("  rfrees  by size class: ", really_freed_by_size); -  Printf("Stats: malloc large: %zu small slow: %zu\n", -             malloc_large, malloc_small_slow); +  Printf("Stats: malloc large: %zu\n", malloc_large);  }  void AsanStats::MergeFrom(const AsanStats *stats) { @@ -161,8 +157,7 @@ uptr __sanitizer_get_free_bytes() {    GetAccumulatedStats(&stats);    uptr total_free = stats.mmaped                    - stats.munmaped -                  + stats.really_freed -                  + stats.really_freed_redzones; +                  + stats.really_freed;    uptr total_used = stats.malloced                    + stats.malloced_redzones;    // Return sane value if total_free < total_used due to racy diff --git a/lib/asan/asan_stats.h b/lib/asan/asan_stats.h index c66848dc57139..4605135e166f5 100644 --- a/lib/asan/asan_stats.h +++ b/lib/asan/asan_stats.h @@ -32,20 +32,14 @@ struct AsanStats {    uptr freed;    uptr real_frees;    uptr really_freed; -  uptr really_freed_redzones;    uptr reallocs;    uptr realloced;    uptr mmaps;    uptr mmaped;    uptr munmaps;    uptr munmaped; -  uptr mmaped_by_size[kNumberOfSizeClasses]; -  uptr malloced_by_size[kNumberOfSizeClasses]; -  uptr freed_by_size[kNumberOfSizeClasses]; -  uptr really_freed_by_size[kNumberOfSizeClasses]; -    uptr malloc_large; -  uptr malloc_small_slow; +  uptr malloced_by_size[kNumberOfSizeClasses];    // Ctor for global AsanStats (accumulated stats for dead threads).    explicit AsanStats(LinkerInitialized) { } diff --git a/lib/asan/asan_suppressions.cc b/lib/asan/asan_suppressions.cc index 62198aec64e74..41887b5c88b40 100644 --- a/lib/asan/asan_suppressions.cc +++ b/lib/asan/asan_suppressions.cc @@ -26,14 +26,28 @@ static SuppressionContext *suppression_ctx = nullptr;  static const char kInterceptorName[] = "interceptor_name";  static const char kInterceptorViaFunction[] = "interceptor_via_fun";  static const char kInterceptorViaLibrary[] = "interceptor_via_lib"; +static const char kODRViolation[] = "odr_violation";  static const char *kSuppressionTypes[] = { -    kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary}; +    kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary, +    kODRViolation}; + +extern "C" { +#if SANITIZER_SUPPORTS_WEAK_HOOKS +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE +const char *__asan_default_suppressions(); +#else +// No week hooks, provide empty implementation. +const char *__asan_default_suppressions() { return ""; } +#endif  // SANITIZER_SUPPORTS_WEAK_HOOKS +}  // extern "C"  void InitializeSuppressions() {    CHECK_EQ(nullptr, suppression_ctx);    suppression_ctx = new (suppression_placeholder)  // NOLINT        SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));    suppression_ctx->ParseFromFile(flags()->suppressions); +  if (&__asan_default_suppressions) +    suppression_ctx->Parse(__asan_default_suppressions());  }  bool IsInterceptorSuppressed(const char *interceptor_name) { @@ -49,6 +63,13 @@ bool HaveStackTraceBasedSuppressions() {           suppression_ctx->HasSuppressionType(kInterceptorViaLibrary);  } +bool IsODRViolationSuppressed(const char *global_var_name) { +  CHECK(suppression_ctx); +  Suppression *s; +  // Match "odr_violation" suppressions. +  return suppression_ctx->Match(global_var_name, kODRViolation, &s); +} +  bool IsStackTraceSuppressed(const StackTrace *stack) {    if (!HaveStackTraceBasedSuppressions())      return false; @@ -60,14 +81,10 @@ bool IsStackTraceSuppressed(const StackTrace *stack) {      uptr addr = stack->trace[i];      if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) { -      const char *module_name; -      uptr module_offset;        // Match "interceptor_via_lib" suppressions. -      if (symbolizer->GetModuleNameAndOffsetForPC(addr, &module_name, -                                                  &module_offset) && -          suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s)) { -        return true; -      } +      if (const char *module_name = symbolizer->GetModuleNameForPc(addr)) +        if (suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s)) +          return true;      }      if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) { diff --git a/lib/asan/asan_suppressions.h b/lib/asan/asan_suppressions.h index cd7ba2ef0ae73..5246b4b30334f 100644 --- a/lib/asan/asan_suppressions.h +++ b/lib/asan/asan_suppressions.h @@ -23,6 +23,7 @@ void InitializeSuppressions();  bool IsInterceptorSuppressed(const char *interceptor_name);  bool HaveStackTraceBasedSuppressions();  bool IsStackTraceSuppressed(const StackTrace *stack); +bool IsODRViolationSuppressed(const char *global_var_name);  } // namespace __asan diff --git a/lib/asan/asan_thread.h b/lib/asan/asan_thread.h index 9da136c87ef17..50acfc42d6a21 100644 --- a/lib/asan/asan_thread.h +++ b/lib/asan/asan_thread.h @@ -34,19 +34,16 @@ class AsanThread;  class AsanThreadContext : public ThreadContextBase {   public:    explicit AsanThreadContext(int tid) -      : ThreadContextBase(tid), -        announced(false), -        destructor_iterations(kPthreadDestructorIterations), -        stack_id(0), -        thread(0) { -  } +      : ThreadContextBase(tid), announced(false), +        destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), +        thread(0) {}    bool announced;    u8 destructor_iterations;    u32 stack_id;    AsanThread *thread; -  void OnCreated(void *arg); -  void OnFinished(); +  void OnCreated(void *arg) override; +  void OnFinished() override;  };  // AsanThreadContext objects are never freed, so we need many of them. diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index 693f0bcdee8e5..addb3d40a696f 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -22,21 +22,134 @@  #include "asan_interceptors.h"  #include "asan_internal.h"  #include "asan_report.h" +#include "asan_stack.h"  #include "asan_thread.h"  #include "sanitizer_common/sanitizer_libc.h"  #include "sanitizer_common/sanitizer_mutex.h" +using namespace __asan;  // NOLINT +  extern "C" { -  SANITIZER_INTERFACE_ATTRIBUTE -  int __asan_should_detect_stack_use_after_return() { -    __asan_init(); -    return __asan_option_detect_stack_use_after_return; -  } +SANITIZER_INTERFACE_ATTRIBUTE +int __asan_should_detect_stack_use_after_return() { +  __asan_init(); +  return __asan_option_detect_stack_use_after_return; +} + +// -------------------- A workaround for the abscence of weak symbols ----- {{{ +// We don't have a direct equivalent of weak symbols when using MSVC, but we can +// use the /alternatename directive to tell the linker to default a specific +// symbol to a specific value, which works nicely for allocator hooks and +// __asan_default_options(). +void __sanitizer_default_malloc_hook(void *ptr, uptr size) { } +void __sanitizer_default_free_hook(void *ptr) { } +const char* __asan_default_default_options() { return ""; } +const char* __asan_default_default_suppressions() { return ""; } +void __asan_default_on_error() {} +#pragma comment(linker, "/alternatename:___sanitizer_malloc_hook=___sanitizer_default_malloc_hook")  // NOLINT +#pragma comment(linker, "/alternatename:___sanitizer_free_hook=___sanitizer_default_free_hook")      // NOLINT +#pragma comment(linker, "/alternatename:___asan_default_options=___asan_default_default_options")    // NOLINT +#pragma comment(linker, "/alternatename:___asan_default_suppressions=___asan_default_default_suppressions")    // NOLINT +#pragma comment(linker, "/alternatename:___asan_on_error=___asan_default_on_error")                  // NOLINT +// }}} +}  // extern "C" + +// ---------------------- Windows-specific inteceptors ---------------- {{{ +INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) { +  CHECK(REAL(RaiseException)); +  __asan_handle_no_return(); +  REAL(RaiseException)(a, b, c, d); +} + +INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) { +  CHECK(REAL(_except_handler3)); +  __asan_handle_no_return(); +  return REAL(_except_handler3)(a, b, c, d); +} + +#if ASAN_DYNAMIC +// This handler is named differently in -MT and -MD CRTs. +#define _except_handler4 _except_handler4_common +#endif +INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { +  CHECK(REAL(_except_handler4)); +  __asan_handle_no_return(); +  return REAL(_except_handler4)(a, b, c, d); +} + +static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { +  AsanThread *t = (AsanThread*)arg; +  SetCurrentThread(t); +  return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr); +} + +INTERCEPTOR_WINAPI(DWORD, CreateThread, +                   void* security, uptr stack_size, +                   DWORD (__stdcall *start_routine)(void*), void* arg, +                   DWORD thr_flags, void* tid) { +  // Strict init-order checking is thread-hostile. +  if (flags()->strict_init_order) +    StopInitOrderChecking(); +  GET_STACK_TRACE_THREAD; +  // FIXME: The CreateThread interceptor is not the same as a pthread_create +  // one.  This is a bandaid fix for PR22025. +  bool detached = false;  // FIXME: how can we determine it on Windows? +  u32 current_tid = GetCurrentTidOrInvalid(); +  AsanThread *t = +        AsanThread::Create(start_routine, arg, current_tid, &stack, detached); +  return REAL(CreateThread)(security, stack_size, +                            asan_thread_start, t, thr_flags, tid); +} + +namespace { +BlockingMutex mu_for_thread_tracking(LINKER_INITIALIZED); + +void EnsureWorkerThreadRegistered() { +  // FIXME: GetCurrentThread relies on TSD, which might not play well with +  // system thread pools.  We might want to use something like reference +  // counting to zero out GetCurrentThread() underlying storage when the last +  // work item finishes?  Or can we disable reclaiming of threads in the pool? +  BlockingMutexLock l(&mu_for_thread_tracking); +  if (__asan::GetCurrentThread()) +    return; + +  AsanThread *t = AsanThread::Create( +      /* start_routine */ nullptr, /* arg */ nullptr, +      /* parent_tid */ -1, /* stack */ nullptr, /* detached */ true); +  t->Init(); +  asanThreadRegistry().StartThread(t->tid(), 0, 0); +  SetCurrentThread(t); +} +}  // namespace + +INTERCEPTOR_WINAPI(DWORD, NtWaitForWorkViaWorkerFactory, DWORD a, DWORD b) { +  // NtWaitForWorkViaWorkerFactory is called from system worker pool threads to +  // query work scheduled by BindIoCompletionCallback, QueueUserWorkItem, etc. +  // System worker pool threads are created at arbitraty point in time and +  // without using CreateThread, so we wrap NtWaitForWorkViaWorkerFactory +  // instead and don't register a specific parent_tid/stack. +  EnsureWorkerThreadRegistered(); +  return REAL(NtWaitForWorkViaWorkerFactory)(a, b);  } +// }}} +  namespace __asan { -// ---------------------- TSD ---------------- {{{1 +void InitializePlatformInterceptors() { +  ASAN_INTERCEPT_FUNC(CreateThread); +  ASAN_INTERCEPT_FUNC(RaiseException); +  ASAN_INTERCEPT_FUNC(_except_handler3); +  ASAN_INTERCEPT_FUNC(_except_handler4); + +  // NtWaitForWorkViaWorkerFactory is always linked dynamically. +  CHECK(::__interception::OverrideFunction( +      "NtWaitForWorkViaWorkerFactory", +      (uptr)WRAP(NtWaitForWorkViaWorkerFactory), +      (uptr *)&REAL(NtWaitForWorkViaWorkerFactory))); +} + +// ---------------------- TSD ---------------- {{{  static bool tsd_key_inited = false;  static __declspec(thread) void *fake_tsd = 0; @@ -59,7 +172,9 @@ void AsanTSDSet(void *tsd) {  void PlatformTSDDtor(void *tsd) {    AsanThread::TSDDtor(tsd);  } -// ---------------------- Various stuff ---------------- {{{1 +// }}} + +// ---------------------- Various stuff ---------------- {{{  void DisableReexec() {    // No need to re-exec on Windows.  } @@ -93,23 +208,6 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {  static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler; -SignalContext SignalContext::Create(void *siginfo, void *context) { -  EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo; -  CONTEXT *context_record = (CONTEXT*)context; - -  uptr pc = (uptr)exception_record->ExceptionAddress; -#ifdef _WIN64 -  uptr bp = (uptr)context_record->Rbp; -  uptr sp = (uptr)context_record->Rsp; -#else -  uptr bp = (uptr)context_record->Ebp; -  uptr sp = (uptr)context_record->Esp; -#endif -  uptr access_addr = exception_record->ExceptionInformation[1]; - -  return SignalContext(context, access_addr, pc, sp, bp); -} -  static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {    EXCEPTION_RECORD *exception_record = info->ExceptionRecord;    CONTEXT *context = info->ContextRecord; @@ -162,7 +260,7 @@ int __asan_set_seh_filter() {  static __declspec(allocate(".CRT$XIZ"))      int (*__intercept_seh)() = __asan_set_seh_filter;  #endif - +// }}}  }  // namespace __asan  #endif  // _WIN32 diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc index 5d39e33096a89..b77f18168ae5d 100644 --- a/lib/asan/asan_win_dll_thunk.cc +++ b/lib/asan/asan_win_dll_thunk.cc @@ -303,8 +303,8 @@ INTERFACE_FUNCTION(__sanitizer_cov_init)  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_with_check) -INTERFACE_FUNCTION(__sanitizer_free_hook)  INTERFACE_FUNCTION(__sanitizer_get_allocated_size)  INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)  INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes) @@ -314,13 +314,14 @@ INTERFACE_FUNCTION(__sanitizer_get_heap_size)  INTERFACE_FUNCTION(__sanitizer_get_ownership)  INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage)  INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes) -INTERFACE_FUNCTION(__sanitizer_malloc_hook)  INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file)  INTERFACE_FUNCTION(__sanitizer_print_stack_trace)  INTERFACE_FUNCTION(__sanitizer_ptr_cmp)  INTERFACE_FUNCTION(__sanitizer_ptr_sub)  INTERFACE_FUNCTION(__sanitizer_report_error_summary)  INTERFACE_FUNCTION(__sanitizer_reset_coverage) +INTERFACE_FUNCTION(__sanitizer_get_number_of_counters) +INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)  INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify)  INTERFACE_FUNCTION(__sanitizer_set_death_callback)  INTERFACE_FUNCTION(__sanitizer_set_report_path) @@ -380,11 +381,15 @@ INTERCEPT_LIBRARY_FUNCTION(strcat);  // NOLINT  INTERCEPT_LIBRARY_FUNCTION(strchr);  INTERCEPT_LIBRARY_FUNCTION(strcmp);  INTERCEPT_LIBRARY_FUNCTION(strcpy);  // NOLINT +INTERCEPT_LIBRARY_FUNCTION(strcspn);  INTERCEPT_LIBRARY_FUNCTION(strlen);  INTERCEPT_LIBRARY_FUNCTION(strncat);  INTERCEPT_LIBRARY_FUNCTION(strncmp);  INTERCEPT_LIBRARY_FUNCTION(strncpy);  INTERCEPT_LIBRARY_FUNCTION(strnlen); +INTERCEPT_LIBRARY_FUNCTION(strpbrk); +INTERCEPT_LIBRARY_FUNCTION(strspn); +INTERCEPT_LIBRARY_FUNCTION(strstr);  INTERCEPT_LIBRARY_FUNCTION(strtol);  INTERCEPT_LIBRARY_FUNCTION(wcslen); diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc index 19456141c1ecb..d59f9f5768a07 100644 --- a/lib/asan/asan_win_dynamic_runtime_thunk.cc +++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -15,7 +15,8 @@  //  // This includes:  //  - forwarding the detect_stack_use_after_return runtime option -//  - installing a custom SEH handler +//  - working around deficiencies of the MD runtime +//  - installing a custom SEH handlerx  //  //===----------------------------------------------------------------------===// @@ -24,9 +25,13 @@  // simplifies the build procedure.  #ifdef ASAN_DYNAMIC_RUNTIME_THUNK  #include <windows.h> -#include <psapi.h> -extern "C" { +// First, declare CRT sections we'll be using in this file +#pragma section(".CRT$XID", long, read)  // NOLINT +#pragma section(".CRT$XIZ", long, read)  // NOLINT +#pragma section(".CRT$XTW", long, read)  // NOLINT +#pragma section(".CRT$XTY", long, read)  // NOLINT +  ////////////////////////////////////////////////////////////////////////////////  // Define a copy of __asan_option_detect_stack_use_after_return that should be  // used when linking an MD runtime with a set of object files on Windows. @@ -38,82 +43,55 @@ extern "C" {  // with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows  // just to work around this issue, let's clone the a variable that is  // constant after initialization anyways. +extern "C" {  __declspec(dllimport) int __asan_should_detect_stack_use_after_return();  int __asan_option_detect_stack_use_after_return =      __asan_should_detect_stack_use_after_return();  }  //////////////////////////////////////////////////////////////////////////////// -// For some reason, the MD CRT doesn't call the C/C++ terminators as MT does. -// To work around this, for each DLL we schedule a call to -// UnregisterGlobalsInRange atexit() specifying the address range of the DLL -// image to unregister globals in that range.   We don't do the same -// for the main module (.exe) as the asan_globals.cc allocator is destroyed -// by the time UnregisterGlobalsInRange is executed. -// See PR22545 for the details. -namespace __asan { -__declspec(dllimport) -void UnregisterGlobalsInRange(void *beg, void *end); -} +// For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL +// unload or on exit.  ASan relies on LLVM global_dtors to call +// __asan_unregister_globals on these events, which unfortunately doesn't work +// with the MD runtime, see PR22545 for the details. +// To work around this, for each DLL we schedule a call to UnregisterGlobals +// 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" void __cdecl _initterm(void *a, void *b);  namespace { -void *this_module_base, *this_module_end; +__declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0; +__declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0;  void UnregisterGlobals() { -  __asan::UnregisterGlobalsInRange(this_module_base, this_module_end); +  _initterm(&before_global_dtors, &after_global_dtors);  }  int ScheduleUnregisterGlobals() { -  HMODULE this_module = 0; -  // Increments the reference counter of the DLL module, so need to call -  // FreeLibrary later. -  if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, -                         (LPCTSTR)&UnregisterGlobals, &this_module)) -    return 1; - -  // Skip the main module. -  if (this_module == GetModuleHandle(0)) -    return 0; - -  MODULEINFO mi; -  bool success = -      GetModuleInformation(GetCurrentProcess(), this_module, &mi, sizeof(mi)); -  if (!FreeLibrary(this_module)) -    return 2; -  if (!success) -    return 3; - -  this_module_base = mi.lpBaseOfDll; -  this_module_end = (char*)mi.lpBaseOfDll + mi.SizeOfImage; -    return atexit(UnregisterGlobals);  } -}  // namespace - -/////////////////////////////////////////////////////////////////////////////// -// ASan SEH handling. -extern "C" __declspec(dllimport) int __asan_set_seh_filter(); -static int SetSEHFilter() { return __asan_set_seh_filter(); } -/////////////////////////////////////////////////////////////////////////////// -// We schedule some work at start-up by placing callbacks to our code to the -// list of CRT C initializers. -// -// First, declare sections we'll be using: -#pragma section(".CRT$XID", long, read)  // NOLINT -#pragma section(".CRT$XIZ", long, read)  // NOLINT - -// We need to call 'atexit(UnregisterGlobals);' after atexit() is initialized -// (.CRT$XIC) but before the C++ constructors (.CRT$XCA). +// We need to call 'atexit(UnregisterGlobals);' as early as possible, but after +// atexit() is initialized (.CRT$XIC).  As this is executed before C++ +// initializers (think ctors for globals), UnregisterGlobals gets executed after +// dtors for C++ globals.  __declspec(allocate(".CRT$XID")) -static int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; +int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; +}  // namespace + +//////////////////////////////////////////////////////////////////////////////// +// ASan SEH handling.  // We need to set the ASan-specific SEH handler at the end of CRT initialization  // of each module (see also asan_win.cc). -// +extern "C" { +__declspec(dllimport) int __asan_set_seh_filter(); +static int SetSEHFilter() { return __asan_set_seh_filter(); } +  // Unfortunately, putting a pointer to __asan_set_seh_filter into  // __asan_intercept_seh gets optimized out, so we have to use an extra function. -extern "C" __declspec(allocate(".CRT$XIZ")) -int (*__asan_seh_interceptor)() = SetSEHFilter; +__declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter; +}  #endif // ASAN_DYNAMIC_RUNTIME_THUNK diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py index 59fceaaed814c..b9d3ad3ad2fe6 100755 --- a/lib/asan/scripts/asan_symbolize.py +++ b/lib/asan/scripts/asan_symbolize.py @@ -23,6 +23,7 @@ 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): @@ -392,6 +393,8 @@ class SymbolizationLoop(object):            [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)) diff --git a/lib/asan/tests/CMakeLists.txt b/lib/asan/tests/CMakeLists.txt index 513d1282f8a6f..afdd2adf08872 100644 --- a/lib/asan/tests/CMakeLists.txt +++ b/lib/asan/tests/CMakeLists.txt @@ -52,6 +52,11 @@ if(APPLE)    list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS ${DARWIN_osx_LINKFLAGS})  endif() +if(MSVC) +  # Disable exceptions on Windows until they work reliably. +  list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -fno-exceptions -DGTEST_HAS_SEH=0) +endif() +  set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")  set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS    ${ASAN_UNITTEST_COMMON_CFLAGS} @@ -94,6 +99,7 @@ append_list_if(ANDROID atomic ASAN_UNITTEST_INSTRUMENTED_LIBS)  set(ASAN_UNITTEST_NOINST_LINKFLAGS ${ASAN_UNITTEST_COMMON_LINKFLAGS})  append_list_if(COMPILER_RT_HAS_LIBM -lm ASAN_UNITTEST_NOINST_LINKFLAGS)  append_list_if(COMPILER_RT_HAS_LIBDL -ldl ASAN_UNITTEST_NOINST_LINKFLAGS) +append_list_if(COMPILER_RT_HAS_LIBRT -lrt ASAN_UNITTEST_NOINST_LINKFLAGS)  append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread ASAN_UNITTEST_NOINST_LINKFLAGS)  append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread            ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINKFLAGS) @@ -123,7 +129,7 @@ endmacro()  # Link ASan unit test for a given architecture from a set  # of objects in with given linker flags.  macro(add_asan_test test_suite test_name arch kind) -  parse_arguments(TEST "OBJECTS;LINKFLAGS;SUBDIR" "WITH_TEST_RUNTIME" ${ARGN}) +  cmake_parse_arguments(TEST "WITH_TEST_RUNTIME" "" "OBJECTS;LINKFLAGS;SUBDIR" ${ARGN})    get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)    set(TEST_DEPS ${TEST_OBJECTS})    if(NOT COMPILER_RT_STANDALONE_BUILD) @@ -214,18 +220,18 @@ macro(add_asan_tests_for_arch_and_kind arch kind)        $<TARGET_OBJECTS:RTAsan.osx>        $<TARGET_OBJECTS:RTInterception.osx>        $<TARGET_OBJECTS:RTSanitizerCommon.osx> -      $<TARGET_OBJECTS:RTLSanCommon.osx>) +      $<TARGET_OBJECTS:RTLSanCommon.osx> +      $<TARGET_OBJECTS:RTUbsan.osx>)    else()      set(ASAN_TEST_RUNTIME_OBJECTS        $<TARGET_OBJECTS:RTAsan.${arch}>        $<TARGET_OBJECTS:RTAsan_cxx.${arch}>        $<TARGET_OBJECTS:RTInterception.${arch}>        $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> -      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>) -    if(NOT WIN32) -      list(APPEND ASAN_TEST_RUNTIME_OBJECTS -           $<TARGET_OBJECTS:RTLSanCommon.${arch}>) -    endif() +      $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> +      $<TARGET_OBJECTS:RTLSanCommon.${arch}> +      $<TARGET_OBJECTS:RTUbsan.${arch}> +      $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>)    endif()    add_library(${ASAN_TEST_RUNTIME} STATIC ${ASAN_TEST_RUNTIME_OBJECTS})    set_target_properties(${ASAN_TEST_RUNTIME} PROPERTIES @@ -270,6 +276,8 @@ if(ANDROID)        $<TARGET_OBJECTS:RTInterception.${arch}>        $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>        $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> +      $<TARGET_OBJECTS:RTUbsan.${arch}> +      $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>        ${COMPILER_RT_GTEST_SOURCE}        ${ASAN_NOINST_TEST_SOURCES})      set_target_compile_flags(AsanNoinstTest ${ASAN_UNITTEST_COMMON_CFLAGS}) diff --git a/lib/asan/tests/asan_asm_test.cc b/lib/asan/tests/asan_asm_test.cc index 1d8b04d611bd5..200de2c137a54 100644 --- a/lib/asan/tests/asan_asm_test.cc +++ b/lib/asan/tests/asan_asm_test.cc @@ -232,7 +232,7 @@ TEST(AddressSanitizer, asm_flags) {    long magic = 0x1234;    long r = 0x0; -#if defined(__x86_64__) +#if defined(__x86_64__) && !defined(__ILP32__)    __asm__("xorq %%rax, %%rax  \n\t"            "movq (%[p]), %%rax \n\t"            "sete %%al          \n\t" @@ -248,7 +248,7 @@ TEST(AddressSanitizer, asm_flags) {            : [r] "=r"(r)            : [p] "r"(&magic)            : "eax", "memory"); -#endif // defined(__x86_64__) +#endif // defined(__x86_64__) && !defined(__ILP32__)    ASSERT_EQ(0x1, r);  } diff --git a/lib/asan/tests/asan_str_test.cc b/lib/asan/tests/asan_str_test.cc index 1cd2a08b90213..89b0d3d2d0f93 100644 --- a/lib/asan/tests/asan_str_test.cc +++ b/lib/asan/tests/asan_str_test.cc @@ -290,9 +290,6 @@ void RunStrCmpTest(PointerToStrCmp StrCmp) {    Ident(StrCmp(s1, s2));    Ident(StrCmp(s1, s2 + size - 1));    Ident(StrCmp(s1 + size - 1, s2 + size - 1)); -  s1[size - 1] = 'z'; -  s2[size - 1] = 'x'; -  Ident(StrCmp(s1, s2));    // 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)); @@ -371,17 +368,14 @@ TEST(AddressSanitizer, StrCatOOBTest) {    // 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 + to_size, from), RightOOBWriteMessage(0));    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 not zero-terminated. -  memset(to, 'z', to_size); -  EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(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. @@ -409,7 +403,6 @@ TEST(AddressSanitizer, StrNCatOOBTest) {    // 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 + to_size, from, 2), RightOOBWriteMessage(0));    EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBReadMessage(0));    memset(from, 'z', from_size); @@ -417,8 +410,6 @@ TEST(AddressSanitizer, StrNCatOOBTest) {    to[0] = '\0';    // "from" is too short.    EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBReadMessage(0)); -  // "to" is not zero-terminated. -  EXPECT_DEATH(strncat(to + 1, from, 1), RightOOBWriteMessage(0));    // "to" is too short to fit "from".    to[0] = 'z';    to[to_size - from_size + 1] = '\0'; @@ -508,20 +499,15 @@ void RunAtoiOOBTest(PointerToCallAtoi Atoi) {    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 or other non-digit. +  // Make last symbol a terminating NULL    array[9] = '\0';    Atoi(array); -  array[9] = 'a'; -  Atoi(array); -  Atoi(array + 9);    // 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)); -  array[8] = '-'; -  Atoi(array);    free(array);  } @@ -546,7 +532,6 @@ typedef void(*PointerToCallStrtol)(const char*, char**, int);  void RunStrtolOOBTest(PointerToCallStrtol Strtol) {    char *array = MallocAndMemsetString(3); -  char *endptr = NULL;    array[0] = '1';    array[1] = '2';    array[2] = '3'; @@ -554,19 +539,12 @@ void RunStrtolOOBTest(PointerToCallStrtol Strtol) {    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). -  Strtol(array, &endptr, 3); -  EXPECT_EQ(array + 2, endptr);    EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));    array[2] = 'z'; -  Strtol(array, &endptr, 35); -  EXPECT_EQ(array + 2, endptr);    EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBReadMessage(0));    // Add terminating zero to get rid of overflow.    array[2] = '\0';    Strtol(array, NULL, 36); -  // Don't check for overflow if base is invalid. -  Strtol(array - 1, NULL, -1); -  Strtol(array + 3, NULL, 1);    // 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)); @@ -574,13 +552,6 @@ void RunStrtolOOBTest(PointerToCallStrtol Strtol) {    EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));    array[2] = '-';    EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); -  array[1] = '+'; -  Strtol(array, NULL, 0); -  array[1] = array[2] = 'z'; -  Strtol(array, &endptr, 0); -  EXPECT_EQ(array, endptr); -  Strtol(array + 2, NULL, 0); -  EXPECT_EQ(array, endptr);    free(array);  } diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc index 952b05e21fe22..07d59e09a72f2 100644 --- a/lib/asan/tests/asan_test.cc +++ b/lib/asan/tests/asan_test.cc @@ -31,13 +31,13 @@ NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);}  template<typename T>  NOINLINE void uaf_test(int size, int off) { -  char *p = (char *)malloc_aaa(size); +  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*)(p + off)); +  asan_write((T *)((char *)p + off));  }  TEST(AddressSanitizer, HasFeatureAddressSanitizerTest) { @@ -436,10 +436,10 @@ TEST(AddressSanitizer, WrongFreeTest) {  void DoubleFree() {    int *x = (int*)malloc(100 * sizeof(int)); -  fprintf(stderr, "DoubleFree: x=%p\n", x); +  fprintf(stderr, "DoubleFree: x=%p\n", (void *)x);    free(x);    free(x); -  fprintf(stderr, "should have failed in the second free(%p)\n", x); +  fprintf(stderr, "should have failed in the second free(%p)\n", (void *)x);    abort();  } @@ -569,7 +569,7 @@ TEST(AddressSanitizer, LongJmpTest) {  }  #if !defined(_WIN32)  // Only basic longjmp is available on Windows. -NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { +NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) {    // create three red zones for these two stack objects.    int a;    int b; @@ -577,10 +577,10 @@ NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {    int *A = Ident(&a);    int *B = Ident(&b);    *A = *B; -  __builtin_longjmp((void**)buf, 1); +  _longjmp(buf, 1);  } -NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) { +NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {    // create three red zones for these two stack objects.    int a;    int b; @@ -588,10 +588,14 @@ NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) {    int *A = Ident(&a);    int *B = Ident(&b);    *A = *B; -  _longjmp(buf, 1); +  siglongjmp(buf, 1);  } -NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) { +#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; @@ -599,12 +603,9 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {    int *A = Ident(&a);    int *B = Ident(&b);    *A = *B; -  siglongjmp(buf, 1); +  __builtin_longjmp((void**)buf, 1);  } -#if !defined(__ANDROID__) && !defined(__arm__) && \ -    !defined(__powerpc64__) && !defined(__powerpc__) && \ -    !defined(__aarch64__)  // Does not work on Power and ARM:  // https://code.google.com/p/address-sanitizer/issues/detail?id=185  TEST(AddressSanitizer, BuiltinLongJmpTest) { @@ -616,7 +617,8 @@ TEST(AddressSanitizer, BuiltinLongJmpTest) {    }  }  #endif  // !defined(__ANDROID__) && !defined(__powerpc64__) && -        // !defined(__powerpc__) && !defined(__arm__) +        // !defined(__powerpc__) && !defined(__arm__) && +        // !defined(__mips__) && !defined(__mips64)  TEST(AddressSanitizer, UnderscopeLongJmpTest) {    static jmp_buf buf; @@ -1243,7 +1245,7 @@ TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) {    const size_t kAllocSize = (1 << 28) - 1024;    size_t total_size = 0;    while (true) { -    char *x = (char*)malloc(kAllocSize); +    void *x = malloc(kAllocSize);      memset(x, 0, kAllocSize);      total_size += kAllocSize;      fprintf(stderr, "total: %ldM %p\n", (long)total_size >> 20, x);  | 
