diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h index 6060d6032228..900a3fc5c986 100644 --- a/compiler-rt/include/sanitizer/asan_interface.h +++ b/compiler-rt/include/sanitizer/asan_interface.h @@ -174,6 +174,56 @@ int SANITIZER_CDECL __asan_get_report_access_type(void); /// \returns Access size in bytes. size_t SANITIZER_CDECL __asan_get_report_access_size(void); +/// Gets the source address or address range involved in the current error +/// (e.g., memcpy source, or the address being read from). +/// +/// \param out_addr [out] Storage for the address. +/// \param out_size [out] Storage for the range size. +/// +/// \returns 1 if found, 0 otherwise. +int SANITIZER_CDECL __asan_get_report_src_address(const void **out_addr, + size_t *out_size); + +/// Gets the destination address or address range involved in the current error +/// (e.g., memcpy dest, or the address being written to). +/// +/// \param out_addr [out] Storage for the address. +/// \param out_size [out] Storage for the range size. +/// +/// \returns 1 if found, 0 otherwise. +int SANITIZER_CDECL __asan_get_report_dest_address(const void **out_addr, + size_t *out_size); + +/// Gets the address or address range being deallocated in the current error +/// (lifetime is terminated). +/// +/// \param out_addr [out] Storage for the address. +/// \param out_size [out] Storage for the range size. +/// +/// \returns 1 if found, 0 otherwise. +int SANITIZER_CDECL __asan_get_report_dealloc_address(const void **out_addr, + size_t *out_size); + +/// Gets the first non-dereferenced operand address involved in the current +/// error (e.g., pointer comparison or ODR violation). +/// +/// \param out_addr [out] Storage for the address. +/// \param out_size [out] Storage for the range size. Zero may be reported. +/// +/// \returns 1 if found, 0 otherwise. +int SANITIZER_CDECL __asan_get_report_first_address(const void **out_addr, + size_t *out_size); + +/// Gets the second non-dereferenced operand address involved in the current +/// error (e.g., pointer comparison or ODR violation). +/// +/// \param out_addr [out] Storage for the address. +/// \param out_size [out] Storage for the range size. Zero may be reported. +/// +/// \returns 1 if found, 0 otherwise. +int SANITIZER_CDECL __asan_get_report_second_address(const void **out_addr, + size_t *out_size); + /// Gets the bug description of an ASan error (useful for calling from a /// debugger). /// diff --git a/compiler-rt/lib/asan/asan_errors.h b/compiler-rt/lib/asan/asan_errors.h index 9c6843774f37..fedaaabcf803 100644 --- a/compiler-rt/lib/asan/asan_errors.h +++ b/compiler-rt/lib/asan/asan_errors.h @@ -298,16 +298,16 @@ struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase { const char *function; ErrorStringFunctionMemoryRangesOverlap() = default; // (*) - ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_, - uptr addr1, uptr length1_, uptr addr2, - uptr length2_, const char *function_) + ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace* stack, + uptr addr1, uptr length1, uptr addr2, + uptr length2, const char* function) : ErrorBase(tid), - stack(stack_), - length1(length1_), - length2(length2_), + stack(stack), + length1(length1), + length2(length2), addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false), addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false), - function(function_) { + function(function) { char bug_type[100]; internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); scariness.Clear(); @@ -320,14 +320,16 @@ struct ErrorStringFunctionSizeOverflow : ErrorBase { const BufferedStackTrace *stack; AddressDescription addr_description; uptr size; + bool is_write; ErrorStringFunctionSizeOverflow() = default; // (*) - ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_, - uptr addr, uptr size_) + ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace* stack, uptr addr, + uptr size, bool is_write) : ErrorBase(tid, 10, "negative-size-param"), - stack(stack_), + stack(stack), addr_description(addr, /*shouldLockThreadRegistry=*/false), - size(size_) {} + size(size), + is_write(is_write) {} void Print(); }; diff --git a/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h b/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h index ec988cff51c5..f7759caf68e2 100644 --- a/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h +++ b/compiler-rt/lib/asan/asan_interceptors_memintrinsics.h @@ -53,31 +53,31 @@ struct AsanInterceptorContext { // that no extra frames are created, and stack trace contains // relevant information only. // We check all shadow bytes. -#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) \ - do { \ - uptr __offset = (uptr)(offset); \ - uptr __size = (uptr)(size); \ - uptr __bad = 0; \ - if (UNLIKELY(__offset > __offset + __size)) { \ - GET_STACK_TRACE_FATAL_HERE; \ - ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ - } \ - if (UNLIKELY(!QuickCheckForUnpoisonedRegion(__offset, __size)) && \ - (__bad = __asan_region_is_poisoned(__offset, __size))) { \ - AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \ - bool suppressed = false; \ - if (_ctx) { \ - suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ - if (!suppressed && HaveStackTraceBasedSuppressions()) { \ - GET_STACK_TRACE_FATAL_HERE; \ - suppressed = IsStackTraceSuppressed(&stack); \ - } \ - } \ - if (!suppressed) { \ - GET_CURRENT_PC_BP_SP; \ - ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false); \ - } \ - } \ +#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) \ + do { \ + uptr __offset = (uptr)(offset); \ + uptr __size = (uptr)(size); \ + uptr __bad = 0; \ + if (UNLIKELY(__offset > __offset + __size)) { \ + GET_STACK_TRACE_FATAL_HERE; \ + ReportStringFunctionSizeOverflow(__offset, __size, isWrite, &stack); \ + } \ + if (UNLIKELY(!QuickCheckForUnpoisonedRegion(__offset, __size)) && \ + (__bad = __asan_region_is_poisoned(__offset, __size))) { \ + AsanInterceptorContext* _ctx = (AsanInterceptorContext*)ctx; \ + bool suppressed = false; \ + if (_ctx) { \ + suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \ + if (!suppressed && HaveStackTraceBasedSuppressions()) { \ + GET_STACK_TRACE_FATAL_HERE; \ + suppressed = IsStackTraceSuppressed(&stack); \ + } \ + } \ + if (!suppressed) { \ + GET_CURRENT_PC_BP_SP; \ + ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false); \ + } \ + } \ } while (0) #define ASAN_READ_RANGE(ctx, offset, size) \ diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc index b465356b1e44..f2aaedf293f3 100644 --- a/compiler-rt/lib/asan/asan_interface.inc +++ b/compiler-rt/lib/asan/asan_interface.inc @@ -33,6 +33,11 @@ INTERFACE_FUNCTION(__asan_get_free_stack) INTERFACE_FUNCTION(__asan_get_report_access_size) INTERFACE_FUNCTION(__asan_get_report_access_type) INTERFACE_FUNCTION(__asan_get_report_address) +INTERFACE_FUNCTION(__asan_get_report_src_address) +INTERFACE_FUNCTION(__asan_get_report_dest_address) +INTERFACE_FUNCTION(__asan_get_report_dealloc_address) +INTERFACE_FUNCTION(__asan_get_report_first_address) +INTERFACE_FUNCTION(__asan_get_report_second_address) INTERFACE_FUNCTION(__asan_get_report_bp) INTERFACE_FUNCTION(__asan_get_report_description) INTERFACE_FUNCTION(__asan_get_report_pc) diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h index a99826378022..c87802debfe3 100644 --- a/compiler-rt/lib/asan/asan_interface_internal.h +++ b/compiler-rt/lib/asan/asan_interface_internal.h @@ -157,6 +157,18 @@ extern "C" { int __asan_get_report_access_type(); SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_report_access_size(); + + SANITIZER_INTERFACE_ATTRIBUTE + int __asan_get_report_src_address(uptr* out_addr, uptr* out_size); + SANITIZER_INTERFACE_ATTRIBUTE + int __asan_get_report_dest_address(uptr* out_addr, uptr* out_size); + SANITIZER_INTERFACE_ATTRIBUTE + int __asan_get_report_dealloc_address(uptr* out_addr, uptr* out_size); + SANITIZER_INTERFACE_ATTRIBUTE + int __asan_get_report_first_address(uptr* out_addr, uptr* out_size); + SANITIZER_INTERFACE_ATTRIBUTE + int __asan_get_report_second_address(uptr* out_addr, uptr* out_size); + SANITIZER_INTERFACE_ATTRIBUTE const char * __asan_get_report_description(); diff --git a/compiler-rt/lib/asan/asan_report.cpp b/compiler-rt/lib/asan/asan_report.cpp index e50faf022321..c618d5411bda 100644 --- a/compiler-rt/lib/asan/asan_report.cpp +++ b/compiler-rt/lib/asan/asan_report.cpp @@ -374,11 +374,11 @@ void ReportStringFunctionMemoryRangesOverlap(const char *function, in_report.ReportError(error); } -void ReportStringFunctionSizeOverflow(uptr offset, uptr size, - BufferedStackTrace *stack) { +void ReportStringFunctionSizeOverflow(uptr offset, uptr size, bool is_write, + BufferedStackTrace* stack) { ScopedInErrorReport in_report; ErrorStringFunctionSizeOverflow error(GetCurrentTidOrInvalid(), stack, offset, - size); + size, is_write); in_report.ReportError(error); } @@ -610,6 +610,148 @@ uptr __asan_get_report_access_size() { return 0; } +int __asan_get_report_src_address(uptr* out_addr, uptr* out_size) { + ErrorDescription& err = ScopedInErrorReport::CurrentError(); + if (err.kind == kErrorKindGeneric && !err.Generic.is_write) { + if (out_addr) + *out_addr = err.Generic.addr_description.Address(); + if (out_size) + *out_size = err.Generic.access_size; + return 1; + } + if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) { + if (out_addr) + *out_addr = + err.StringFunctionMemoryRangesOverlap.addr2_description.Address(); + if (out_size) + *out_size = err.StringFunctionMemoryRangesOverlap.length2; + return 1; + } + if (err.kind == kErrorKindStringFunctionSizeOverflow && + !err.StringFunctionSizeOverflow.is_write) { + if (out_addr) + *out_addr = err.StringFunctionSizeOverflow.addr_description.Address(); + if (out_size) + *out_size = err.StringFunctionSizeOverflow.size; + return 1; + } + if (err.kind == kErrorKindMallocUsableSizeNotOwned) { + if (out_addr) + *out_addr = err.MallocUsableSizeNotOwned.addr_description.Address(); + if (out_size) + *out_size = 0; + return 1; + } + if (err.kind == kErrorKindSanitizerGetAllocatedSizeNotOwned) { + if (out_addr) + *out_addr = + err.SanitizerGetAllocatedSizeNotOwned.addr_description.Address(); + if (out_size) + *out_size = 0; + return 1; + } + return 0; +} + +int __asan_get_report_dest_address(uptr* out_addr, uptr* out_size) { + ErrorDescription& err = ScopedInErrorReport::CurrentError(); + if (err.kind == kErrorKindGeneric && err.Generic.is_write) { + if (out_addr) + *out_addr = err.Generic.addr_description.Address(); + if (out_size) + *out_size = err.Generic.access_size; + return 1; + } + if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) { + if (out_addr) + *out_addr = + err.StringFunctionMemoryRangesOverlap.addr1_description.Address(); + if (out_size) + *out_size = err.StringFunctionMemoryRangesOverlap.length1; + return 1; + } + if (err.kind == kErrorKindStringFunctionSizeOverflow && + err.StringFunctionSizeOverflow.is_write) { + if (out_addr) + *out_addr = err.StringFunctionSizeOverflow.addr_description.Address(); + if (out_size) + *out_size = err.StringFunctionSizeOverflow.size; + return 1; + } + return 0; +} + +int __asan_get_report_dealloc_address(uptr* out_addr, uptr* out_size) { + ErrorDescription& err = ScopedInErrorReport::CurrentError(); + if (err.kind == kErrorKindDoubleFree) { + if (out_addr) + *out_addr = err.DoubleFree.addr_description.addr; + if (out_size) + *out_size = 0; + return 1; + } + if (err.kind == kErrorKindNewDeleteTypeMismatch) { + if (out_addr) + *out_addr = err.NewDeleteTypeMismatch.addr_description.addr; + if (out_size) + *out_size = err.NewDeleteTypeMismatch.delete_size; + return 1; + } + if (err.kind == kErrorKindFreeNotMalloced) { + if (out_addr) + *out_addr = err.FreeNotMalloced.addr_description.Address(); + if (out_size) + *out_size = 0; + return 1; + } + if (err.kind == kErrorKindAllocTypeMismatch) { + if (out_addr) + *out_addr = err.AllocTypeMismatch.addr_description.Address(); + if (out_size) + *out_size = 0; + return 1; + } + return 0; +} + +int __asan_get_report_first_address(uptr* out_addr, uptr* out_size) { + ErrorDescription& err = ScopedInErrorReport::CurrentError(); + if (err.kind == kErrorKindInvalidPointerPair) { + if (out_addr) + *out_addr = err.InvalidPointerPair.addr1_description.Address(); + if (out_size) + *out_size = 0; + return 1; + } + if (err.kind == kErrorKindODRViolation) { + if (out_addr) + *out_addr = err.ODRViolation.global1.beg; + if (out_size) + *out_size = 0; + return 1; + } + return 0; +} + +int __asan_get_report_second_address(uptr* out_addr, uptr* out_size) { + ErrorDescription& err = ScopedInErrorReport::CurrentError(); + if (err.kind == kErrorKindInvalidPointerPair) { + if (out_addr) + *out_addr = err.InvalidPointerPair.addr2_description.Address(); + if (out_size) + *out_size = 0; + return 1; + } + if (err.kind == kErrorKindODRViolation) { + if (out_addr) + *out_addr = err.ODRViolation.global2.beg; + if (out_size) + *out_size = 0; + return 1; + } + return 0; +} + const char *__asan_get_report_description() { if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric) return ScopedInErrorReport::CurrentError().Generic.bug_descr; diff --git a/compiler-rt/lib/asan/asan_report.h b/compiler-rt/lib/asan/asan_report.h index b181849b10f9..b83057bdf821 100644 --- a/compiler-rt/lib/asan/asan_report.h +++ b/compiler-rt/lib/asan/asan_report.h @@ -81,8 +81,8 @@ void ReportStringFunctionMemoryRangesOverlap(const char *function, const char *offset1, uptr length1, const char *offset2, uptr length2, BufferedStackTrace *stack); -void ReportStringFunctionSizeOverflow(uptr offset, uptr size, - BufferedStackTrace *stack); +void ReportStringFunctionSizeOverflow(uptr offset, uptr size, bool is_write, + BufferedStackTrace* stack); void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid, uptr new_mid, BufferedStackTrace *stack); diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp index c1cc383b3c1e..cd7248167c73 100644 --- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp +++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp @@ -50,6 +50,15 @@ __asan_on_error() { // CHECK: addr: {{0x0*}}[[ADDR]] fprintf(stderr, "description: %s\n", description); // CHECK: description: double-free + + const void *addr_dealloc = NULL; + size_t size_dealloc = 0xbad; + int is_dealloc = + __asan_get_report_dealloc_address(&addr_dealloc, &size_dealloc); + fprintf(stderr, + "is_dealloc: %d, addr_dealloc: " PTR_FMT ", size_dealloc: %zu\n", + is_dealloc, addr_dealloc, size_dealloc); + // CHECK: is_dealloc: 1, addr_dealloc: 0x[[ADDR]], size_dealloc: 0 } // CHECK: AddressSanitizer: attempting double-free on {{0x0*}}[[ADDR]] in thread T0 diff --git a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp new file mode 100644 index 000000000000..7d45b5af99b7 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp @@ -0,0 +1,71 @@ +// Checks that the ASan debugging API for getting report information +// returns correct values for invalid pointer pairs. +// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair && %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +// If we use %p with MS CRTs, it comes out all upper case. Use %08x to get +// lowercase hex. +#ifdef _WIN32 +# ifdef _WIN64 +# define PTR_FMT "0x%08llx" +# else +# define PTR_FMT "0x%08x" +# endif +// Solaris libc omits the leading 0x. +#elif defined(__sun__) && defined(__svr4__) +# define PTR_FMT "0x%p" +#else +# define PTR_FMT "%p" +#endif + +char *p; +char *q; + +int main() { + // Disable stderr buffering. Needed on Windows. + setvbuf(stderr, NULL, _IONBF, 0); + + p = (char *)malloc(42); + q = (char *)malloc(42); + + fprintf(stderr, "p: " PTR_FMT "\n", p); + // CHECK: p: 0x[[ADDR1:[0-9a-f]+]] + fprintf(stderr, "q: " PTR_FMT "\n", q); + // CHECK: q: 0x[[ADDR2:[0-9a-f]+]] + + // Trigger invalid pointer pair + int res = p > q; // BOOM + + free(p); + free(q); + return res; +} + +// Required for dyld macOS 12.0+ +#if (__APPLE__) +__attribute__((weak)) +#endif +extern "C" void __asan_on_error() { + int present = __asan_report_present(); + fprintf(stderr, "%s\n", (present == 1) ? "report" : ""); + // CHECK: report + + const void *addr_first = NULL; + size_t size_first = 0xbad; + int is_first = __asan_get_report_first_address(&addr_first, &size_first); + fprintf(stderr, "is_first: %d, addr_first: " PTR_FMT ", size_first: %zu\n", + is_first, addr_first, size_first); + // CHECK: is_first: 1, addr_first: 0x[[ADDR1]], size_first: 0 + + const void *addr_second = NULL; + size_t size_second = 0xbad; + int is_second = __asan_get_report_second_address(&addr_second, &size_second); + fprintf(stderr, "is_second: %d, addr_second: " PTR_FMT ", size_second: %zu\n", + is_second, addr_second, size_second); + // CHECK: is_second: 1, addr_second: 0x[[ADDR2]], size_second: 0 +} + +// CHECK: ERROR: AddressSanitizer: invalid-pointer-pair diff --git a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp new file mode 100644 index 000000000000..aa2915c28c85 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp @@ -0,0 +1,59 @@ +// Checks that the ASan debugging API for getting report information reports +// memory overlap error details. +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +char buffer[10] = "hello"; + +int main() { + // Disable stderr buffering. Needed on Windows. + setvbuf(stderr, NULL, _IONBF, 0); + + // Trigger memcpy-param-overlap + memcpy(buffer, buffer + 1, 3); // BOOM + return 0; +} + +// If we use %p with MS CRTs, it comes out all upper case. Use %08x to get +// lowercase hex. +#ifdef _WIN32 +# ifdef _WIN64 +# define PTR_FMT "0x%08llx" +# else +# define PTR_FMT "0x%08x" +# endif +// Solaris libc omits the leading 0x. +#elif defined(__sun__) && defined(__svr4__) +# define PTR_FMT "0x%p" +#else +# define PTR_FMT "%p" +#endif + +// Required for dyld macOS 12.0+ +#if (__APPLE__) +__attribute__((weak)) +#endif +extern "C" void __asan_on_error() { + int present = __asan_report_present(); + fprintf(stderr, "%s\n", (present == 1) ? "report" : ""); + // CHECK: report + + const void *addr_src = NULL; + size_t size_src = 0; + int is_src = __asan_get_report_src_address(&addr_src, &size_src); + fprintf(stderr, "is_src: %d, addr_src: " PTR_FMT ", size_src: %zu\n", is_src, + addr_src, size_src); + // CHECK: is_src: 1, addr_src: 0x{{[0-9a-f]+}}, size_src: 3 + + const void *addr_dest = NULL; + size_t size_dest = 0; + int is_dest = __asan_get_report_dest_address(&addr_dest, &size_dest); + fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT ", size_dest: %zu\n", + is_dest, addr_dest, size_dest); + // CHECK: is_dest: 1, addr_dest: 0x{{[0-9a-f]+}}, size_dest: 3 +} + +// CHECK: memcpy-param-overlap diff --git a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp new file mode 100644 index 000000000000..60b03d087d95 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp @@ -0,0 +1,60 @@ +// Checks that the ASan debugging API for getting report information +// returns correct values for negative size parameter errors. +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +char buffer[10] = "hello"; + +int main() { + // Disable stderr buffering. Needed on Windows. + setvbuf(stderr, NULL, _IONBF, 0); + + // Trigger negative-size-param + memset(buffer, 0, (size_t)-1); // BOOM + return 0; +} + +// If we use %p with MS CRTs, it comes out all upper case. Use %08x to get +// lowercase hex. +#ifdef _WIN32 +# ifdef _WIN64 +# define PTR_FMT "0x%08llx" +# else +# define PTR_FMT "0x%08x" +# endif +// Solaris libc omits the leading 0x. +#elif defined(__sun__) && defined(__svr4__) +# define PTR_FMT "0x%p" +#else +# define PTR_FMT "%p" +#endif + +// Required for dyld macOS 12.0+ +#if (__APPLE__) +__attribute__((weak)) +#endif +extern "C" void __asan_on_error() { + int present = __asan_report_present(); + fprintf(stderr, "%s\n", (present == 1) ? "report" : ""); + // CHECK: report + + const void *addr_src = NULL; + size_t size_src = 0; + int is_src = __asan_get_report_src_address(&addr_src, &size_src); + fprintf(stderr, "is_src: %d\n", is_src); + // CHECK: is_src: 0 + + const void *addr_dest = NULL; + size_t size_dest = 0; + int is_dest = __asan_get_report_dest_address(&addr_dest, &size_dest); + // We check size_dest + 1 because size_dest is -1 (as size_t), which varies + // depending on the platform's size_t. Adding 1 should result in 0. + fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT ", size_dest+1: %zu\n", + is_dest, addr_dest, size_dest + 1); + // CHECK: is_dest: 1, addr_dest: 0x{{[0-9a-f]+}}, size_dest+1: 0 +} + +// CHECK: AddressSanitizer: negative-size-param diff --git a/compiler-rt/test/asan/TestCases/debug_report.cpp b/compiler-rt/test/asan/TestCases/debug_report.cpp index 0dbb9f2fb998..f6038693873e 100644 --- a/compiler-rt/test/asan/TestCases/debug_report.cpp +++ b/compiler-rt/test/asan/TestCases/debug_report.cpp @@ -61,10 +61,21 @@ __asan_on_error() { // CHECK: addr: 0x[[ADDR:[0-9a-f]+]] fprintf(stderr, "type: %s\n", (is_write ? "write" : "read")); // CHECK: type: write - fprintf(stderr, "access_size: %ld\n", access_size); + fprintf(stderr, "access_size: %zu\n", access_size); // CHECK: access_size: 1 fprintf(stderr, "description: %s\n", description); // CHECK: description: heap-use-after-free + + const void *addr2 = NULL; + size_t size2 = 0; + int is_dest = __asan_get_report_dest_address(&addr2, &size2); + fprintf(stderr, "is_dest: %d, addr2: " PTR_FMT ", size2: %zu\n", is_dest, + addr2, size2); + // CHECK: is_dest: 1, addr2: 0x[[ADDR]], size2: 1 + + int is_src = __asan_get_report_src_address(&addr2, &size2); + fprintf(stderr, "is_src: %d\n", is_src); + // CHECK: is_src: 0 } // CHECK: AddressSanitizer: heap-use-after-free on address {{0x0*}}[[ADDR]] at pc {{0x0*}}[[PC]] bp {{0x0*}}[[BP]] sp {{0x0*}}[[SP]]