aboutsummaryrefslogtreecommitdiff
path: root/lib/asan
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asan')
-rw-r--r--lib/asan/CMakeLists.txt105
-rw-r--r--lib/asan/asan_allocator.cc9
-rw-r--r--lib/asan/asan_allocator.h2
-rw-r--r--lib/asan/asan_fake_stack.cc23
-rw-r--r--lib/asan/asan_flags.cc22
-rw-r--r--lib/asan/asan_globals.cc76
-rw-r--r--lib/asan/asan_interceptors.cc156
-rw-r--r--lib/asan/asan_interceptors.h12
-rw-r--r--lib/asan/asan_interface_internal.h21
-rw-r--r--lib/asan/asan_internal.h18
-rw-r--r--lib/asan/asan_linux.cc77
-rw-r--r--lib/asan/asan_mac.cc66
-rw-r--r--lib/asan/asan_mapping.h15
-rw-r--r--lib/asan/asan_poisoning.cc6
-rw-r--r--lib/asan/asan_poisoning.h2
-rw-r--r--lib/asan/asan_posix.cc8
-rw-r--r--lib/asan/asan_report.cc65
-rw-r--r--lib/asan/asan_report.h13
-rw-r--r--lib/asan/asan_rtl.cc161
-rw-r--r--lib/asan/asan_stats.cc9
-rw-r--r--lib/asan/asan_stats.h8
-rw-r--r--lib/asan/asan_suppressions.cc33
-rw-r--r--lib/asan/asan_suppressions.h1
-rw-r--r--lib/asan/asan_thread.h13
-rw-r--r--lib/asan/asan_win.cc148
-rw-r--r--lib/asan/asan_win_dll_thunk.cc9
-rw-r--r--lib/asan/asan_win_dynamic_runtime_thunk.cc94
-rwxr-xr-xlib/asan/scripts/asan_symbolize.py3
-rw-r--r--lib/asan/tests/CMakeLists.txt22
-rw-r--r--lib/asan/tests/asan_asm_test.cc4
-rw-r--r--lib/asan/tests/asan_str_test.cc33
-rw-r--r--lib/asan/tests/asan_test.cc32
32 files changed, 687 insertions, 579 deletions
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt
index d4c5c17d36a2..28611a8a4659 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 fd63ac68c09e..2df9a510bd9a 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 3208d1f950cd..5ccd00c97bab 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 bf4f1eb4c781..d20641155b88 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 efb7767d5d91..e8ea549b62e3 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 06140bbb360a..c34b1d3cedf2 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 3dc7ec67a3e5..d8b48d391ab8 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(), &param->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 ee3b82aa7ef9..488ada78ab8b 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 ea7540f6bb56..ad8ebcd91ad9 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 ffd3ff82d71e..107e16ee31b9 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 8e8bafd47af6..9580fc7c06d4 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 b35368617dca..3e028378df28 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 5cb011d683d3..f9e1a527de18 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 e2b1f4dc4d5e..569d359aa425 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 3fc94649fb39..6344225f0f64 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 ad31458df28d..2e857f6f624c 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 8706d5decc0b..c1681e644464 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 029c914b8a04..e2786b0f260c 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 9126e71a6437..a8d92b915a9a 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 a78b7b1e926d..b8c68c32dfbf 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 c66848dc5713..4605135e166f 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 62198aec64e7..41887b5c88b4 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 cd7ba2ef0ae7..5246b4b30334 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 9da136c87ef1..50acfc42d6a2 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 693f0bcdee8e..addb3d40a696 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 5d39e33096a8..b77f18168ae5 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 19456141c1ec..d59f9f5768a0 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 59fceaaed814..b9d3ad3ad2fe 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 513d1282f8a6..afdd2adf0887 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 1d8b04d611bd..200de2c137a5 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 1cd2a08b9021..89b0d3d2d0f9 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 952b05e21fe2..07d59e09a72f 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);