[compiler-rt] [asan] API for getting multiple pointer ranges (PR #181446)

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 23 19:10:20 PDT 2026


https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/181446

>From 4c21a9ec78a457313c31918d5703e926aff3d9fc Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Fri, 13 Feb 2026 20:36:54 +0100
Subject: [PATCH 01/12] [asan] API for getting multiple pointer ranges

Add an API that, unlike __asan_get_report_address(), can return multiple
addresses and sizes. E.g., a handler might be interested in inspecting
the source and the destination ranges of a memcpy-param-overlap error.
---
 .../include/sanitizer/asan_interface.h        |  24 ++++
 compiler-rt/lib/asan/asan_errors.h            |   8 +-
 .../asan/asan_interceptors_memintrinsics.h    |  50 ++++----
 .../lib/asan/asan_interface_internal.h        |  12 ++
 compiler-rt/lib/asan/asan_report.cpp          | 108 +++++++++++++++++-
 compiler-rt/lib/asan/asan_report.h            |   4 +-
 6 files changed, 173 insertions(+), 33 deletions(-)

diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 544f2e4b32687..5de4ea1ca5794 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -174,6 +174,30 @@ int SANITIZER_CDECL __asan_get_report_access_type(void);
 /// \returns Access size in bytes.
 size_t SANITIZER_CDECL __asan_get_report_access_size(void);
 
+typedef enum {
+  // Source address (e.g. memcpy source, or the address being read from).
+  __asan_address_info_src = 1,
+  // Destination address (e.g. memcpy dest, or the address being written to).
+  __asan_address_info_dest = 2,
+  // Address being deallocated (lifetime is terminated).
+  __asan_address_info_dealloc = 3,
+  // First non-dereferenced operand (e.g. pointer comparison, ODR definition).
+  __asan_address_info_first = 4,
+  // Second non-dereferenced operand (e.g. pointer comparison, ODR definition).
+  __asan_address_info_second = 5,
+} __asan_address_info_type;
+
+/// Gets a specific address or address range involved in the current error.
+///
+/// \param type __asan_address_info_type which the info is requested for.
+/// \param out_addr [out] Storage for the address.
+/// \param out_size [out] Storage for the range size. Zero may be reported
+/// (e.g., for pointer comparison errors as no dereferencing occurs).
+///
+/// \returns 1 if found, 0 otherwise.
+int SANITIZER_CDECL __asan_get_report_address_info(int type, 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 f339b35d2a764..06ec69f0f4547 100644
--- a/compiler-rt/lib/asan/asan_errors.h
+++ b/compiler-rt/lib/asan/asan_errors.h
@@ -301,14 +301,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_),
         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 ec988cff51c59..f7759caf68e2c 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_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h
index a998263780221..ab09c5028f587 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();
+
+  typedef enum {
+    __asan_address_info_src = 1,
+    __asan_address_info_dest = 2,
+    __asan_address_info_dealloc = 3,
+    __asan_address_info_first = 4,
+    __asan_address_info_second = 5,
+  } __asan_address_info_type;
+
+  SANITIZER_INTERFACE_ATTRIBUTE
+  int __asan_get_report_address_info(int type, 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 e049a21e4e16d..e19626934e272 100644
--- a/compiler-rt/lib/asan/asan_report.cpp
+++ b/compiler-rt/lib/asan/asan_report.cpp
@@ -366,11 +366,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);
 }
 
@@ -602,6 +602,108 @@ uptr __asan_get_report_access_size() {
   return 0;
 }
 
+int __asan_get_report_address_info(int type, uptr* out_addr, uptr* out_size) {
+  ErrorDescription& err = ScopedInErrorReport::CurrentError();
+  switch (type) {
+    case __asan_address_info_src:
+      if (err.kind == kErrorKindGeneric && !err.Generic.is_write) {
+        *out_addr = err.Generic.addr_description.Address();
+        *out_size = err.Generic.access_size;
+        return 1;
+      }
+      if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
+        *out_addr =
+            err.StringFunctionMemoryRangesOverlap.addr2_description.Address();
+        *out_size = err.StringFunctionMemoryRangesOverlap.length2;
+        return 1;
+      }
+      if (err.kind == kErrorKindStringFunctionSizeOverflow &&
+          !err.StringFunctionSizeOverflow.is_write) {
+        *out_addr = err.StringFunctionSizeOverflow.addr_description.Address();
+        *out_size = err.StringFunctionSizeOverflow.size;
+        return 1;
+      }
+      if (err.kind == kErrorKindMallocUsableSizeNotOwned) {
+        *out_addr = err.MallocUsableSizeNotOwned.addr_description.Address();
+        *out_size = 0;
+        return 1;
+      }
+      if (err.kind == kErrorKindSanitizerGetAllocatedSizeNotOwned) {
+        *out_addr =
+            err.SanitizerGetAllocatedSizeNotOwned.addr_description.Address();
+        *out_size = 0;
+        return 1;
+      }
+      break;
+    case __asan_address_info_dest:
+      if (err.kind == kErrorKindGeneric && err.Generic.is_write) {
+        *out_addr = err.Generic.addr_description.Address();
+        *out_size = err.Generic.access_size;
+        return 1;
+      }
+      if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
+        *out_addr =
+            err.StringFunctionMemoryRangesOverlap.addr1_description.Address();
+        *out_size = err.StringFunctionMemoryRangesOverlap.length1;
+        return 1;
+      }
+      if (err.kind == kErrorKindStringFunctionSizeOverflow &&
+          err.StringFunctionSizeOverflow.is_write) {
+        *out_addr = err.StringFunctionSizeOverflow.addr_description.Address();
+        *out_size = err.StringFunctionSizeOverflow.size;
+        return 1;
+      }
+      break;
+    case __asan_address_info_dealloc:
+      if (err.kind == kErrorKindDoubleFree) {
+        *out_addr = err.DoubleFree.addr_description.addr;
+        *out_size = 0;
+        return 1;
+      }
+      if (err.kind == kErrorKindNewDeleteTypeMismatch) {
+        *out_addr = err.NewDeleteTypeMismatch.addr_description.addr;
+        *out_size = err.NewDeleteTypeMismatch.delete_size;
+        return 1;
+      }
+      if (err.kind == kErrorKindFreeNotMalloced) {
+        *out_addr = err.FreeNotMalloced.addr_description.Address();
+        *out_size = 0;
+        return 1;
+      }
+      if (err.kind == kErrorKindAllocTypeMismatch) {
+        *out_addr = err.AllocTypeMismatch.addr_description.Address();
+        *out_size = 0;
+        return 1;
+      }
+      break;
+    case __asan_address_info_first:
+      if (err.kind == kErrorKindInvalidPointerPair) {
+        *out_addr = err.InvalidPointerPair.addr1_description.Address();
+        *out_size = 0;
+        return 1;
+      }
+      if (err.kind == kErrorKindODRViolation) {
+        *out_addr = err.ODRViolation.global1.beg;
+        *out_size = 0;
+        return 1;
+      }
+      break;
+    case __asan_address_info_second:
+      if (err.kind == kErrorKindInvalidPointerPair) {
+        *out_addr = err.InvalidPointerPair.addr2_description.Address();
+        *out_size = 0;
+        return 1;
+      }
+      if (err.kind == kErrorKindODRViolation) {
+        *out_addr = err.ODRViolation.global2.beg;
+        *out_size = 0;
+        return 1;
+      }
+      break;
+  }
+  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 3143d83abe390..b6c2b3eae7c70 100644
--- a/compiler-rt/lib/asan/asan_report.h
+++ b/compiler-rt/lib/asan/asan_report.h
@@ -79,8 +79,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);

>From 379055a29067e979bacb33a1c044e99bcf91d7fe Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Sat, 14 Feb 2026 03:44:14 +0100
Subject: [PATCH 02/12] update interface.inc

---
 compiler-rt/lib/asan/asan_interface.inc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc
index b465356b1e443..7cbc4e636b5ab 100644
--- a/compiler-rt/lib/asan/asan_interface.inc
+++ b/compiler-rt/lib/asan/asan_interface.inc
@@ -33,6 +33,7 @@ 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_address_info)
 INTERFACE_FUNCTION(__asan_get_report_bp)
 INTERFACE_FUNCTION(__asan_get_report_description)
 INTERFACE_FUNCTION(__asan_get_report_pc)

>From da2057867403b0b9089d3614b3c27b9a150106ed Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Mon, 16 Feb 2026 19:57:30 +0100
Subject: [PATCH 03/12] comment wording

---
 compiler-rt/include/sanitizer/asan_interface.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 5de4ea1ca5794..739781f00f6b9 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -181,9 +181,9 @@ typedef enum {
   __asan_address_info_dest = 2,
   // Address being deallocated (lifetime is terminated).
   __asan_address_info_dealloc = 3,
-  // First non-dereferenced operand (e.g. pointer comparison, ODR definition).
+  // First non-dereferenced operand (e.g. pointer comparison, ODR violation).
   __asan_address_info_first = 4,
-  // Second non-dereferenced operand (e.g. pointer comparison, ODR definition).
+  // Second non-dereferenced operand (e.g. pointer comparison, ODR violation).
   __asan_address_info_second = 5,
 } __asan_address_info_type;
 

>From 85fe104f74aa84f897516102cc649185e1630501 Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Tue, 14 Apr 2026 15:35:44 +0200
Subject: [PATCH 04/12] tests, polish

---
 .../include/sanitizer/asan_interface.h        |  1 +
 compiler-rt/lib/asan/asan_errors.h            | 14 ++---
 .../test/asan/TestCases/debug_double_free.cpp |  6 ++
 .../TestCases/debug_invalid_pointer_pair.cpp  | 55 +++++++++++++++++
 .../asan/TestCases/debug_memcpy_overlap.cpp   | 58 ++++++++++++++++++
 .../asan/TestCases/debug_negative_size.cpp    | 60 +++++++++++++++++++
 .../test/asan/TestCases/debug_report.cpp      | 10 ++++
 7 files changed, 197 insertions(+), 7 deletions(-)
 create mode 100644 compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
 create mode 100644 compiler-rt/test/asan/TestCases/debug_negative_size.cpp

diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 739781f00f6b9..777e0ccb54e3c 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -175,6 +175,7 @@ int SANITIZER_CDECL __asan_get_report_access_type(void);
 size_t SANITIZER_CDECL __asan_get_report_access_size(void);
 
 typedef enum {
+  __asan_address_info_none = 0,
   // Source address (e.g. memcpy source, or the address being read from).
   __asan_address_info_src = 1,
   // Destination address (e.g. memcpy dest, or the address being written to).
diff --git a/compiler-rt/lib/asan/asan_errors.h b/compiler-rt/lib/asan/asan_errors.h
index 06ec69f0f4547..607e332b93d47 100644
--- a/compiler-rt/lib/asan/asan_errors.h
+++ b/compiler-rt/lib/asan/asan_errors.h
@@ -279,16 +279,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();
diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
index c1cc383b3c1e3..59f988aff89d1 100644
--- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
@@ -50,6 +50,12 @@ __asan_on_error() {
   // CHECK: addr: {{0x0*}}[[ADDR]]
   fprintf(stderr, "description: %s\n", description);
   // CHECK: description: double-free
+
+  void *addr_dealloc = NULL;
+  size_t size_dealloc = 0;
+  int is_dealloc = __asan_get_report_address_info(__asan_address_info_dealloc, &addr_dealloc, &size_dealloc);
+  fprintf(stderr, "is_dealloc: %d, addr_dealloc: " PTR_FMT ", size_dealloc: %ld\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 0000000000000..9c2b67af768e0
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
@@ -0,0 +1,55 @@
+// 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 <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+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: %p\n", p);
+  // CHECK: p: 0x[[ADDR1:[0-9a-f]+]]
+  fprintf(stderr, "q: %p\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
+
+  void *addr_first = NULL;
+  size_t size_first = 0;
+  int is_first = __asan_get_report_address_info(__asan_address_info_first, &addr_first, &size_first);
+  fprintf(stderr, "is_first: %d, addr_first: %p, size_first: %ld\n", is_first, addr_first, size_first);
+  // CHECK: is_first: 1, addr_first: 0x[[ADDR1]], size_first: 0
+
+  void *addr_second = NULL;
+  size_t size_second = 0;
+  int is_second = __asan_get_report_address_info(__asan_address_info_second, &addr_second, &size_second);
+  fprintf(stderr, "is_second: %d, addr_second: %p, size_second: %ld\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 0000000000000..d57cdc3b7fa1c
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
@@ -0,0 +1,58 @@
+// 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 <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <string.h>
+
+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
+
+  void *addr_src = NULL;
+  size_t size_src = 0;
+  int is_src = __asan_get_report_address_info(__asan_address_info_src, &addr_src, &size_src);
+  fprintf(stderr, "is_src: %d, addr_src: " PTR_FMT ", size_src: %ld\n", is_src, addr_src, size_src);
+  // CHECK: is_src: 1, addr_src: 0x{{[0-9a-f]+}}, size_src: 3
+
+  void *addr_dest = NULL;
+  size_t size_dest = 0;
+  int is_dest = __asan_get_report_address_info(__asan_address_info_dest, &addr_dest, &size_dest);
+  fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT ", size_dest: %ld\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 0000000000000..396ea7311cf71
--- /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 <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <string.h>
+
+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
+
+  void *addr_src = NULL;
+  size_t size_src = 0;
+  int is_src = __asan_get_report_address_info(__asan_address_info_src, &addr_src, &size_src);
+  fprintf(stderr, "is_src: %d\n", is_src);
+  // CHECK: is_src: 0
+
+  void *addr_dest = NULL;
+  size_t size_dest = 0;
+  int is_dest = __asan_get_report_address_info(__asan_address_info_dest, &addr_dest, &size_dest);
+  // Do not format the size_dest because it is a very large number (-1 as size_t) and might be printed differently
+  // depending on the platform's size_t. We just check it's populated.
+  fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT "\n", is_dest, addr_dest);
+  // CHECK: is_dest: 1, addr_dest: 0x{{[0-9a-f]+}}
+}
+
+// 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 0dbb9f2fb9988..9c5f5032835af 100644
--- a/compiler-rt/test/asan/TestCases/debug_report.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_report.cpp
@@ -65,6 +65,16 @@ __asan_on_error() {
   // CHECK: access_size: 1
   fprintf(stderr, "description: %s\n", description);
   // CHECK: description: heap-use-after-free
+
+  void *addr2 = NULL;
+  size_t size2 = 0;
+  int is_dest = __asan_get_report_address_info(__asan_address_info_dest, &addr2, &size2);
+  fprintf(stderr, "is_dest: %d, addr2: " PTR_FMT ", size2: %ld\n", is_dest, addr2, size2);
+  // CHECK: is_dest: 1, addr2: 0x[[ADDR]], size2: 1
+
+  int is_none = __asan_get_report_address_info(__asan_address_info_none, &addr2, &size2);
+  fprintf(stderr, "is_none: %d\n", is_none);
+  // CHECK: is_none: 0
 }
 
 // CHECK: AddressSanitizer: heap-use-after-free on address {{0x0*}}[[ADDR]] at pc {{0x0*}}[[PC]] bp {{0x0*}}[[BP]] sp {{0x0*}}[[SP]]

>From d4dcf919f8848233ab16adf9ec7a5f0c8ae38a00 Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Tue, 14 Apr 2026 20:51:24 +0200
Subject: [PATCH 05/12] reformat; fix win test

---
 compiler-rt/lib/asan/asan_errors.h            |  4 +--
 .../test/asan/TestCases/debug_double_free.cpp |  7 ++--
 .../TestCases/debug_invalid_pointer_pair.cpp  | 34 ++++++++++++++-----
 .../asan/TestCases/debug_memcpy_overlap.cpp   | 29 +++++++++-------
 .../asan/TestCases/debug_negative_size.cpp    | 23 +++++++------
 .../test/asan/TestCases/debug_report.cpp      | 11 +++---
 6 files changed, 68 insertions(+), 40 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_errors.h b/compiler-rt/lib/asan/asan_errors.h
index 607e332b93d47..d821c3856d532 100644
--- a/compiler-rt/lib/asan/asan_errors.h
+++ b/compiler-rt/lib/asan/asan_errors.h
@@ -279,9 +279,9 @@ struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
   const char *function;
 
   ErrorStringFunctionMemoryRangesOverlap() = default;  // (*)
-  ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack,
+  ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace* stack,
                                          uptr addr1, uptr length1, uptr addr2,
-                                         uptr length2, const char *function)
+                                         uptr length2, const char* function)
       : ErrorBase(tid),
         stack(stack),
         length1(length1),
diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
index 59f988aff89d1..cfd67eebf13c4 100644
--- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
@@ -53,8 +53,11 @@ __asan_on_error() {
 
   void *addr_dealloc = NULL;
   size_t size_dealloc = 0;
-  int is_dealloc = __asan_get_report_address_info(__asan_address_info_dealloc, &addr_dealloc, &size_dealloc);
-  fprintf(stderr, "is_dealloc: %d, addr_dealloc: " PTR_FMT ", size_dealloc: %ld\n", is_dealloc, addr_dealloc, size_dealloc);
+  int is_dealloc = __asan_get_report_address_info(__asan_address_info_dealloc,
+                                                  &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
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
index 9c2b67af768e0..2a299f92cceae 100644
--- a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
@@ -6,6 +6,21 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+// 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;
 
@@ -16,9 +31,9 @@ int main() {
   p = (char *)malloc(42);
   q = (char *)malloc(42);
 
-  fprintf(stderr, "p: %p\n", p);
+  fprintf(stderr, "p: " PTR_FMT "\n", p);
   // CHECK: p: 0x[[ADDR1:[0-9a-f]+]]
-  fprintf(stderr, "q: %p\n", q);
+  fprintf(stderr, "q: " PTR_FMT "\n", q);
   // CHECK: q: 0x[[ADDR2:[0-9a-f]+]]
 
   // Trigger invalid pointer pair
@@ -33,22 +48,25 @@ int main() {
 #if (__APPLE__)
 __attribute__((weak))
 #endif
-extern "C" void
-__asan_on_error() {
+extern "C" void __asan_on_error() {
   int present = __asan_report_present();
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
   void *addr_first = NULL;
   size_t size_first = 0;
-  int is_first = __asan_get_report_address_info(__asan_address_info_first, &addr_first, &size_first);
-  fprintf(stderr, "is_first: %d, addr_first: %p, size_first: %ld\n", is_first, addr_first, size_first);
+  int is_first = __asan_get_report_address_info(__asan_address_info_first,
+                                                &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
 
   void *addr_second = NULL;
   size_t size_second = 0;
-  int is_second = __asan_get_report_address_info(__asan_address_info_second, &addr_second, &size_second);
-  fprintf(stderr, "is_second: %d, addr_second: %p, size_second: %ld\n", is_second, addr_second, size_second);
+  int is_second = __asan_get_report_address_info(__asan_address_info_second,
+                                                 &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
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
index d57cdc3b7fa1c..276a91549c8c0 100644
--- a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
@@ -20,38 +20,41 @@ int main() {
 // 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
+#  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"
+#  define PTR_FMT "0x%p"
 #else
-# define PTR_FMT "%p"
+#  define PTR_FMT "%p"
 #endif
 
 // Required for dyld macOS 12.0+
 #if (__APPLE__)
 __attribute__((weak))
 #endif
-extern "C" void
-__asan_on_error() {
+extern "C" void __asan_on_error() {
   int present = __asan_report_present();
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
   void *addr_src = NULL;
   size_t size_src = 0;
-  int is_src = __asan_get_report_address_info(__asan_address_info_src, &addr_src, &size_src);
-  fprintf(stderr, "is_src: %d, addr_src: " PTR_FMT ", size_src: %ld\n", is_src, addr_src, size_src);
+  int is_src = __asan_get_report_address_info(__asan_address_info_src,
+                                              &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
 
   void *addr_dest = NULL;
   size_t size_dest = 0;
-  int is_dest = __asan_get_report_address_info(__asan_address_info_dest, &addr_dest, &size_dest);
-  fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT ", size_dest: %ld\n", is_dest, addr_dest, size_dest);
+  int is_dest = __asan_get_report_address_info(__asan_address_info_dest,
+                                               &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
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
index 396ea7311cf71..ca1dc8a97c020 100644
--- a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
@@ -20,37 +20,38 @@ int main() {
 // 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
+#  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"
+#  define PTR_FMT "0x%p"
 #else
-# define PTR_FMT "%p"
+#  define PTR_FMT "%p"
 #endif
 
 // Required for dyld macOS 12.0+
 #if (__APPLE__)
 __attribute__((weak))
 #endif
-extern "C" void
-__asan_on_error() {
+extern "C" void __asan_on_error() {
   int present = __asan_report_present();
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
   void *addr_src = NULL;
   size_t size_src = 0;
-  int is_src = __asan_get_report_address_info(__asan_address_info_src, &addr_src, &size_src);
+  int is_src = __asan_get_report_address_info(__asan_address_info_src,
+                                              &addr_src, &size_src);
   fprintf(stderr, "is_src: %d\n", is_src);
   // CHECK: is_src: 0
 
   void *addr_dest = NULL;
   size_t size_dest = 0;
-  int is_dest = __asan_get_report_address_info(__asan_address_info_dest, &addr_dest, &size_dest);
+  int is_dest = __asan_get_report_address_info(__asan_address_info_dest,
+                                               &addr_dest, &size_dest);
   // Do not format the size_dest because it is a very large number (-1 as size_t) and might be printed differently
   // depending on the platform's size_t. We just check it's populated.
   fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT "\n", is_dest, addr_dest);
diff --git a/compiler-rt/test/asan/TestCases/debug_report.cpp b/compiler-rt/test/asan/TestCases/debug_report.cpp
index 9c5f5032835af..06ef4d565098f 100644
--- a/compiler-rt/test/asan/TestCases/debug_report.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_report.cpp
@@ -61,18 +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
 
   void *addr2 = NULL;
   size_t size2 = 0;
-  int is_dest = __asan_get_report_address_info(__asan_address_info_dest, &addr2, &size2);
-  fprintf(stderr, "is_dest: %d, addr2: " PTR_FMT ", size2: %ld\n", is_dest, addr2, size2);
+  int is_dest =
+      __asan_get_report_address_info(__asan_address_info_dest, &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_none = __asan_get_report_address_info(__asan_address_info_none, &addr2, &size2);
+  int is_none =
+      __asan_get_report_address_info(__asan_address_info_none, &addr2, &size2);
   fprintf(stderr, "is_none: %d\n", is_none);
   // CHECK: is_none: 0
 }

>From 476b715fcae5493adb5c0d9d4d9a291e96dc159e Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Tue, 14 Apr 2026 23:11:11 +0200
Subject: [PATCH 06/12] polish

---
 compiler-rt/lib/asan/asan_errors.h                     | 10 +++++-----
 compiler-rt/lib/asan/asan_interface_internal.h         |  1 +
 .../test/asan/TestCases/debug_negative_size.cpp        |  9 +++++----
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_errors.h b/compiler-rt/lib/asan/asan_errors.h
index d821c3856d532..a9625c1477adf 100644
--- a/compiler-rt/lib/asan/asan_errors.h
+++ b/compiler-rt/lib/asan/asan_errors.h
@@ -304,13 +304,13 @@ struct ErrorStringFunctionSizeOverflow : ErrorBase {
   bool is_write;
 
   ErrorStringFunctionSizeOverflow() = default;  // (*)
-  ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace* stack_,
-                                  uptr addr, uptr size_, bool is_write_)
+  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_),
-        is_write(is_write_) {}
+        size(size),
+        is_write(is_write) {}
   void Print();
 };
 
diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h
index ab09c5028f587..b9a2159ab3930 100644
--- a/compiler-rt/lib/asan/asan_interface_internal.h
+++ b/compiler-rt/lib/asan/asan_interface_internal.h
@@ -159,6 +159,7 @@ extern "C" {
   uptr __asan_get_report_access_size();
 
   typedef enum {
+    __asan_address_info_none = 0,
     __asan_address_info_src = 1,
     __asan_address_info_dest = 2,
     __asan_address_info_dealloc = 3,
diff --git a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
index ca1dc8a97c020..ac7e367dcd101 100644
--- a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
@@ -52,10 +52,11 @@ extern "C" void __asan_on_error() {
   size_t size_dest = 0;
   int is_dest = __asan_get_report_address_info(__asan_address_info_dest,
                                                &addr_dest, &size_dest);
-  // Do not format the size_dest because it is a very large number (-1 as size_t) and might be printed differently
-  // depending on the platform's size_t. We just check it's populated.
-  fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT "\n", is_dest, addr_dest);
-  // CHECK: is_dest: 1, addr_dest: 0x{{[0-9a-f]+}}
+  // 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

>From 72668241763a1b4cdf06af5fad6654555052fe7e Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Tue, 14 Apr 2026 23:58:07 +0200
Subject: [PATCH 07/12] no tautological asserts

---
 compiler-rt/test/asan/TestCases/debug_double_free.cpp         | 2 +-
 .../test/asan/TestCases/debug_invalid_pointer_pair.cpp        | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
index cfd67eebf13c4..3804b6477ae60 100644
--- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
@@ -52,7 +52,7 @@ __asan_on_error() {
   // CHECK: description: double-free
 
   void *addr_dealloc = NULL;
-  size_t size_dealloc = 0;
+  size_t size_dealloc = 0xbad;
   int is_dealloc = __asan_get_report_address_info(__asan_address_info_dealloc,
                                                   &addr_dealloc, &size_dealloc);
   fprintf(stderr,
diff --git a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
index 2a299f92cceae..69d43b1a3fa4d 100644
--- a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
@@ -54,7 +54,7 @@ extern "C" void __asan_on_error() {
   // CHECK: report
 
   void *addr_first = NULL;
-  size_t size_first = 0;
+  size_t size_first = 0xbad;
   int is_first = __asan_get_report_address_info(__asan_address_info_first,
                                                 &addr_first, &size_first);
   fprintf(stderr, "is_first: %d, addr_first: " PTR_FMT ", size_first: %zu\n",
@@ -62,7 +62,7 @@ extern "C" void __asan_on_error() {
   // CHECK: is_first: 1, addr_first: 0x[[ADDR1]], size_first: 0
 
   void *addr_second = NULL;
-  size_t size_second = 0;
+  size_t size_second = 0xbad;
   int is_second = __asan_get_report_address_info(__asan_address_info_second,
                                                  &addr_second, &size_second);
   fprintf(stderr, "is_second: %d, addr_second: " PTR_FMT ", size_second: %zu\n",

>From 64044d559df0c8a7907438ff9f0ad1c7977276ae Mon Sep 17 00:00:00 2001
From: Maksim Ivanov <emaxx at google.com>
Date: Wed, 15 Apr 2026 00:15:15 +0200
Subject: [PATCH 08/12] optional out args

---
 compiler-rt/lib/asan/asan_report.cpp | 145 +++++++++++++--------------
 1 file changed, 71 insertions(+), 74 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_report.cpp b/compiler-rt/lib/asan/asan_report.cpp
index e19626934e272..7b21d1d6c26ad 100644
--- a/compiler-rt/lib/asan/asan_report.cpp
+++ b/compiler-rt/lib/asan/asan_report.cpp
@@ -604,104 +604,101 @@ uptr __asan_get_report_access_size() {
 
 int __asan_get_report_address_info(int type, uptr* out_addr, uptr* out_size) {
   ErrorDescription& err = ScopedInErrorReport::CurrentError();
+  uptr addr = 0;
+  uptr size = 0;
+  bool found = false;
   switch (type) {
     case __asan_address_info_src:
       if (err.kind == kErrorKindGeneric && !err.Generic.is_write) {
-        *out_addr = err.Generic.addr_description.Address();
-        *out_size = err.Generic.access_size;
-        return 1;
-      }
-      if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
-        *out_addr =
+        addr = err.Generic.addr_description.Address();
+        size = err.Generic.access_size;
+        found = true;
+      } else if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
+        addr =
             err.StringFunctionMemoryRangesOverlap.addr2_description.Address();
-        *out_size = err.StringFunctionMemoryRangesOverlap.length2;
-        return 1;
-      }
-      if (err.kind == kErrorKindStringFunctionSizeOverflow &&
-          !err.StringFunctionSizeOverflow.is_write) {
-        *out_addr = err.StringFunctionSizeOverflow.addr_description.Address();
-        *out_size = err.StringFunctionSizeOverflow.size;
-        return 1;
-      }
-      if (err.kind == kErrorKindMallocUsableSizeNotOwned) {
-        *out_addr = err.MallocUsableSizeNotOwned.addr_description.Address();
-        *out_size = 0;
-        return 1;
-      }
-      if (err.kind == kErrorKindSanitizerGetAllocatedSizeNotOwned) {
-        *out_addr =
-            err.SanitizerGetAllocatedSizeNotOwned.addr_description.Address();
-        *out_size = 0;
-        return 1;
+        size = err.StringFunctionMemoryRangesOverlap.length2;
+        found = true;
+      } else if (err.kind == kErrorKindStringFunctionSizeOverflow &&
+                 !err.StringFunctionSizeOverflow.is_write) {
+        addr = err.StringFunctionSizeOverflow.addr_description.Address();
+        size = err.StringFunctionSizeOverflow.size;
+        found = true;
+      } else if (err.kind == kErrorKindMallocUsableSizeNotOwned) {
+        addr = err.MallocUsableSizeNotOwned.addr_description.Address();
+        size = 0;
+        found = true;
+      } else if (err.kind == kErrorKindSanitizerGetAllocatedSizeNotOwned) {
+        addr = err.SanitizerGetAllocatedSizeNotOwned.addr_description.Address();
+        size = 0;
+        found = true;
       }
       break;
     case __asan_address_info_dest:
       if (err.kind == kErrorKindGeneric && err.Generic.is_write) {
-        *out_addr = err.Generic.addr_description.Address();
-        *out_size = err.Generic.access_size;
-        return 1;
-      }
-      if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
-        *out_addr =
+        addr = err.Generic.addr_description.Address();
+        size = err.Generic.access_size;
+        found = true;
+      } else if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
+        addr =
             err.StringFunctionMemoryRangesOverlap.addr1_description.Address();
-        *out_size = err.StringFunctionMemoryRangesOverlap.length1;
-        return 1;
-      }
-      if (err.kind == kErrorKindStringFunctionSizeOverflow &&
-          err.StringFunctionSizeOverflow.is_write) {
-        *out_addr = err.StringFunctionSizeOverflow.addr_description.Address();
-        *out_size = err.StringFunctionSizeOverflow.size;
-        return 1;
+        size = err.StringFunctionMemoryRangesOverlap.length1;
+        found = true;
+      } else if (err.kind == kErrorKindStringFunctionSizeOverflow &&
+                 err.StringFunctionSizeOverflow.is_write) {
+        addr = err.StringFunctionSizeOverflow.addr_description.Address();
+        size = err.StringFunctionSizeOverflow.size;
+        found = true;
       }
       break;
     case __asan_address_info_dealloc:
       if (err.kind == kErrorKindDoubleFree) {
-        *out_addr = err.DoubleFree.addr_description.addr;
-        *out_size = 0;
-        return 1;
-      }
-      if (err.kind == kErrorKindNewDeleteTypeMismatch) {
-        *out_addr = err.NewDeleteTypeMismatch.addr_description.addr;
-        *out_size = err.NewDeleteTypeMismatch.delete_size;
-        return 1;
-      }
-      if (err.kind == kErrorKindFreeNotMalloced) {
-        *out_addr = err.FreeNotMalloced.addr_description.Address();
-        *out_size = 0;
-        return 1;
-      }
-      if (err.kind == kErrorKindAllocTypeMismatch) {
-        *out_addr = err.AllocTypeMismatch.addr_description.Address();
-        *out_size = 0;
-        return 1;
+        addr = err.DoubleFree.addr_description.addr;
+        size = 0;
+        found = true;
+      } else if (err.kind == kErrorKindNewDeleteTypeMismatch) {
+        addr = err.NewDeleteTypeMismatch.addr_description.addr;
+        size = err.NewDeleteTypeMismatch.delete_size;
+        found = true;
+      } else if (err.kind == kErrorKindFreeNotMalloced) {
+        addr = err.FreeNotMalloced.addr_description.Address();
+        size = 0;
+        found = true;
+      } else if (err.kind == kErrorKindAllocTypeMismatch) {
+        addr = err.AllocTypeMismatch.addr_description.Address();
+        size = 0;
+        found = true;
       }
       break;
     case __asan_address_info_first:
       if (err.kind == kErrorKindInvalidPointerPair) {
-        *out_addr = err.InvalidPointerPair.addr1_description.Address();
-        *out_size = 0;
-        return 1;
-      }
-      if (err.kind == kErrorKindODRViolation) {
-        *out_addr = err.ODRViolation.global1.beg;
-        *out_size = 0;
-        return 1;
+        addr = err.InvalidPointerPair.addr1_description.Address();
+        size = 0;
+        found = true;
+      } else if (err.kind == kErrorKindODRViolation) {
+        addr = err.ODRViolation.global1.beg;
+        size = 0;
+        found = true;
       }
       break;
     case __asan_address_info_second:
       if (err.kind == kErrorKindInvalidPointerPair) {
-        *out_addr = err.InvalidPointerPair.addr2_description.Address();
-        *out_size = 0;
-        return 1;
-      }
-      if (err.kind == kErrorKindODRViolation) {
-        *out_addr = err.ODRViolation.global2.beg;
-        *out_size = 0;
-        return 1;
+        addr = err.InvalidPointerPair.addr2_description.Address();
+        size = 0;
+        found = true;
+      } else if (err.kind == kErrorKindODRViolation) {
+        addr = err.ODRViolation.global2.beg;
+        size = 0;
+        found = true;
       }
       break;
   }
-  return 0;
+  if (!found)
+    return 0;
+  if (out_addr)
+    *out_addr = addr;
+  if (out_size)
+    *out_size = size;
+  return 1;
 }
 
 const char *__asan_get_report_description() {

>From 06aed6fc0a5d79dd2e357b14d588419538415683 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 23 Apr 2026 18:07:34 -0700
Subject: [PATCH 09/12] [asan] Split __asan_get_report_address_info into
 specific functions

This patch replaces the generic `__asan_get_report_address_info` function
with a set of more specific functions:
- `__asan_get_report_src_address`
- `__asan_get_report_dest_address`
- `__asan_get_report_dealloc_address`
- `__asan_get_report_first_address`
- `__asan_get_report_second_address`
---
 .../include/sanitizer/asan_interface.h        |  65 ++++--
 compiler-rt/lib/asan/asan_interface.inc       |   6 +-
 .../lib/asan/asan_interface_internal.h        |  19 +-
 compiler-rt/lib/asan/asan_report.cpp          | 206 ++++++++++--------
 .../test/asan/TestCases/debug_double_free.cpp |   3 +-
 .../TestCases/debug_invalid_pointer_pair.cpp  |   6 +-
 .../asan/TestCases/debug_memcpy_overlap.cpp   |   6 +-
 .../asan/TestCases/debug_negative_size.cpp    |   6 +-
 .../test/asan/TestCases/debug_report.cpp      |  10 +-
 9 files changed, 181 insertions(+), 146 deletions(-)

diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 9bce79c1f793e..2705f79b6cdaf 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -174,31 +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);
 
-typedef enum {
-  __asan_address_info_none = 0,
-  // Source address (e.g. memcpy source, or the address being read from).
-  __asan_address_info_src = 1,
-  // Destination address (e.g. memcpy dest, or the address being written to).
-  __asan_address_info_dest = 2,
-  // Address being deallocated (lifetime is terminated).
-  __asan_address_info_dealloc = 3,
-  // First non-dereferenced operand (e.g. pointer comparison, ODR violation).
-  __asan_address_info_first = 4,
-  // Second non-dereferenced operand (e.g. pointer comparison, ODR violation).
-  __asan_address_info_second = 5,
-} __asan_address_info_type;
-
-/// Gets a specific address or address range involved in the current error.
-///
-/// \param type __asan_address_info_type which the info is requested for.
+/// 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(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. Zero may be reported
-/// (e.g., for pointer comparison errors as no dereferencing occurs).
+/// \param out_size [out] Storage for the range size.
 ///
 /// \returns 1 if found, 0 otherwise.
-int SANITIZER_CDECL __asan_get_report_address_info(int type, void **out_addr,
+int SANITIZER_CDECL __asan_get_report_dest_address(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(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(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(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_interface.inc b/compiler-rt/lib/asan/asan_interface.inc
index 7cbc4e636b5ab..f2aaedf293f39 100644
--- a/compiler-rt/lib/asan/asan_interface.inc
+++ b/compiler-rt/lib/asan/asan_interface.inc
@@ -33,7 +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_address_info)
+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 b9a2159ab3930..c87802debfe33 100644
--- a/compiler-rt/lib/asan/asan_interface_internal.h
+++ b/compiler-rt/lib/asan/asan_interface_internal.h
@@ -158,17 +158,16 @@ extern "C" {
   SANITIZER_INTERFACE_ATTRIBUTE
   uptr __asan_get_report_access_size();
 
-  typedef enum {
-    __asan_address_info_none = 0,
-    __asan_address_info_src = 1,
-    __asan_address_info_dest = 2,
-    __asan_address_info_dealloc = 3,
-    __asan_address_info_first = 4,
-    __asan_address_info_second = 5,
-  } __asan_address_info_type;
-
   SANITIZER_INTERFACE_ATTRIBUTE
-  int __asan_get_report_address_info(int type, uptr* out_addr, uptr* out_size);
+  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 7b484175b0f63..8b2cea44b1e87 100644
--- a/compiler-rt/lib/asan/asan_report.cpp
+++ b/compiler-rt/lib/asan/asan_report.cpp
@@ -610,103 +610,119 @@ uptr __asan_get_report_access_size() {
   return 0;
 }
 
-int __asan_get_report_address_info(int type, uptr* out_addr, uptr* out_size) {
+int __asan_get_report_src_address(uptr* out_addr, uptr* out_size) {
   ErrorDescription& err = ScopedInErrorReport::CurrentError();
-  uptr addr = 0;
-  uptr size = 0;
-  bool found = false;
-  switch (type) {
-    case __asan_address_info_src:
-      if (err.kind == kErrorKindGeneric && !err.Generic.is_write) {
-        addr = err.Generic.addr_description.Address();
-        size = err.Generic.access_size;
-        found = true;
-      } else if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
-        addr =
-            err.StringFunctionMemoryRangesOverlap.addr2_description.Address();
-        size = err.StringFunctionMemoryRangesOverlap.length2;
-        found = true;
-      } else if (err.kind == kErrorKindStringFunctionSizeOverflow &&
-                 !err.StringFunctionSizeOverflow.is_write) {
-        addr = err.StringFunctionSizeOverflow.addr_description.Address();
-        size = err.StringFunctionSizeOverflow.size;
-        found = true;
-      } else if (err.kind == kErrorKindMallocUsableSizeNotOwned) {
-        addr = err.MallocUsableSizeNotOwned.addr_description.Address();
-        size = 0;
-        found = true;
-      } else if (err.kind == kErrorKindSanitizerGetAllocatedSizeNotOwned) {
-        addr = err.SanitizerGetAllocatedSizeNotOwned.addr_description.Address();
-        size = 0;
-        found = true;
-      }
-      break;
-    case __asan_address_info_dest:
-      if (err.kind == kErrorKindGeneric && err.Generic.is_write) {
-        addr = err.Generic.addr_description.Address();
-        size = err.Generic.access_size;
-        found = true;
-      } else if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap) {
-        addr =
-            err.StringFunctionMemoryRangesOverlap.addr1_description.Address();
-        size = err.StringFunctionMemoryRangesOverlap.length1;
-        found = true;
-      } else if (err.kind == kErrorKindStringFunctionSizeOverflow &&
-                 err.StringFunctionSizeOverflow.is_write) {
-        addr = err.StringFunctionSizeOverflow.addr_description.Address();
-        size = err.StringFunctionSizeOverflow.size;
-        found = true;
-      }
-      break;
-    case __asan_address_info_dealloc:
-      if (err.kind == kErrorKindDoubleFree) {
-        addr = err.DoubleFree.addr_description.addr;
-        size = 0;
-        found = true;
-      } else if (err.kind == kErrorKindNewDeleteTypeMismatch) {
-        addr = err.NewDeleteTypeMismatch.addr_description.addr;
-        size = err.NewDeleteTypeMismatch.delete_size;
-        found = true;
-      } else if (err.kind == kErrorKindFreeNotMalloced) {
-        addr = err.FreeNotMalloced.addr_description.Address();
-        size = 0;
-        found = true;
-      } else if (err.kind == kErrorKindAllocTypeMismatch) {
-        addr = err.AllocTypeMismatch.addr_description.Address();
-        size = 0;
-        found = true;
-      }
-      break;
-    case __asan_address_info_first:
-      if (err.kind == kErrorKindInvalidPointerPair) {
-        addr = err.InvalidPointerPair.addr1_description.Address();
-        size = 0;
-        found = true;
-      } else if (err.kind == kErrorKindODRViolation) {
-        addr = err.ODRViolation.global1.beg;
-        size = 0;
-        found = true;
-      }
-      break;
-    case __asan_address_info_second:
-      if (err.kind == kErrorKindInvalidPointerPair) {
-        addr = err.InvalidPointerPair.addr2_description.Address();
-        size = 0;
-        found = true;
-      } else if (err.kind == kErrorKindODRViolation) {
-        addr = err.ODRViolation.global2.beg;
-        size = 0;
-        found = true;
-      }
-      break;
+  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 (!found)
-    return 0;
-  if (out_addr)
-    *out_addr = addr;
-  if (out_size)
-    *out_size = 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() {
diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
index 3804b6477ae60..26a73b1890e49 100644
--- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
@@ -53,8 +53,7 @@ __asan_on_error() {
 
   void *addr_dealloc = NULL;
   size_t size_dealloc = 0xbad;
-  int is_dealloc = __asan_get_report_address_info(__asan_address_info_dealloc,
-                                                  &addr_dealloc, &size_dealloc);
+  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);
diff --git a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
index 69d43b1a3fa4d..45585bc2adabf 100644
--- a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
@@ -55,16 +55,14 @@ extern "C" void __asan_on_error() {
 
   void *addr_first = NULL;
   size_t size_first = 0xbad;
-  int is_first = __asan_get_report_address_info(__asan_address_info_first,
-                                                &addr_first, &size_first);
+  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
 
   void *addr_second = NULL;
   size_t size_second = 0xbad;
-  int is_second = __asan_get_report_address_info(__asan_address_info_second,
-                                                 &addr_second, &size_second);
+  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
diff --git a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
index 276a91549c8c0..a3b047ff2361a 100644
--- a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
@@ -43,16 +43,14 @@ extern "C" void __asan_on_error() {
 
   void *addr_src = NULL;
   size_t size_src = 0;
-  int is_src = __asan_get_report_address_info(__asan_address_info_src,
-                                              &addr_src, &size_src);
+  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
 
   void *addr_dest = NULL;
   size_t size_dest = 0;
-  int is_dest = __asan_get_report_address_info(__asan_address_info_dest,
-                                               &addr_dest, &size_dest);
+  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
diff --git a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
index ac7e367dcd101..a34cd766514cb 100644
--- a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
@@ -43,15 +43,13 @@ extern "C" void __asan_on_error() {
 
   void *addr_src = NULL;
   size_t size_src = 0;
-  int is_src = __asan_get_report_address_info(__asan_address_info_src,
-                                              &addr_src, &size_src);
+  int is_src = __asan_get_report_src_address(&addr_src, &size_src);
   fprintf(stderr, "is_src: %d\n", is_src);
   // CHECK: is_src: 0
 
   void *addr_dest = NULL;
   size_t size_dest = 0;
-  int is_dest = __asan_get_report_address_info(__asan_address_info_dest,
-                                               &addr_dest, &size_dest);
+  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",
diff --git a/compiler-rt/test/asan/TestCases/debug_report.cpp b/compiler-rt/test/asan/TestCases/debug_report.cpp
index 06ef4d565098f..18f5582cbeb9f 100644
--- a/compiler-rt/test/asan/TestCases/debug_report.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_report.cpp
@@ -68,16 +68,14 @@ __asan_on_error() {
 
   void *addr2 = NULL;
   size_t size2 = 0;
-  int is_dest =
-      __asan_get_report_address_info(__asan_address_info_dest, &addr2, &size2);
+  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_none =
-      __asan_get_report_address_info(__asan_address_info_none, &addr2, &size2);
-  fprintf(stderr, "is_none: %d\n", is_none);
-  // CHECK: is_none: 0
+  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]]

>From ef4e973432bd4b5c4d55ec5ab51d7f1e0513a566 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 23 Apr 2026 18:34:27 -0700
Subject: [PATCH 10/12] asan: split __asan_get_report_*_address into address
 and size

---
 .../include/sanitizer/asan_interface.h        |  63 ++++---
 compiler-rt/lib/asan/asan_interface.inc       |   5 +
 .../lib/asan/asan_interface_internal.h        |  20 ++-
 compiler-rt/lib/asan/asan_report.cpp          | 169 ++++++++----------
 .../test/asan/TestCases/debug_double_free.cpp |   7 +-
 .../TestCases/debug_invalid_pointer_pair.cpp  |  14 +-
 .../asan/TestCases/debug_memcpy_overlap.cpp   |  16 +-
 .../asan/TestCases/debug_negative_size.cpp    |  13 +-
 .../test/asan/TestCases/debug_report.cpp      |  11 +-
 9 files changed, 157 insertions(+), 161 deletions(-)

diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 2705f79b6cdaf..7dad26e4e9b29 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -174,55 +174,62 @@ 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
+/// Gets the source address 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 Returns the address if found. Otherwise returns 0.
+void *SANITIZER_CDECL __asan_get_report_src_address(void);
+
+/// Gets the source address range size involved in the current error.
 ///
-/// \returns 1 if found, 0 otherwise.
-int SANITIZER_CDECL __asan_get_report_src_address(void **out_addr,
-                                                  size_t *out_size);
+/// \returns Returns the size in bytes.
+size_t SANITIZER_CDECL __asan_get_report_src_size(void);
 
-/// Gets the destination address or address range involved in the current error
+/// Gets the destination address 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 Returns the address if found. Otherwise returns 0.
+void *SANITIZER_CDECL __asan_get_report_dest_address(void);
+
+/// Gets the destination address range size involved in the current error.
 ///
-/// \returns 1 if found, 0 otherwise.
-int SANITIZER_CDECL __asan_get_report_dest_address(void **out_addr,
-                                                   size_t *out_size);
+/// \returns Returns the size in bytes.
+size_t SANITIZER_CDECL __asan_get_report_dest_size(void);
 
-/// Gets the address or address range being deallocated in the current error
+/// Gets the address 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 Returns the address if found. Otherwise returns 0.
+void *SANITIZER_CDECL __asan_get_report_dealloc_address(void);
+
+/// Gets the deallocated address range size involved in the current error.
 ///
-/// \returns 1 if found, 0 otherwise.
-int SANITIZER_CDECL __asan_get_report_dealloc_address(void **out_addr,
-                                                      size_t *out_size);
+/// \returns Returns the size in bytes.
+size_t SANITIZER_CDECL __asan_get_report_dealloc_size(void);
 
 /// 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 Returns the address if found. Otherwise returns 0.
+void *SANITIZER_CDECL __asan_get_report_first_address(void);
+
+/// Gets the first non-dereferenced operand address range size involved in the
+/// current error.
 ///
-/// \returns 1 if found, 0 otherwise.
-int SANITIZER_CDECL __asan_get_report_first_address(void **out_addr,
-                                                    size_t *out_size);
+/// \returns Returns the size in bytes.
+size_t SANITIZER_CDECL __asan_get_report_first_size(void);
 
 /// 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 Returns the address if found. Otherwise returns 0.
+void *SANITIZER_CDECL __asan_get_report_second_address(void);
+
+/// Gets the second non-dereferenced operand address range size involved in the
+/// current error.
 ///
-/// \returns 1 if found, 0 otherwise.
-int SANITIZER_CDECL __asan_get_report_second_address(void **out_addr,
-                                                     size_t *out_size);
+/// \returns Returns the size in bytes.
+size_t SANITIZER_CDECL __asan_get_report_second_size(void);
 
 /// Gets the bug description of an ASan error (useful for calling from a
 /// debugger).
diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc
index f2aaedf293f39..6338f9837af28 100644
--- a/compiler-rt/lib/asan/asan_interface.inc
+++ b/compiler-rt/lib/asan/asan_interface.inc
@@ -34,10 +34,15 @@ 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_src_size)
 INTERFACE_FUNCTION(__asan_get_report_dest_address)
+INTERFACE_FUNCTION(__asan_get_report_dest_size)
 INTERFACE_FUNCTION(__asan_get_report_dealloc_address)
+INTERFACE_FUNCTION(__asan_get_report_dealloc_size)
 INTERFACE_FUNCTION(__asan_get_report_first_address)
+INTERFACE_FUNCTION(__asan_get_report_first_size)
 INTERFACE_FUNCTION(__asan_get_report_second_address)
+INTERFACE_FUNCTION(__asan_get_report_second_size)
 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 c87802debfe33..18904fbbca5bd 100644
--- a/compiler-rt/lib/asan/asan_interface_internal.h
+++ b/compiler-rt/lib/asan/asan_interface_internal.h
@@ -159,15 +159,25 @@ extern "C" {
   uptr __asan_get_report_access_size();
 
   SANITIZER_INTERFACE_ATTRIBUTE
-  int __asan_get_report_src_address(uptr* out_addr, uptr* out_size);
+  uptr __asan_get_report_src_address(void);
   SANITIZER_INTERFACE_ATTRIBUTE
-  int __asan_get_report_dest_address(uptr* out_addr, uptr* out_size);
+  uptr __asan_get_report_src_size(void);
   SANITIZER_INTERFACE_ATTRIBUTE
-  int __asan_get_report_dealloc_address(uptr* out_addr, uptr* out_size);
+  uptr __asan_get_report_dest_address(void);
   SANITIZER_INTERFACE_ATTRIBUTE
-  int __asan_get_report_first_address(uptr* out_addr, uptr* out_size);
+  uptr __asan_get_report_dest_size(void);
   SANITIZER_INTERFACE_ATTRIBUTE
-  int __asan_get_report_second_address(uptr* out_addr, uptr* out_size);
+  uptr __asan_get_report_dealloc_address(void);
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_dealloc_size(void);
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_first_address(void);
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_first_size(void);
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_second_address(void);
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_second_size(void);
 
   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 8b2cea44b1e87..51474929a970d 100644
--- a/compiler-rt/lib/asan/asan_report.cpp
+++ b/compiler-rt/lib/asan/asan_report.cpp
@@ -610,118 +610,101 @@ uptr __asan_get_report_access_size() {
   return 0;
 }
 
-int __asan_get_report_src_address(uptr* out_addr, uptr* out_size) {
+uptr __asan_get_report_src_address() {
   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 == kErrorKindGeneric && !err.Generic.is_write)
+    return err.Generic.addr_description.Address();
+  if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap)
+    return err.StringFunctionMemoryRangesOverlap.addr2_description.Address();
   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;
-  }
+      !err.StringFunctionSizeOverflow.is_write)
+    return err.StringFunctionSizeOverflow.addr_description.Address();
+  if (err.kind == kErrorKindMallocUsableSizeNotOwned)
+    return err.MallocUsableSizeNotOwned.addr_description.Address();
+  if (err.kind == kErrorKindSanitizerGetAllocatedSizeNotOwned)
+    return err.SanitizerGetAllocatedSizeNotOwned.addr_description.Address();
   return 0;
 }
 
-int __asan_get_report_dest_address(uptr* out_addr, uptr* out_size) {
+uptr __asan_get_report_src_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 == kErrorKindGeneric && !err.Generic.is_write)
+    return err.Generic.access_size;
+  if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap)
+    return err.StringFunctionMemoryRangesOverlap.length2;
   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;
-  }
+      !err.StringFunctionSizeOverflow.is_write)
+    return err.StringFunctionSizeOverflow.size;
   return 0;
 }
 
-int __asan_get_report_dealloc_address(uptr* out_addr, uptr* out_size) {
+uptr __asan_get_report_dest_address() {
   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;
-  }
+  if (err.kind == kErrorKindGeneric && err.Generic.is_write)
+    return err.Generic.addr_description.Address();
+  if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap)
+    return err.StringFunctionMemoryRangesOverlap.addr1_description.Address();
+  if (err.kind == kErrorKindStringFunctionSizeOverflow &&
+      err.StringFunctionSizeOverflow.is_write)
+    return err.StringFunctionSizeOverflow.addr_description.Address();
   return 0;
 }
 
-int __asan_get_report_first_address(uptr* out_addr, uptr* out_size) {
+uptr __asan_get_report_dest_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;
-  }
+  if (err.kind == kErrorKindGeneric && err.Generic.is_write)
+    return err.Generic.access_size;
+  if (err.kind == kErrorKindStringFunctionMemoryRangesOverlap)
+    return err.StringFunctionMemoryRangesOverlap.length1;
+  if (err.kind == kErrorKindStringFunctionSizeOverflow &&
+      err.StringFunctionSizeOverflow.is_write)
+    return err.StringFunctionSizeOverflow.size;
   return 0;
 }
 
-int __asan_get_report_second_address(uptr* out_addr, uptr* out_size) {
+uptr __asan_get_report_dealloc_address() {
   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;
-  }
+  if (err.kind == kErrorKindDoubleFree)
+    return err.DoubleFree.addr_description.addr;
+  if (err.kind == kErrorKindNewDeleteTypeMismatch)
+    return err.NewDeleteTypeMismatch.addr_description.addr;
+  if (err.kind == kErrorKindFreeNotMalloced)
+    return err.FreeNotMalloced.addr_description.Address();
+  if (err.kind == kErrorKindAllocTypeMismatch)
+    return err.AllocTypeMismatch.addr_description.Address();
+  return 0;
+}
+
+uptr __asan_get_report_dealloc_size() {
+  ErrorDescription& err = ScopedInErrorReport::CurrentError();
+  if (err.kind == kErrorKindNewDeleteTypeMismatch)
+    return err.NewDeleteTypeMismatch.delete_size;
+  return 0;
+}
+
+uptr __asan_get_report_first_address() {
+  ErrorDescription& err = ScopedInErrorReport::CurrentError();
+  if (err.kind == kErrorKindInvalidPointerPair)
+    return err.InvalidPointerPair.addr1_description.Address();
+  if (err.kind == kErrorKindODRViolation)
+    return err.ODRViolation.global1.beg;
+  return 0;
+}
+
+uptr __asan_get_report_first_size() {
+  return 0;
+}
+
+uptr __asan_get_report_second_address() {
+  ErrorDescription& err = ScopedInErrorReport::CurrentError();
+  if (err.kind == kErrorKindInvalidPointerPair)
+    return err.InvalidPointerPair.addr2_description.Address();
+  if (err.kind == kErrorKindODRViolation)
+    return err.ODRViolation.global2.beg;
+  return 0;
+}
+
+uptr __asan_get_report_second_size() {
   return 0;
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
index 26a73b1890e49..1efaf8f703191 100644
--- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
@@ -51,12 +51,11 @@ __asan_on_error() {
   fprintf(stderr, "description: %s\n", description);
   // CHECK: description: double-free
 
-  void *addr_dealloc = NULL;
-  size_t size_dealloc = 0xbad;
-  int is_dealloc = __asan_get_report_dealloc_address(&addr_dealloc, &size_dealloc);
+  void *addr_dealloc = __asan_get_report_dealloc_address();
+  size_t size_dealloc = __asan_get_report_dealloc_size();
   fprintf(stderr,
           "is_dealloc: %d, addr_dealloc: " PTR_FMT ", size_dealloc: %zu\n",
-          is_dealloc, addr_dealloc, size_dealloc);
+          !!addr_dealloc, addr_dealloc, size_dealloc);
   // CHECK: is_dealloc: 1, addr_dealloc: 0x[[ADDR]], size_dealloc: 0
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
index 45585bc2adabf..464bb9a4a17b4 100644
--- a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
@@ -53,18 +53,16 @@ extern "C" void __asan_on_error() {
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
-  void *addr_first = NULL;
-  size_t size_first = 0xbad;
-  int is_first = __asan_get_report_first_address(&addr_first, &size_first);
+  void *addr_first = __asan_get_report_first_address();
+  size_t size_first = __asan_get_report_first_size();
   fprintf(stderr, "is_first: %d, addr_first: " PTR_FMT ", size_first: %zu\n",
-          is_first, addr_first, size_first);
+          !!addr_first, addr_first, size_first);
   // CHECK: is_first: 1, addr_first: 0x[[ADDR1]], size_first: 0
 
-  void *addr_second = NULL;
-  size_t size_second = 0xbad;
-  int is_second = __asan_get_report_second_address(&addr_second, &size_second);
+  void *addr_second = __asan_get_report_second_address();
+  size_t size_second = __asan_get_report_second_size();
   fprintf(stderr, "is_second: %d, addr_second: " PTR_FMT ", size_second: %zu\n",
-          is_second, addr_second, size_second);
+          !!addr_second, addr_second, size_second);
   // CHECK: is_second: 1, addr_second: 0x[[ADDR2]], size_second: 0
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
index a3b047ff2361a..6ef4249c902b2 100644
--- a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
@@ -41,18 +41,16 @@ extern "C" void __asan_on_error() {
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
-  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);
+  void *addr_src = __asan_get_report_src_address();
+  size_t size_src = __asan_get_report_src_size();
+  fprintf(stderr, "is_src: %d, addr_src: " PTR_FMT ", size_src: %zu\n",
+          !!addr_src, addr_src, size_src);
   // CHECK: is_src: 1, addr_src: 0x{{[0-9a-f]+}}, size_src: 3
 
-  void *addr_dest = NULL;
-  size_t size_dest = 0;
-  int is_dest = __asan_get_report_dest_address(&addr_dest, &size_dest);
+  void *addr_dest = __asan_get_report_dest_address();
+  size_t size_dest = __asan_get_report_dest_size();
   fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT ", size_dest: %zu\n",
-          is_dest, addr_dest, size_dest);
+          !!addr_dest, addr_dest, size_dest);
   // CHECK: is_dest: 1, addr_dest: 0x{{[0-9a-f]+}}, size_dest: 3
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
index a34cd766514cb..94abf26fa2301 100644
--- a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
@@ -41,19 +41,16 @@ extern "C" void __asan_on_error() {
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
-  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);
+  void *addr_src = __asan_get_report_src_address();
+  fprintf(stderr, "is_src: %d\n", !!addr_src);
   // CHECK: is_src: 0
 
-  void *addr_dest = NULL;
-  size_t size_dest = 0;
-  int is_dest = __asan_get_report_dest_address(&addr_dest, &size_dest);
+  void *addr_dest = __asan_get_report_dest_address();
+  size_t size_dest = __asan_get_report_dest_size();
   // 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);
+          !!addr_dest, addr_dest, size_dest + 1);
   // CHECK: is_dest: 1, addr_dest: 0x{{[0-9a-f]+}}, size_dest+1: 0
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_report.cpp b/compiler-rt/test/asan/TestCases/debug_report.cpp
index 18f5582cbeb9f..bdc4dd71274e7 100644
--- a/compiler-rt/test/asan/TestCases/debug_report.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_report.cpp
@@ -66,15 +66,14 @@ __asan_on_error() {
   fprintf(stderr, "description: %s\n", description);
   // CHECK: description: heap-use-after-free
 
-  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,
+  void *addr2 = __asan_get_report_dest_address();
+  size_t size2 = __asan_get_report_dest_size();
+  fprintf(stderr, "is_dest: %d, addr2: " PTR_FMT ", size2: %zu\n", !!addr2,
           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);
+  void *addr_src = __asan_get_report_src_address();
+  fprintf(stderr, "is_src: %d\n", !!addr_src);
   // CHECK: is_src: 0
 }
 

>From 2c5f371835cb46f25cfdb9abb2b2a821256a5dfb Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 23 Apr 2026 18:37:27 -0700
Subject: [PATCH 11/12] [asan] Remove unused __asan_get_report_first_size and
 __asan_get_report_second_size

---
 compiler-rt/include/sanitizer/asan_interface.h     | 12 ------------
 compiler-rt/lib/asan/asan_interface.inc            |  2 --
 compiler-rt/lib/asan/asan_interface_internal.h     |  4 ----
 compiler-rt/lib/asan/asan_report.cpp               |  8 --------
 .../asan/TestCases/debug_invalid_pointer_pair.cpp  | 14 ++++++--------
 5 files changed, 6 insertions(+), 34 deletions(-)

diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 7dad26e4e9b29..1f1825772432c 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -213,24 +213,12 @@ size_t SANITIZER_CDECL __asan_get_report_dealloc_size(void);
 /// \returns Returns the address if found. Otherwise returns 0.
 void *SANITIZER_CDECL __asan_get_report_first_address(void);
 
-/// Gets the first non-dereferenced operand address range size involved in the
-/// current error.
-///
-/// \returns Returns the size in bytes.
-size_t SANITIZER_CDECL __asan_get_report_first_size(void);
-
 /// Gets the second non-dereferenced operand address involved in the current
 /// error (e.g., pointer comparison or ODR violation).
 ///
 /// \returns Returns the address if found. Otherwise returns 0.
 void *SANITIZER_CDECL __asan_get_report_second_address(void);
 
-/// Gets the second non-dereferenced operand address range size involved in the
-/// current error.
-///
-/// \returns Returns the size in bytes.
-size_t SANITIZER_CDECL __asan_get_report_second_size(void);
-
 /// Gets the bug description of an ASan error (useful for calling from a
 /// debugger).
 ///
diff --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc
index 6338f9837af28..3bf44c31d46f9 100644
--- a/compiler-rt/lib/asan/asan_interface.inc
+++ b/compiler-rt/lib/asan/asan_interface.inc
@@ -40,9 +40,7 @@ INTERFACE_FUNCTION(__asan_get_report_dest_size)
 INTERFACE_FUNCTION(__asan_get_report_dealloc_address)
 INTERFACE_FUNCTION(__asan_get_report_dealloc_size)
 INTERFACE_FUNCTION(__asan_get_report_first_address)
-INTERFACE_FUNCTION(__asan_get_report_first_size)
 INTERFACE_FUNCTION(__asan_get_report_second_address)
-INTERFACE_FUNCTION(__asan_get_report_second_size)
 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 18904fbbca5bd..d1103ee8a70a5 100644
--- a/compiler-rt/lib/asan/asan_interface_internal.h
+++ b/compiler-rt/lib/asan/asan_interface_internal.h
@@ -173,11 +173,7 @@ extern "C" {
   SANITIZER_INTERFACE_ATTRIBUTE
   uptr __asan_get_report_first_address(void);
   SANITIZER_INTERFACE_ATTRIBUTE
-  uptr __asan_get_report_first_size(void);
-  SANITIZER_INTERFACE_ATTRIBUTE
   uptr __asan_get_report_second_address(void);
-  SANITIZER_INTERFACE_ATTRIBUTE
-  uptr __asan_get_report_second_size(void);
 
   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 51474929a970d..c65e5ef902a76 100644
--- a/compiler-rt/lib/asan/asan_report.cpp
+++ b/compiler-rt/lib/asan/asan_report.cpp
@@ -691,10 +691,6 @@ uptr __asan_get_report_first_address() {
   return 0;
 }
 
-uptr __asan_get_report_first_size() {
-  return 0;
-}
-
 uptr __asan_get_report_second_address() {
   ErrorDescription& err = ScopedInErrorReport::CurrentError();
   if (err.kind == kErrorKindInvalidPointerPair)
@@ -704,10 +700,6 @@ uptr __asan_get_report_second_address() {
   return 0;
 }
 
-uptr __asan_get_report_second_size() {
-  return 0;
-}
-
 const char *__asan_get_report_description() {
   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
     return ScopedInErrorReport::CurrentError().Generic.bug_descr;
diff --git a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
index 464bb9a4a17b4..e0d22134f377e 100644
--- a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
@@ -54,16 +54,14 @@ extern "C" void __asan_on_error() {
   // CHECK: report
 
   void *addr_first = __asan_get_report_first_address();
-  size_t size_first = __asan_get_report_first_size();
-  fprintf(stderr, "is_first: %d, addr_first: " PTR_FMT ", size_first: %zu\n",
-          !!addr_first, addr_first, size_first);
-  // CHECK: is_first: 1, addr_first: 0x[[ADDR1]], size_first: 0
+  fprintf(stderr, "is_first: %d, addr_first: " PTR_FMT "\n",
+          !!addr_first, addr_first);
+  // CHECK: is_first: 1, addr_first: 0x[[ADDR1]]
 
   void *addr_second = __asan_get_report_second_address();
-  size_t size_second = __asan_get_report_second_size();
-  fprintf(stderr, "is_second: %d, addr_second: " PTR_FMT ", size_second: %zu\n",
-          !!addr_second, addr_second, size_second);
-  // CHECK: is_second: 1, addr_second: 0x[[ADDR2]], size_second: 0
+  fprintf(stderr, "is_second: %d, addr_second: " PTR_FMT "\n",
+          !!addr_second, addr_second);
+  // CHECK: is_second: 1, addr_second: 0x[[ADDR2]]
 }
 
 // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair

>From 145b9c37c349e7c26cf378aeece101248424c966 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 23 Apr 2026 19:09:19 -0700
Subject: [PATCH 12/12] [asan] Use const void*

---
 compiler-rt/include/sanitizer/asan_interface.h       | 10 +++++-----
 .../test/asan/TestCases/debug_double_free.cpp        |  2 +-
 .../asan/TestCases/debug_invalid_pointer_pair.cpp    | 12 ++++++------
 .../test/asan/TestCases/debug_memcpy_overlap.cpp     |  4 ++--
 .../test/asan/TestCases/debug_negative_size.cpp      |  4 ++--
 compiler-rt/test/asan/TestCases/debug_report.cpp     |  4 ++--
 6 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/compiler-rt/include/sanitizer/asan_interface.h b/compiler-rt/include/sanitizer/asan_interface.h
index 1f1825772432c..078ca490c8de9 100644
--- a/compiler-rt/include/sanitizer/asan_interface.h
+++ b/compiler-rt/include/sanitizer/asan_interface.h
@@ -178,7 +178,7 @@ size_t SANITIZER_CDECL __asan_get_report_access_size(void);
 /// (e.g., memcpy source, or the address being read from).
 ///
 /// \returns Returns the address if found. Otherwise returns 0.
-void *SANITIZER_CDECL __asan_get_report_src_address(void);
+const void *SANITIZER_CDECL __asan_get_report_src_address(void);
 
 /// Gets the source address range size involved in the current error.
 ///
@@ -189,7 +189,7 @@ size_t SANITIZER_CDECL __asan_get_report_src_size(void);
 /// (e.g., memcpy dest, or the address being written to).
 ///
 /// \returns Returns the address if found. Otherwise returns 0.
-void *SANITIZER_CDECL __asan_get_report_dest_address(void);
+const void *SANITIZER_CDECL __asan_get_report_dest_address(void);
 
 /// Gets the destination address range size involved in the current error.
 ///
@@ -200,7 +200,7 @@ size_t SANITIZER_CDECL __asan_get_report_dest_size(void);
 /// (lifetime is terminated).
 ///
 /// \returns Returns the address if found. Otherwise returns 0.
-void *SANITIZER_CDECL __asan_get_report_dealloc_address(void);
+const void *SANITIZER_CDECL __asan_get_report_dealloc_address(void);
 
 /// Gets the deallocated address range size involved in the current error.
 ///
@@ -211,13 +211,13 @@ size_t SANITIZER_CDECL __asan_get_report_dealloc_size(void);
 /// error (e.g., pointer comparison or ODR violation).
 ///
 /// \returns Returns the address if found. Otherwise returns 0.
-void *SANITIZER_CDECL __asan_get_report_first_address(void);
+const void *SANITIZER_CDECL __asan_get_report_first_address(void);
 
 /// Gets the second non-dereferenced operand address involved in the current
 /// error (e.g., pointer comparison or ODR violation).
 ///
 /// \returns Returns the address if found. Otherwise returns 0.
-void *SANITIZER_CDECL __asan_get_report_second_address(void);
+const void *SANITIZER_CDECL __asan_get_report_second_address(void);
 
 /// Gets the bug description of an ASan error (useful for calling from a
 /// debugger).
diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
index 1efaf8f703191..41d68ff5459f2 100644
--- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp
@@ -51,7 +51,7 @@ __asan_on_error() {
   fprintf(stderr, "description: %s\n", description);
   // CHECK: description: double-free
 
-  void *addr_dealloc = __asan_get_report_dealloc_address();
+  const void *addr_dealloc = __asan_get_report_dealloc_address();
   size_t size_dealloc = __asan_get_report_dealloc_size();
   fprintf(stderr,
           "is_dealloc: %d, addr_dealloc: " PTR_FMT ", size_dealloc: %zu\n",
diff --git a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
index e0d22134f377e..ec7b0b4557d1d 100644
--- a/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_invalid_pointer_pair.cpp
@@ -53,14 +53,14 @@ extern "C" void __asan_on_error() {
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
-  void *addr_first = __asan_get_report_first_address();
-  fprintf(stderr, "is_first: %d, addr_first: " PTR_FMT "\n",
-          !!addr_first, addr_first);
+  const void *addr_first = __asan_get_report_first_address();
+  fprintf(stderr, "is_first: %d, addr_first: " PTR_FMT "\n", !!addr_first,
+          addr_first);
   // CHECK: is_first: 1, addr_first: 0x[[ADDR1]]
 
-  void *addr_second = __asan_get_report_second_address();
-  fprintf(stderr, "is_second: %d, addr_second: " PTR_FMT "\n",
-          !!addr_second, addr_second);
+  const void *addr_second = __asan_get_report_second_address();
+  fprintf(stderr, "is_second: %d, addr_second: " PTR_FMT "\n", !!addr_second,
+          addr_second);
   // CHECK: is_second: 1, addr_second: 0x[[ADDR2]]
 }
 
diff --git a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
index 6ef4249c902b2..a885213f01842 100644
--- a/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_memcpy_overlap.cpp
@@ -41,13 +41,13 @@ extern "C" void __asan_on_error() {
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
-  void *addr_src = __asan_get_report_src_address();
+  const void *addr_src = __asan_get_report_src_address();
   size_t size_src = __asan_get_report_src_size();
   fprintf(stderr, "is_src: %d, addr_src: " PTR_FMT ", size_src: %zu\n",
           !!addr_src, addr_src, size_src);
   // CHECK: is_src: 1, addr_src: 0x{{[0-9a-f]+}}, size_src: 3
 
-  void *addr_dest = __asan_get_report_dest_address();
+  const void *addr_dest = __asan_get_report_dest_address();
   size_t size_dest = __asan_get_report_dest_size();
   fprintf(stderr, "is_dest: %d, addr_dest: " PTR_FMT ", size_dest: %zu\n",
           !!addr_dest, addr_dest, size_dest);
diff --git a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
index 94abf26fa2301..7270c2163bf71 100644
--- a/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_negative_size.cpp
@@ -41,11 +41,11 @@ extern "C" void __asan_on_error() {
   fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
   // CHECK: report
 
-  void *addr_src = __asan_get_report_src_address();
+  const void *addr_src = __asan_get_report_src_address();
   fprintf(stderr, "is_src: %d\n", !!addr_src);
   // CHECK: is_src: 0
 
-  void *addr_dest = __asan_get_report_dest_address();
+  const void *addr_dest = __asan_get_report_dest_address();
   size_t size_dest = __asan_get_report_dest_size();
   // 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.
diff --git a/compiler-rt/test/asan/TestCases/debug_report.cpp b/compiler-rt/test/asan/TestCases/debug_report.cpp
index bdc4dd71274e7..9d19bbeade28a 100644
--- a/compiler-rt/test/asan/TestCases/debug_report.cpp
+++ b/compiler-rt/test/asan/TestCases/debug_report.cpp
@@ -66,13 +66,13 @@ __asan_on_error() {
   fprintf(stderr, "description: %s\n", description);
   // CHECK: description: heap-use-after-free
 
-  void *addr2 = __asan_get_report_dest_address();
+  const void *addr2 = __asan_get_report_dest_address();
   size_t size2 = __asan_get_report_dest_size();
   fprintf(stderr, "is_dest: %d, addr2: " PTR_FMT ", size2: %zu\n", !!addr2,
           addr2, size2);
   // CHECK: is_dest: 1, addr2: 0x[[ADDR]], size2: 1
 
-  void *addr_src = __asan_get_report_src_address();
+  const void *addr_src = __asan_get_report_src_address();
   fprintf(stderr, "is_src: %d\n", !!addr_src);
   // CHECK: is_src: 0
 }



More information about the llvm-commits mailing list