13cab2bb3Spatrick //===-- asan_report.cpp ---------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker.
103cab2bb3Spatrick //
113cab2bb3Spatrick // This file contains error reporting code.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick
14*810390e3Srobert #include "asan_report.h"
15*810390e3Srobert
16*810390e3Srobert #include "asan_descriptions.h"
173cab2bb3Spatrick #include "asan_errors.h"
183cab2bb3Spatrick #include "asan_flags.h"
193cab2bb3Spatrick #include "asan_internal.h"
203cab2bb3Spatrick #include "asan_mapping.h"
213cab2bb3Spatrick #include "asan_scariness_score.h"
223cab2bb3Spatrick #include "asan_stack.h"
233cab2bb3Spatrick #include "asan_thread.h"
243cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h"
253cab2bb3Spatrick #include "sanitizer_common/sanitizer_flags.h"
26*810390e3Srobert #include "sanitizer_common/sanitizer_interface_internal.h"
273cab2bb3Spatrick #include "sanitizer_common/sanitizer_report_decorator.h"
283cab2bb3Spatrick #include "sanitizer_common/sanitizer_stackdepot.h"
293cab2bb3Spatrick #include "sanitizer_common/sanitizer_symbolizer.h"
303cab2bb3Spatrick
313cab2bb3Spatrick namespace __asan {
323cab2bb3Spatrick
333cab2bb3Spatrick // -------------------- User-specified callbacks ----------------- {{{1
343cab2bb3Spatrick static void (*error_report_callback)(const char*);
353cab2bb3Spatrick static char *error_message_buffer = nullptr;
363cab2bb3Spatrick static uptr error_message_buffer_pos = 0;
37*810390e3Srobert static Mutex error_message_buf_mutex;
383cab2bb3Spatrick static const unsigned kAsanBuggyPcPoolSize = 25;
393cab2bb3Spatrick static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
403cab2bb3Spatrick
AppendToErrorMessageBuffer(const char * buffer)413cab2bb3Spatrick void AppendToErrorMessageBuffer(const char *buffer) {
42*810390e3Srobert Lock l(&error_message_buf_mutex);
433cab2bb3Spatrick if (!error_message_buffer) {
443cab2bb3Spatrick error_message_buffer =
453cab2bb3Spatrick (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
463cab2bb3Spatrick error_message_buffer_pos = 0;
473cab2bb3Spatrick }
483cab2bb3Spatrick uptr length = internal_strlen(buffer);
493cab2bb3Spatrick RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos);
503cab2bb3Spatrick uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos;
513cab2bb3Spatrick internal_strncpy(error_message_buffer + error_message_buffer_pos,
523cab2bb3Spatrick buffer, remaining);
533cab2bb3Spatrick error_message_buffer[kErrorMessageBufferSize - 1] = '\0';
543cab2bb3Spatrick // FIXME: reallocate the buffer instead of truncating the message.
553cab2bb3Spatrick error_message_buffer_pos += Min(remaining, length);
563cab2bb3Spatrick }
573cab2bb3Spatrick
583cab2bb3Spatrick // ---------------------- Helper functions ----------------------- {{{1
593cab2bb3Spatrick
PrintMemoryByte(InternalScopedString * str,const char * before,u8 byte,bool in_shadow,const char * after)603cab2bb3Spatrick void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
613cab2bb3Spatrick bool in_shadow, const char *after) {
623cab2bb3Spatrick Decorator d;
633cab2bb3Spatrick str->append("%s%s%x%x%s%s", before,
643cab2bb3Spatrick in_shadow ? d.ShadowByte(byte) : d.MemoryByte(), byte >> 4,
653cab2bb3Spatrick byte & 15, d.Default(), after);
663cab2bb3Spatrick }
673cab2bb3Spatrick
PrintZoneForPointer(uptr ptr,uptr zone_ptr,const char * zone_name)683cab2bb3Spatrick static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
693cab2bb3Spatrick const char *zone_name) {
703cab2bb3Spatrick if (zone_ptr) {
713cab2bb3Spatrick if (zone_name) {
72*810390e3Srobert Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", (void *)ptr,
73*810390e3Srobert (void *)zone_ptr, zone_name);
743cab2bb3Spatrick } else {
753cab2bb3Spatrick Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
76*810390e3Srobert (void *)ptr, (void *)zone_ptr);
773cab2bb3Spatrick }
783cab2bb3Spatrick } else {
79*810390e3Srobert Printf("malloc_zone_from_ptr(%p) = 0\n", (void *)ptr);
803cab2bb3Spatrick }
813cab2bb3Spatrick }
823cab2bb3Spatrick
833cab2bb3Spatrick // ---------------------- Address Descriptions ------------------- {{{1
843cab2bb3Spatrick
ParseFrameDescription(const char * frame_descr,InternalMmapVector<StackVarDescr> * vars)853cab2bb3Spatrick bool ParseFrameDescription(const char *frame_descr,
863cab2bb3Spatrick InternalMmapVector<StackVarDescr> *vars) {
873cab2bb3Spatrick CHECK(frame_descr);
883cab2bb3Spatrick const char *p;
893cab2bb3Spatrick // This string is created by the compiler and has the following form:
903cab2bb3Spatrick // "n alloc_1 alloc_2 ... alloc_n"
913cab2bb3Spatrick // where alloc_i looks like "offset size len ObjectName"
923cab2bb3Spatrick // or "offset size len ObjectName:line".
933cab2bb3Spatrick uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
943cab2bb3Spatrick if (n_objects == 0)
953cab2bb3Spatrick return false;
963cab2bb3Spatrick
973cab2bb3Spatrick for (uptr i = 0; i < n_objects; i++) {
983cab2bb3Spatrick uptr beg = (uptr)internal_simple_strtoll(p, &p, 10);
993cab2bb3Spatrick uptr size = (uptr)internal_simple_strtoll(p, &p, 10);
1003cab2bb3Spatrick uptr len = (uptr)internal_simple_strtoll(p, &p, 10);
1013cab2bb3Spatrick if (beg == 0 || size == 0 || *p != ' ') {
1023cab2bb3Spatrick return false;
1033cab2bb3Spatrick }
1043cab2bb3Spatrick p++;
1053cab2bb3Spatrick char *colon_pos = internal_strchr(p, ':');
1063cab2bb3Spatrick uptr line = 0;
1073cab2bb3Spatrick uptr name_len = len;
1083cab2bb3Spatrick if (colon_pos != nullptr && colon_pos < p + len) {
1093cab2bb3Spatrick name_len = colon_pos - p;
1103cab2bb3Spatrick line = (uptr)internal_simple_strtoll(colon_pos + 1, nullptr, 10);
1113cab2bb3Spatrick }
1123cab2bb3Spatrick StackVarDescr var = {beg, size, p, name_len, line};
1133cab2bb3Spatrick vars->push_back(var);
1143cab2bb3Spatrick p += len;
1153cab2bb3Spatrick }
1163cab2bb3Spatrick
1173cab2bb3Spatrick return true;
1183cab2bb3Spatrick }
1193cab2bb3Spatrick
1203cab2bb3Spatrick // -------------------- Different kinds of reports ----------------- {{{1
1213cab2bb3Spatrick
1223cab2bb3Spatrick // Use ScopedInErrorReport to run common actions just before and
1233cab2bb3Spatrick // immediately after printing error report.
1243cab2bb3Spatrick class ScopedInErrorReport {
1253cab2bb3Spatrick public:
ScopedInErrorReport(bool fatal=false)1263cab2bb3Spatrick explicit ScopedInErrorReport(bool fatal = false)
1273cab2bb3Spatrick : halt_on_error_(fatal || flags()->halt_on_error) {
1283cab2bb3Spatrick // Make sure the registry and sanitizer report mutexes are locked while
1293cab2bb3Spatrick // we're printing an error report.
1303cab2bb3Spatrick // We can lock them only here to avoid self-deadlock in case of
1313cab2bb3Spatrick // recursive reports.
1323cab2bb3Spatrick asanThreadRegistry().Lock();
1333cab2bb3Spatrick Printf(
1343cab2bb3Spatrick "=================================================================\n");
1353cab2bb3Spatrick }
1363cab2bb3Spatrick
~ScopedInErrorReport()1373cab2bb3Spatrick ~ScopedInErrorReport() {
1383cab2bb3Spatrick if (halt_on_error_ && !__sanitizer_acquire_crash_state()) {
1393cab2bb3Spatrick asanThreadRegistry().Unlock();
1403cab2bb3Spatrick return;
1413cab2bb3Spatrick }
1423cab2bb3Spatrick ASAN_ON_ERROR();
1433cab2bb3Spatrick if (current_error_.IsValid()) current_error_.Print();
1443cab2bb3Spatrick
1453cab2bb3Spatrick // Make sure the current thread is announced.
1463cab2bb3Spatrick DescribeThread(GetCurrentThread());
1473cab2bb3Spatrick // We may want to grab this lock again when printing stats.
1483cab2bb3Spatrick asanThreadRegistry().Unlock();
1493cab2bb3Spatrick // Print memory stats.
1503cab2bb3Spatrick if (flags()->print_stats)
1513cab2bb3Spatrick __asan_print_accumulated_stats();
1523cab2bb3Spatrick
1533cab2bb3Spatrick if (common_flags()->print_cmdline)
1543cab2bb3Spatrick PrintCmdline();
1553cab2bb3Spatrick
156d89ec533Spatrick if (common_flags()->print_module_map == 2)
157d89ec533Spatrick DumpProcessMap();
1583cab2bb3Spatrick
1593cab2bb3Spatrick // Copy the message buffer so that we could start logging without holding a
160*810390e3Srobert // lock that gets acquired during printing.
1613cab2bb3Spatrick InternalMmapVector<char> buffer_copy(kErrorMessageBufferSize);
1623cab2bb3Spatrick {
163*810390e3Srobert Lock l(&error_message_buf_mutex);
1643cab2bb3Spatrick internal_memcpy(buffer_copy.data(),
1653cab2bb3Spatrick error_message_buffer, kErrorMessageBufferSize);
1661f9cb04fSpatrick // Clear error_message_buffer so that if we find other errors
1671f9cb04fSpatrick // we don't re-log this error.
1681f9cb04fSpatrick error_message_buffer_pos = 0;
1693cab2bb3Spatrick }
1703cab2bb3Spatrick
1713cab2bb3Spatrick LogFullErrorReport(buffer_copy.data());
1723cab2bb3Spatrick
1733cab2bb3Spatrick if (error_report_callback) {
1743cab2bb3Spatrick error_report_callback(buffer_copy.data());
1753cab2bb3Spatrick }
1763cab2bb3Spatrick
1773cab2bb3Spatrick if (halt_on_error_ && common_flags()->abort_on_error) {
1783cab2bb3Spatrick // On Android the message is truncated to 512 characters.
1793cab2bb3Spatrick // FIXME: implement "compact" error format, possibly without, or with
1803cab2bb3Spatrick // highly compressed stack traces?
1813cab2bb3Spatrick // FIXME: or just use the summary line as abort message?
1823cab2bb3Spatrick SetAbortMessage(buffer_copy.data());
1833cab2bb3Spatrick }
1843cab2bb3Spatrick
1853cab2bb3Spatrick // In halt_on_error = false mode, reset the current error object (before
1863cab2bb3Spatrick // unlocking).
1873cab2bb3Spatrick if (!halt_on_error_)
1883cab2bb3Spatrick internal_memset(¤t_error_, 0, sizeof(current_error_));
1893cab2bb3Spatrick
1903cab2bb3Spatrick if (halt_on_error_) {
1913cab2bb3Spatrick Report("ABORTING\n");
1923cab2bb3Spatrick Die();
1933cab2bb3Spatrick }
1943cab2bb3Spatrick }
1953cab2bb3Spatrick
ReportError(const ErrorDescription & description)1963cab2bb3Spatrick void ReportError(const ErrorDescription &description) {
1973cab2bb3Spatrick // Can only report one error per ScopedInErrorReport.
1983cab2bb3Spatrick CHECK_EQ(current_error_.kind, kErrorKindInvalid);
1993cab2bb3Spatrick internal_memcpy(¤t_error_, &description, sizeof(current_error_));
2003cab2bb3Spatrick }
2013cab2bb3Spatrick
CurrentError()2023cab2bb3Spatrick static ErrorDescription &CurrentError() {
2033cab2bb3Spatrick return current_error_;
2043cab2bb3Spatrick }
2053cab2bb3Spatrick
2063cab2bb3Spatrick private:
2073cab2bb3Spatrick ScopedErrorReportLock error_report_lock_;
2083cab2bb3Spatrick // Error currently being reported. This enables the destructor to interact
2093cab2bb3Spatrick // with the debugger and point it to an error description.
2103cab2bb3Spatrick static ErrorDescription current_error_;
2113cab2bb3Spatrick bool halt_on_error_;
2123cab2bb3Spatrick };
2133cab2bb3Spatrick
2143cab2bb3Spatrick ErrorDescription ScopedInErrorReport::current_error_(LINKER_INITIALIZED);
2153cab2bb3Spatrick
ReportDeadlySignal(const SignalContext & sig)2163cab2bb3Spatrick void ReportDeadlySignal(const SignalContext &sig) {
2173cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
2183cab2bb3Spatrick ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig);
2193cab2bb3Spatrick in_report.ReportError(error);
2203cab2bb3Spatrick }
2213cab2bb3Spatrick
ReportDoubleFree(uptr addr,BufferedStackTrace * free_stack)2223cab2bb3Spatrick void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
2233cab2bb3Spatrick ScopedInErrorReport in_report;
2243cab2bb3Spatrick ErrorDoubleFree error(GetCurrentTidOrInvalid(), free_stack, addr);
2253cab2bb3Spatrick in_report.ReportError(error);
2263cab2bb3Spatrick }
2273cab2bb3Spatrick
ReportNewDeleteTypeMismatch(uptr addr,uptr delete_size,uptr delete_alignment,BufferedStackTrace * free_stack)2283cab2bb3Spatrick void ReportNewDeleteTypeMismatch(uptr addr, uptr delete_size,
2293cab2bb3Spatrick uptr delete_alignment,
2303cab2bb3Spatrick BufferedStackTrace *free_stack) {
2313cab2bb3Spatrick ScopedInErrorReport in_report;
2323cab2bb3Spatrick ErrorNewDeleteTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
2333cab2bb3Spatrick delete_size, delete_alignment);
2343cab2bb3Spatrick in_report.ReportError(error);
2353cab2bb3Spatrick }
2363cab2bb3Spatrick
ReportFreeNotMalloced(uptr addr,BufferedStackTrace * free_stack)2373cab2bb3Spatrick void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
2383cab2bb3Spatrick ScopedInErrorReport in_report;
2393cab2bb3Spatrick ErrorFreeNotMalloced error(GetCurrentTidOrInvalid(), free_stack, addr);
2403cab2bb3Spatrick in_report.ReportError(error);
2413cab2bb3Spatrick }
2423cab2bb3Spatrick
ReportAllocTypeMismatch(uptr addr,BufferedStackTrace * free_stack,AllocType alloc_type,AllocType dealloc_type)2433cab2bb3Spatrick void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
2443cab2bb3Spatrick AllocType alloc_type,
2453cab2bb3Spatrick AllocType dealloc_type) {
2463cab2bb3Spatrick ScopedInErrorReport in_report;
2473cab2bb3Spatrick ErrorAllocTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
2483cab2bb3Spatrick alloc_type, dealloc_type);
2493cab2bb3Spatrick in_report.ReportError(error);
2503cab2bb3Spatrick }
2513cab2bb3Spatrick
ReportMallocUsableSizeNotOwned(uptr addr,BufferedStackTrace * stack)2523cab2bb3Spatrick void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
2533cab2bb3Spatrick ScopedInErrorReport in_report;
2543cab2bb3Spatrick ErrorMallocUsableSizeNotOwned error(GetCurrentTidOrInvalid(), stack, addr);
2553cab2bb3Spatrick in_report.ReportError(error);
2563cab2bb3Spatrick }
2573cab2bb3Spatrick
ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,BufferedStackTrace * stack)2583cab2bb3Spatrick void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
2593cab2bb3Spatrick BufferedStackTrace *stack) {
2603cab2bb3Spatrick ScopedInErrorReport in_report;
2613cab2bb3Spatrick ErrorSanitizerGetAllocatedSizeNotOwned error(GetCurrentTidOrInvalid(), stack,
2623cab2bb3Spatrick addr);
2633cab2bb3Spatrick in_report.ReportError(error);
2643cab2bb3Spatrick }
2653cab2bb3Spatrick
ReportCallocOverflow(uptr count,uptr size,BufferedStackTrace * stack)2663cab2bb3Spatrick void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack) {
2673cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
2683cab2bb3Spatrick ErrorCallocOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
2693cab2bb3Spatrick in_report.ReportError(error);
2703cab2bb3Spatrick }
2713cab2bb3Spatrick
ReportReallocArrayOverflow(uptr count,uptr size,BufferedStackTrace * stack)2723cab2bb3Spatrick void ReportReallocArrayOverflow(uptr count, uptr size,
2733cab2bb3Spatrick BufferedStackTrace *stack) {
2743cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
2753cab2bb3Spatrick ErrorReallocArrayOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
2763cab2bb3Spatrick in_report.ReportError(error);
2773cab2bb3Spatrick }
2783cab2bb3Spatrick
ReportPvallocOverflow(uptr size,BufferedStackTrace * stack)2793cab2bb3Spatrick void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack) {
2803cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
2813cab2bb3Spatrick ErrorPvallocOverflow error(GetCurrentTidOrInvalid(), stack, size);
2823cab2bb3Spatrick in_report.ReportError(error);
2833cab2bb3Spatrick }
2843cab2bb3Spatrick
ReportInvalidAllocationAlignment(uptr alignment,BufferedStackTrace * stack)2853cab2bb3Spatrick void ReportInvalidAllocationAlignment(uptr alignment,
2863cab2bb3Spatrick BufferedStackTrace *stack) {
2873cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
2883cab2bb3Spatrick ErrorInvalidAllocationAlignment error(GetCurrentTidOrInvalid(), stack,
2893cab2bb3Spatrick alignment);
2903cab2bb3Spatrick in_report.ReportError(error);
2913cab2bb3Spatrick }
2923cab2bb3Spatrick
ReportInvalidAlignedAllocAlignment(uptr size,uptr alignment,BufferedStackTrace * stack)2933cab2bb3Spatrick void ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
2943cab2bb3Spatrick BufferedStackTrace *stack) {
2953cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
2963cab2bb3Spatrick ErrorInvalidAlignedAllocAlignment error(GetCurrentTidOrInvalid(), stack,
2973cab2bb3Spatrick size, alignment);
2983cab2bb3Spatrick in_report.ReportError(error);
2993cab2bb3Spatrick }
3003cab2bb3Spatrick
ReportInvalidPosixMemalignAlignment(uptr alignment,BufferedStackTrace * stack)3013cab2bb3Spatrick void ReportInvalidPosixMemalignAlignment(uptr alignment,
3023cab2bb3Spatrick BufferedStackTrace *stack) {
3033cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
3043cab2bb3Spatrick ErrorInvalidPosixMemalignAlignment error(GetCurrentTidOrInvalid(), stack,
3053cab2bb3Spatrick alignment);
3063cab2bb3Spatrick in_report.ReportError(error);
3073cab2bb3Spatrick }
3083cab2bb3Spatrick
ReportAllocationSizeTooBig(uptr user_size,uptr total_size,uptr max_size,BufferedStackTrace * stack)3093cab2bb3Spatrick void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
3103cab2bb3Spatrick BufferedStackTrace *stack) {
3113cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
3123cab2bb3Spatrick ErrorAllocationSizeTooBig error(GetCurrentTidOrInvalid(), stack, user_size,
3133cab2bb3Spatrick total_size, max_size);
3143cab2bb3Spatrick in_report.ReportError(error);
3153cab2bb3Spatrick }
3163cab2bb3Spatrick
ReportRssLimitExceeded(BufferedStackTrace * stack)3173cab2bb3Spatrick void ReportRssLimitExceeded(BufferedStackTrace *stack) {
3183cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
3193cab2bb3Spatrick ErrorRssLimitExceeded error(GetCurrentTidOrInvalid(), stack);
3203cab2bb3Spatrick in_report.ReportError(error);
3213cab2bb3Spatrick }
3223cab2bb3Spatrick
ReportOutOfMemory(uptr requested_size,BufferedStackTrace * stack)3233cab2bb3Spatrick void ReportOutOfMemory(uptr requested_size, BufferedStackTrace *stack) {
3243cab2bb3Spatrick ScopedInErrorReport in_report(/*fatal*/ true);
3253cab2bb3Spatrick ErrorOutOfMemory error(GetCurrentTidOrInvalid(), stack, requested_size);
3263cab2bb3Spatrick in_report.ReportError(error);
3273cab2bb3Spatrick }
3283cab2bb3Spatrick
ReportStringFunctionMemoryRangesOverlap(const char * function,const char * offset1,uptr length1,const char * offset2,uptr length2,BufferedStackTrace * stack)3293cab2bb3Spatrick void ReportStringFunctionMemoryRangesOverlap(const char *function,
3303cab2bb3Spatrick const char *offset1, uptr length1,
3313cab2bb3Spatrick const char *offset2, uptr length2,
3323cab2bb3Spatrick BufferedStackTrace *stack) {
3333cab2bb3Spatrick ScopedInErrorReport in_report;
3343cab2bb3Spatrick ErrorStringFunctionMemoryRangesOverlap error(
3353cab2bb3Spatrick GetCurrentTidOrInvalid(), stack, (uptr)offset1, length1, (uptr)offset2,
3363cab2bb3Spatrick length2, function);
3373cab2bb3Spatrick in_report.ReportError(error);
3383cab2bb3Spatrick }
3393cab2bb3Spatrick
ReportStringFunctionSizeOverflow(uptr offset,uptr size,BufferedStackTrace * stack)3403cab2bb3Spatrick void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
3413cab2bb3Spatrick BufferedStackTrace *stack) {
3423cab2bb3Spatrick ScopedInErrorReport in_report;
3433cab2bb3Spatrick ErrorStringFunctionSizeOverflow error(GetCurrentTidOrInvalid(), stack, offset,
3443cab2bb3Spatrick size);
3453cab2bb3Spatrick in_report.ReportError(error);
3463cab2bb3Spatrick }
3473cab2bb3Spatrick
ReportBadParamsToAnnotateContiguousContainer(uptr beg,uptr end,uptr old_mid,uptr new_mid,BufferedStackTrace * stack)3483cab2bb3Spatrick void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
3493cab2bb3Spatrick uptr old_mid, uptr new_mid,
3503cab2bb3Spatrick BufferedStackTrace *stack) {
3513cab2bb3Spatrick ScopedInErrorReport in_report;
3523cab2bb3Spatrick ErrorBadParamsToAnnotateContiguousContainer error(
3533cab2bb3Spatrick GetCurrentTidOrInvalid(), stack, beg, end, old_mid, new_mid);
3543cab2bb3Spatrick in_report.ReportError(error);
3553cab2bb3Spatrick }
3563cab2bb3Spatrick
ReportBadParamsToAnnotateDoubleEndedContiguousContainer(uptr storage_beg,uptr storage_end,uptr old_container_beg,uptr old_container_end,uptr new_container_beg,uptr new_container_end,BufferedStackTrace * stack)357*810390e3Srobert void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
358*810390e3Srobert uptr storage_beg, uptr storage_end, uptr old_container_beg,
359*810390e3Srobert uptr old_container_end, uptr new_container_beg, uptr new_container_end,
360*810390e3Srobert BufferedStackTrace *stack) {
361*810390e3Srobert ScopedInErrorReport in_report;
362*810390e3Srobert ErrorBadParamsToAnnotateDoubleEndedContiguousContainer error(
363*810390e3Srobert GetCurrentTidOrInvalid(), stack, storage_beg, storage_end,
364*810390e3Srobert old_container_beg, old_container_end, new_container_beg,
365*810390e3Srobert new_container_end);
366*810390e3Srobert in_report.ReportError(error);
367*810390e3Srobert }
368*810390e3Srobert
ReportODRViolation(const __asan_global * g1,u32 stack_id1,const __asan_global * g2,u32 stack_id2)3693cab2bb3Spatrick void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
3703cab2bb3Spatrick const __asan_global *g2, u32 stack_id2) {
3713cab2bb3Spatrick ScopedInErrorReport in_report;
3723cab2bb3Spatrick ErrorODRViolation error(GetCurrentTidOrInvalid(), g1, stack_id1, g2,
3733cab2bb3Spatrick stack_id2);
3743cab2bb3Spatrick in_report.ReportError(error);
3753cab2bb3Spatrick }
3763cab2bb3Spatrick
3773cab2bb3Spatrick // ----------------------- CheckForInvalidPointerPair ----------- {{{1
ReportInvalidPointerPair(uptr pc,uptr bp,uptr sp,uptr a1,uptr a2)3783cab2bb3Spatrick static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp,
3793cab2bb3Spatrick uptr a1, uptr a2) {
3803cab2bb3Spatrick ScopedInErrorReport in_report;
3813cab2bb3Spatrick ErrorInvalidPointerPair error(GetCurrentTidOrInvalid(), pc, bp, sp, a1, a2);
3823cab2bb3Spatrick in_report.ReportError(error);
3833cab2bb3Spatrick }
3843cab2bb3Spatrick
IsInvalidPointerPair(uptr a1,uptr a2)3853cab2bb3Spatrick static bool IsInvalidPointerPair(uptr a1, uptr a2) {
3863cab2bb3Spatrick if (a1 == a2)
3873cab2bb3Spatrick return false;
3883cab2bb3Spatrick
3893cab2bb3Spatrick // 256B in shadow memory can be iterated quite fast
3903cab2bb3Spatrick static const uptr kMaxOffset = 2048;
3913cab2bb3Spatrick
3923cab2bb3Spatrick uptr left = a1 < a2 ? a1 : a2;
3933cab2bb3Spatrick uptr right = a1 < a2 ? a2 : a1;
3943cab2bb3Spatrick uptr offset = right - left;
3953cab2bb3Spatrick if (offset <= kMaxOffset)
3963cab2bb3Spatrick return __asan_region_is_poisoned(left, offset);
3973cab2bb3Spatrick
3983cab2bb3Spatrick AsanThread *t = GetCurrentThread();
3993cab2bb3Spatrick
4003cab2bb3Spatrick // check whether left is a stack memory pointer
4013cab2bb3Spatrick if (uptr shadow_offset1 = t->GetStackVariableShadowStart(left)) {
4023cab2bb3Spatrick uptr shadow_offset2 = t->GetStackVariableShadowStart(right);
4033cab2bb3Spatrick return shadow_offset2 == 0 || shadow_offset1 != shadow_offset2;
4043cab2bb3Spatrick }
4053cab2bb3Spatrick
4063cab2bb3Spatrick // check whether left is a heap memory address
4073cab2bb3Spatrick HeapAddressDescription hdesc1, hdesc2;
4083cab2bb3Spatrick if (GetHeapAddressInformation(left, 0, &hdesc1) &&
4093cab2bb3Spatrick hdesc1.chunk_access.access_type == kAccessTypeInside)
4103cab2bb3Spatrick return !GetHeapAddressInformation(right, 0, &hdesc2) ||
4113cab2bb3Spatrick hdesc2.chunk_access.access_type != kAccessTypeInside ||
4123cab2bb3Spatrick hdesc1.chunk_access.chunk_begin != hdesc2.chunk_access.chunk_begin;
4133cab2bb3Spatrick
4143cab2bb3Spatrick // check whether left is an address of a global variable
4153cab2bb3Spatrick GlobalAddressDescription gdesc1, gdesc2;
4163cab2bb3Spatrick if (GetGlobalAddressInformation(left, 0, &gdesc1))
4173cab2bb3Spatrick return !GetGlobalAddressInformation(right - 1, 0, &gdesc2) ||
4183cab2bb3Spatrick !gdesc1.PointsInsideTheSameVariable(gdesc2);
4193cab2bb3Spatrick
4203cab2bb3Spatrick if (t->GetStackVariableShadowStart(right) ||
4213cab2bb3Spatrick GetHeapAddressInformation(right, 0, &hdesc2) ||
4223cab2bb3Spatrick GetGlobalAddressInformation(right - 1, 0, &gdesc2))
4233cab2bb3Spatrick return true;
4243cab2bb3Spatrick
4253cab2bb3Spatrick // At this point we know nothing about both a1 and a2 addresses.
4263cab2bb3Spatrick return false;
4273cab2bb3Spatrick }
4283cab2bb3Spatrick
CheckForInvalidPointerPair(void * p1,void * p2)429d89ec533Spatrick static inline void CheckForInvalidPointerPair(void *p1, void *p2) {
4303cab2bb3Spatrick switch (flags()->detect_invalid_pointer_pairs) {
4313cab2bb3Spatrick case 0:
4323cab2bb3Spatrick return;
4333cab2bb3Spatrick case 1:
4343cab2bb3Spatrick if (p1 == nullptr || p2 == nullptr)
4353cab2bb3Spatrick return;
4363cab2bb3Spatrick break;
4373cab2bb3Spatrick }
4383cab2bb3Spatrick
4393cab2bb3Spatrick uptr a1 = reinterpret_cast<uptr>(p1);
4403cab2bb3Spatrick uptr a2 = reinterpret_cast<uptr>(p2);
4413cab2bb3Spatrick
4423cab2bb3Spatrick if (IsInvalidPointerPair(a1, a2)) {
4433cab2bb3Spatrick GET_CALLER_PC_BP_SP;
4443cab2bb3Spatrick ReportInvalidPointerPair(pc, bp, sp, a1, a2);
4453cab2bb3Spatrick }
4463cab2bb3Spatrick }
4473cab2bb3Spatrick // ----------------------- Mac-specific reports ----------------- {{{1
4483cab2bb3Spatrick
ReportMacMzReallocUnknown(uptr addr,uptr zone_ptr,const char * zone_name,BufferedStackTrace * stack)4493cab2bb3Spatrick void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
4503cab2bb3Spatrick BufferedStackTrace *stack) {
4513cab2bb3Spatrick ScopedInErrorReport in_report;
452*810390e3Srobert Printf(
453*810390e3Srobert "mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
4543cab2bb3Spatrick "This is an unrecoverable problem, exiting now.\n",
455*810390e3Srobert (void *)addr);
4563cab2bb3Spatrick PrintZoneForPointer(addr, zone_ptr, zone_name);
4573cab2bb3Spatrick stack->Print();
4583cab2bb3Spatrick DescribeAddressIfHeap(addr);
4593cab2bb3Spatrick }
4603cab2bb3Spatrick
4613cab2bb3Spatrick // -------------- SuppressErrorReport -------------- {{{1
4623cab2bb3Spatrick // Avoid error reports duplicating for ASan recover mode.
SuppressErrorReport(uptr pc)4633cab2bb3Spatrick static bool SuppressErrorReport(uptr pc) {
4643cab2bb3Spatrick if (!common_flags()->suppress_equal_pcs) return false;
4653cab2bb3Spatrick for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) {
4663cab2bb3Spatrick uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]);
4673cab2bb3Spatrick if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp,
4683cab2bb3Spatrick pc, memory_order_relaxed))
4693cab2bb3Spatrick return false;
4703cab2bb3Spatrick if (cmp == pc) return true;
4713cab2bb3Spatrick }
4723cab2bb3Spatrick Die();
4733cab2bb3Spatrick }
4743cab2bb3Spatrick
ReportGenericError(uptr pc,uptr bp,uptr sp,uptr addr,bool is_write,uptr access_size,u32 exp,bool fatal)4753cab2bb3Spatrick void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
4763cab2bb3Spatrick uptr access_size, u32 exp, bool fatal) {
477*810390e3Srobert if (__asan_test_only_reported_buggy_pointer) {
478*810390e3Srobert *__asan_test_only_reported_buggy_pointer = addr;
479*810390e3Srobert return;
480*810390e3Srobert }
4813cab2bb3Spatrick if (!fatal && SuppressErrorReport(pc)) return;
4823cab2bb3Spatrick ENABLE_FRAME_POINTER;
4833cab2bb3Spatrick
4843cab2bb3Spatrick // Optimization experiments.
4853cab2bb3Spatrick // The experiments can be used to evaluate potential optimizations that remove
4863cab2bb3Spatrick // instrumentation (assess false negatives). Instead of completely removing
4873cab2bb3Spatrick // some instrumentation, compiler can emit special calls into runtime
4883cab2bb3Spatrick // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
4893cab2bb3Spatrick // mask of experiments (exp).
4903cab2bb3Spatrick // The reaction to a non-zero value of exp is to be defined.
4913cab2bb3Spatrick (void)exp;
4923cab2bb3Spatrick
4933cab2bb3Spatrick ScopedInErrorReport in_report(fatal);
4943cab2bb3Spatrick ErrorGeneric error(GetCurrentTidOrInvalid(), pc, bp, sp, addr, is_write,
4953cab2bb3Spatrick access_size);
4963cab2bb3Spatrick in_report.ReportError(error);
4973cab2bb3Spatrick }
4983cab2bb3Spatrick
4993cab2bb3Spatrick } // namespace __asan
5003cab2bb3Spatrick
5013cab2bb3Spatrick // --------------------------- Interface --------------------- {{{1
5023cab2bb3Spatrick using namespace __asan;
5033cab2bb3Spatrick
__asan_report_error(uptr pc,uptr bp,uptr sp,uptr addr,int is_write,uptr access_size,u32 exp)5043cab2bb3Spatrick void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
5053cab2bb3Spatrick uptr access_size, u32 exp) {
5063cab2bb3Spatrick ENABLE_FRAME_POINTER;
5073cab2bb3Spatrick bool fatal = flags()->halt_on_error;
5083cab2bb3Spatrick ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
5093cab2bb3Spatrick }
5103cab2bb3Spatrick
__asan_set_error_report_callback(void (* callback)(const char *))5113cab2bb3Spatrick void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
512*810390e3Srobert Lock l(&error_message_buf_mutex);
5133cab2bb3Spatrick error_report_callback = callback;
5143cab2bb3Spatrick }
5153cab2bb3Spatrick
__asan_describe_address(uptr addr)5163cab2bb3Spatrick void __asan_describe_address(uptr addr) {
5173cab2bb3Spatrick // Thread registry must be locked while we're describing an address.
5183cab2bb3Spatrick asanThreadRegistry().Lock();
5193cab2bb3Spatrick PrintAddressDescription(addr, 1, "");
5203cab2bb3Spatrick asanThreadRegistry().Unlock();
5213cab2bb3Spatrick }
5223cab2bb3Spatrick
__asan_report_present()5233cab2bb3Spatrick int __asan_report_present() {
5243cab2bb3Spatrick return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
5253cab2bb3Spatrick }
5263cab2bb3Spatrick
__asan_get_report_pc()5273cab2bb3Spatrick uptr __asan_get_report_pc() {
5283cab2bb3Spatrick if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
5293cab2bb3Spatrick return ScopedInErrorReport::CurrentError().Generic.pc;
5303cab2bb3Spatrick return 0;
5313cab2bb3Spatrick }
5323cab2bb3Spatrick
__asan_get_report_bp()5333cab2bb3Spatrick uptr __asan_get_report_bp() {
5343cab2bb3Spatrick if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
5353cab2bb3Spatrick return ScopedInErrorReport::CurrentError().Generic.bp;
5363cab2bb3Spatrick return 0;
5373cab2bb3Spatrick }
5383cab2bb3Spatrick
__asan_get_report_sp()5393cab2bb3Spatrick uptr __asan_get_report_sp() {
5403cab2bb3Spatrick if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
5413cab2bb3Spatrick return ScopedInErrorReport::CurrentError().Generic.sp;
5423cab2bb3Spatrick return 0;
5433cab2bb3Spatrick }
5443cab2bb3Spatrick
__asan_get_report_address()5453cab2bb3Spatrick uptr __asan_get_report_address() {
5463cab2bb3Spatrick ErrorDescription &err = ScopedInErrorReport::CurrentError();
5473cab2bb3Spatrick if (err.kind == kErrorKindGeneric)
5483cab2bb3Spatrick return err.Generic.addr_description.Address();
5493cab2bb3Spatrick else if (err.kind == kErrorKindDoubleFree)
5503cab2bb3Spatrick return err.DoubleFree.addr_description.addr;
5513cab2bb3Spatrick return 0;
5523cab2bb3Spatrick }
5533cab2bb3Spatrick
__asan_get_report_access_type()5543cab2bb3Spatrick int __asan_get_report_access_type() {
5553cab2bb3Spatrick if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
5563cab2bb3Spatrick return ScopedInErrorReport::CurrentError().Generic.is_write;
5573cab2bb3Spatrick return 0;
5583cab2bb3Spatrick }
5593cab2bb3Spatrick
__asan_get_report_access_size()5603cab2bb3Spatrick uptr __asan_get_report_access_size() {
5613cab2bb3Spatrick if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
5623cab2bb3Spatrick return ScopedInErrorReport::CurrentError().Generic.access_size;
5633cab2bb3Spatrick return 0;
5643cab2bb3Spatrick }
5653cab2bb3Spatrick
__asan_get_report_description()5663cab2bb3Spatrick const char *__asan_get_report_description() {
5673cab2bb3Spatrick if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
5683cab2bb3Spatrick return ScopedInErrorReport::CurrentError().Generic.bug_descr;
5693cab2bb3Spatrick return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
5703cab2bb3Spatrick }
5713cab2bb3Spatrick
5723cab2bb3Spatrick extern "C" {
5733cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__sanitizer_ptr_sub(void * a,void * b)5743cab2bb3Spatrick void __sanitizer_ptr_sub(void *a, void *b) {
5753cab2bb3Spatrick CheckForInvalidPointerPair(a, b);
5763cab2bb3Spatrick }
5773cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__sanitizer_ptr_cmp(void * a,void * b)5783cab2bb3Spatrick void __sanitizer_ptr_cmp(void *a, void *b) {
5793cab2bb3Spatrick CheckForInvalidPointerPair(a, b);
5803cab2bb3Spatrick }
5813cab2bb3Spatrick } // extern "C"
5823cab2bb3Spatrick
5833cab2bb3Spatrick // Provide default implementation of __asan_on_error that does nothing
5843cab2bb3Spatrick // and may be overriden by user.
SANITIZER_INTERFACE_WEAK_DEF(void,__asan_on_error,void)5853cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __asan_on_error, void) {}
586