[compiler-rt] [ASan][AIX] Preserve original allocation alignment through realloc (PR #184967)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 4 02:27:25 PDT 2026
https://github.com/midhuncodes7 updated https://github.com/llvm/llvm-project/pull/184967
>From 74b1628752254a4ddbc88aaa0f5ba59ac0190cd6 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Thu, 5 Mar 2026 11:56:31 +0530
Subject: [PATCH 01/11] Fix 16 byte alignment for allocators
---
.../lib/asan/AIX/asan.link_with_main_exec.txt | 6 ++
compiler-rt/lib/asan/asan_allocator.cpp | 14 ++-
compiler-rt/lib/asan/asan_allocator.h | 1 +
compiler-rt/lib/asan/asan_malloc_linux.cpp | 54 ++++++++++--
.../sanitizer_allocator_dlsym.h | 6 +-
.../asan/TestCases/AIX/vec_malloc_calloc.cpp | 86 +++++++++++++++++--
6 files changed, 149 insertions(+), 18 deletions(-)
diff --git a/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt b/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
index 5efc48c262369..4bc85e3e50256 100644
--- a/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
+++ b/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
@@ -113,3 +113,9 @@ __asan_poison_stack_memory
__asan_unpoison_stack_memory
__asan_option_detect_stack_use_after_return
__asan_shadow_memory_dynamic_address
+__interceptor_vec_calloc
+__interceptor_vec_malloc
+__interceptor_vec_realloc
+vec_calloc
+vec_malloc
+vec_realloc
diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index 59aeec6a6ae66..cce89adb1539e 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -783,8 +783,12 @@ struct Allocator {
AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.reallocs++;
thread_stats.realloced += new_size;
-
- void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC, true);
+
+ // Preserve the original allocation's alignment
+ uptr orig_align = ComputeUserAlignment(m->user_requested_alignment_log);
+ if (orig_align < 8)
+ orig_align = 8;
+ void *new_ptr = Allocate(new_size, orig_align, stack, FROM_MALLOC, true);
if (new_ptr) {
u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
if (chunk_state != CHUNK_ALLOCATED)
@@ -1059,6 +1063,12 @@ void* asan_vec_malloc(uptr size, BufferedStackTrace* stack) {
void* asan_vec_calloc(uptr nmemb, uptr size, BufferedStackTrace* stack) {
return SetErrnoOnNull(instance.Calloc(nmemb, size, stack, 16));
}
+
+void* asan_vec_realloc(void* p, uptr size, BufferedStackTrace* stack) {
+ if (!p)
+ return SetErrnoOnNull(instance.Allocate(size, 16, stack, FROM_MALLOC, true));
+ return asan_realloc(p, size, stack);
+}
#endif
void *asan_reallocarray(void *p, uptr nmemb, uptr size,
diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h
index 8521e8d068db1..63f7ee6730e55 100644
--- a/compiler-rt/lib/asan/asan_allocator.h
+++ b/compiler-rt/lib/asan/asan_allocator.h
@@ -283,6 +283,7 @@ void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
#if SANITIZER_AIX
void* asan_vec_malloc(uptr size, BufferedStackTrace* stack);
void* asan_vec_calloc(uptr nmemb, uptr size, BufferedStackTrace* stack);
+void* asan_vec_realloc(void* p, uptr size, BufferedStackTrace* stack);
#endif
void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
void *asan_reallocarray(void *p, uptr nmemb, uptr size,
diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp
index a1b10a5fb8558..8c5b19dd3b9da 100644
--- a/compiler-rt/lib/asan/asan_malloc_linux.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp
@@ -53,6 +53,29 @@ INTERCEPTOR(void, free, void *ptr) {
}
#if SANITIZER_INTERCEPT_CFREE
+INTERCEPTOR(void*, __linux_vec_malloc, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size, 16);
+ AsanInitFromRtl();
+ GET_STACK_TRACE_MALLOC;
+ return asan_vec_malloc(size, &stack);
+ }
+
+INTERCEPTOR(void*, __linux_vec_calloc, uptr nmemb, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size, 16);
+ AsanInitFromRtl();
+ GET_STACK_TRACE_MALLOC;
+ return asan_vec_calloc(nmemb, size, &stack);
+}
+
+INTERCEPTOR(void*, __linux_realloc, void* ptr, uptr size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size, 16);
+ GET_STACK_TRACE_MALLOC;
+ return asan_vec_realloc(ptr, size, &stack);
+}
+
INTERCEPTOR(void, cfree, void *ptr) {
if (DlsymAlloc::PointerIsMine(ptr))
return DlsymAlloc::Free(ptr);
@@ -77,32 +100,47 @@ INTERCEPTOR(void*, vec_calloc, uptr nmemb, uptr size) {
GET_STACK_TRACE_MALLOC;
return asan_vec_calloc(nmemb, size, &stack);
}
+
+// Unlike realloc, vec_realloc must return memory aligned to 16 bytes.
+INTERCEPTOR(void*, vec_realloc, void* ptr, uptr size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size, 16);
+ GET_STACK_TRACE_MALLOC;
+ return asan_vec_realloc(ptr, size, &stack);
+}
# endif
-// TODO: Fix malloc/calloc interceptors to return 16-byte alignment with AIX on
-// PASE.
INTERCEPTOR(void*, malloc, uptr size) {
if (DlsymAlloc::Use())
- return DlsymAlloc::Allocate(size);
+ return DlsymAlloc::Allocate(size, SANITIZER_AIX ? 16 : kWordSize);
GET_STACK_TRACE_MALLOC;
+#if SANITIZER_AIX
+ return asan_vec_malloc(size, &stack);
+#else
return asan_malloc(size, &stack);
+#endif
}
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
if (DlsymAlloc::Use())
- return DlsymAlloc::Callocate(nmemb, size);
+ return DlsymAlloc::Callocate(nmemb, size, SANITIZER_AIX ? 16 : kWordSize);
GET_STACK_TRACE_MALLOC;
+#if SANITIZER_AIX
+ return asan_vec_calloc(nmemb, size, &stack);
+#else
return asan_calloc(nmemb, size, &stack);
+#endif
}
-// TODO: AIX needs a method to ensure 16-byte alignment if the incoming
-// pointer was allocated with a 16-byte alignment requirement (or perhaps
-// merely if it happens to have 16-byte alignment).
INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
- return DlsymAlloc::Realloc(ptr, size);
+ return DlsymAlloc::Realloc(ptr, size, SANITIZER_AIX ? 16 : kWordSize);
GET_STACK_TRACE_MALLOC;
+#if SANITIZER_AIX
+ return asan_vec_realloc(ptr, size, &stack);
+#else
return asan_realloc(ptr, size, &stack);
+#endif
}
#if SANITIZER_INTERCEPT_REALLOCARRAY
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
index 35445b9aece50..f2d0141425717 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
@@ -53,9 +53,9 @@ struct DlSymAllocator {
InternalFree(ptr);
}
- static void *Realloc(void *ptr, uptr new_size) {
+ static void *Realloc(void *ptr, uptr new_size, uptr align = kWordSize){
if (!ptr)
- return Allocate(new_size);
+ return Allocate(new_size, align);
CHECK(internal_allocator()->FromPrimary(ptr));
if (!new_size) {
Free(ptr);
@@ -63,7 +63,7 @@ struct DlSymAllocator {
}
uptr size = GetSize(ptr);
uptr memcpy_size = Min(new_size, size);
- void *new_ptr = Allocate(new_size);
+ void *new_ptr = Allocate(new_size, align);
if (new_ptr)
internal_memcpy(new_ptr, ptr, memcpy_size);
Free(ptr);
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
index ea59bdd58d1e8..37602da0871d7 100644
--- a/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
+++ b/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
@@ -1,16 +1,32 @@
-// Verify vec_malloc and vec_calloc interceptors
+// Verify vec_malloc, vec_calloc and vec_realloc interceptors, and that all
+// vec/plain allocators return 16-byte aligned memory on AIX.
// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: not %run %t vec_malloc 2>&1 | FileCheck %s --check-prefix=CHECK-MALLOC
-// RUN: not %run %t vec_calloc 2>&1 | FileCheck %s --check-prefix=CHECK-CALLOC
+// RUN: not %run %t vec_malloc 2>&1 | FileCheck %s --check-prefix=CHECK-MALLOC
+// RUN: not %run %t vec_calloc 2>&1 | FileCheck %s --check-prefix=CHECK-CALLOC
+// RUN: not %run %t vec_realloc 2>&1 | FileCheck %s --check-prefix=CHECK-REALLOC
+// RUN: %run %t align 2>&1 | FileCheck %s --check-prefix=CHECK-ALIGN
+#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+// Helper used by the "align" sub-test: prints OK/FAIL to stderr.
+static void check_align(const char *label, void *ptr) {
+ if (((size_t)ptr & 15) != 0) {
+ fprintf(stderr, "FAIL: %s ptr %p not 16-byte aligned\n", label, ptr);
+ exit(1);
+ }
+ fprintf(stderr, "OK: %s\n", label);
+}
+
int main(int argc, char **argv) {
if (argc != 2)
return 1;
+ // --- overflow detection (existing) ---
+
char *p;
if (strcmp(argv[1], "vec_malloc") == 0)
p = (char *)vec_malloc(10);
@@ -22,11 +38,71 @@ int main(int argc, char **argv) {
// CHECK-CALLOC: {{READ of size 1 at 0x.* thread T0}}
// CHECK-CALLOC: {{0x.* is located 0 bytes after 10-byte region}}
// CHECK-CALLOC: {{0x.* in .vec_calloc}}
- else
+ else if (strcmp(argv[1], "vec_realloc") == 0)
+ p = (char *)vec_realloc(NULL, 10);
+ // CHECK-REALLOC: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK-REALLOC: {{0x.* is located 0 bytes after 10-byte region}}
+ // On AIX 32-bit vec_realloc resolves to the realloc symbol; match both.
+ // CHECK-REALLOC: {{0x.* in .*realloc}}
+
+ // --- 16-byte alignment checks ---
+
+ else if (strcmp(argv[1], "align") == 0) {
+ void *vm = vec_malloc(32);
+ check_align("vec_malloc", vm);
+ // CHECK-ALIGN: OK: vec_malloc
+
+ void *vc = vec_calloc(1, 32);
+ check_align("vec_calloc", vc);
+ // CHECK-ALIGN: OK: vec_calloc
+
+ void *vr_null = vec_realloc(NULL, 32);
+ check_align("vec_realloc(NULL)", vr_null);
+ // CHECK-ALIGN: OK: vec_realloc(NULL)
+
+ void *vr_vm = vec_realloc(vm, 64);
+ check_align("vec_realloc(vec_malloc_ptr)", vr_vm);
+ // CHECK-ALIGN: OK: vec_realloc(vec_malloc_ptr)
+
+ void *vr_vc = vec_realloc(vc, 64);
+ check_align("vec_realloc(vec_calloc_ptr)", vr_vc);
+ // CHECK-ALIGN: OK: vec_realloc(vec_calloc_ptr)
+
+ void *m = malloc(32);
+ check_align("malloc", m);
+ // CHECK-ALIGN: OK: malloc
+
+ void *c = calloc(1, 32);
+ check_align("calloc", c);
+ // CHECK-ALIGN: OK: calloc
+
+ void *re_null = realloc(NULL, 32);
+ check_align("realloc(NULL)", re_null);
+ // CHECK-ALIGN: OK: realloc(NULL)
+
+ void *re_m = realloc(m, 64);
+ check_align("realloc(malloc_ptr)", re_m);
+ // CHECK-ALIGN: OK: realloc(malloc_ptr)
+
+ void *vm2 = vec_malloc(32);
+ void *re_vm = realloc(vm2, 64);
+ check_align("realloc(vec_malloc_ptr)", re_vm);
+ // CHECK-ALIGN: OK: realloc(vec_malloc_ptr)
+
+ free(vr_null);
+ free(vr_vm);
+ free(vr_vc);
+ free(c);
+ free(re_null);
+ free(re_m);
+ free(re_vm);
+ return 0;
+ } else {
return 1;
+ }
char x = p[10];
free(p);
return x;
-}
+}
\ No newline at end of file
>From c01417a8c6ff3a457d222ef069eced7c0e864c97 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Fri, 6 Mar 2026 13:53:35 +0530
Subject: [PATCH 02/11] rename and update test
---
.../TestCases/AIX/{vec_malloc_calloc.cpp => vec_alloc_align.cpp} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename compiler-rt/test/asan/TestCases/AIX/{vec_malloc_calloc.cpp => vec_alloc_align.cpp} (100%)
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
similarity index 100%
rename from compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
rename to compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
>From deeb8b1864c7d0d483c544739ab8ca085bfec039 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Fri, 6 Mar 2026 14:04:35 +0530
Subject: [PATCH 03/11] fix formatting
---
compiler-rt/lib/asan/asan_allocator.cpp | 7 +++--
compiler-rt/lib/asan/asan_malloc_linux.cpp | 30 +++++++++----------
.../sanitizer_allocator_dlsym.h | 4 +--
3 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index cce89adb1539e..b66ad90be97c0 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -783,12 +783,12 @@ struct Allocator {
AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.reallocs++;
thread_stats.realloced += new_size;
-
+
// Preserve the original allocation's alignment
uptr orig_align = ComputeUserAlignment(m->user_requested_alignment_log);
if (orig_align < 8)
orig_align = 8;
- void *new_ptr = Allocate(new_size, orig_align, stack, FROM_MALLOC, true);
+ void* new_ptr = Allocate(new_size, orig_align, stack, FROM_MALLOC, true);
if (new_ptr) {
u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
if (chunk_state != CHUNK_ALLOCATED)
@@ -1066,7 +1066,8 @@ void* asan_vec_calloc(uptr nmemb, uptr size, BufferedStackTrace* stack) {
void* asan_vec_realloc(void* p, uptr size, BufferedStackTrace* stack) {
if (!p)
- return SetErrnoOnNull(instance.Allocate(size, 16, stack, FROM_MALLOC, true));
+ return SetErrnoOnNull(
+ instance.Allocate(size, 16, stack, FROM_MALLOC, true));
return asan_realloc(p, size, stack);
}
#endif
diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp
index 8c5b19dd3b9da..3673279bb7a23 100644
--- a/compiler-rt/lib/asan/asan_malloc_linux.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp
@@ -54,12 +54,12 @@ INTERCEPTOR(void, free, void *ptr) {
#if SANITIZER_INTERCEPT_CFREE
INTERCEPTOR(void*, __linux_vec_malloc, uptr size) {
- if (DlsymAlloc::Use())
- return DlsymAlloc::Allocate(size, 16);
- AsanInitFromRtl();
- GET_STACK_TRACE_MALLOC;
- return asan_vec_malloc(size, &stack);
- }
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size, 16);
+ AsanInitFromRtl();
+ GET_STACK_TRACE_MALLOC;
+ return asan_vec_malloc(size, &stack);
+}
INTERCEPTOR(void*, __linux_vec_calloc, uptr nmemb, uptr size) {
if (DlsymAlloc::Use())
@@ -114,33 +114,33 @@ INTERCEPTOR(void*, malloc, uptr size) {
if (DlsymAlloc::Use())
return DlsymAlloc::Allocate(size, SANITIZER_AIX ? 16 : kWordSize);
GET_STACK_TRACE_MALLOC;
-#if SANITIZER_AIX
+# if SANITIZER_AIX
return asan_vec_malloc(size, &stack);
-#else
+# else
return asan_malloc(size, &stack);
-#endif
+# endif
}
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
if (DlsymAlloc::Use())
return DlsymAlloc::Callocate(nmemb, size, SANITIZER_AIX ? 16 : kWordSize);
GET_STACK_TRACE_MALLOC;
-#if SANITIZER_AIX
+# if SANITIZER_AIX
return asan_vec_calloc(nmemb, size, &stack);
-#else
+# else
return asan_calloc(nmemb, size, &stack);
-#endif
+# endif
}
INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
return DlsymAlloc::Realloc(ptr, size, SANITIZER_AIX ? 16 : kWordSize);
GET_STACK_TRACE_MALLOC;
-#if SANITIZER_AIX
+# if SANITIZER_AIX
return asan_vec_realloc(ptr, size, &stack);
-#else
+# else
return asan_realloc(ptr, size, &stack);
-#endif
+# endif
}
#if SANITIZER_INTERCEPT_REALLOCARRAY
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
index f2d0141425717..4c34be9c12334 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
@@ -53,7 +53,7 @@ struct DlSymAllocator {
InternalFree(ptr);
}
- static void *Realloc(void *ptr, uptr new_size, uptr align = kWordSize){
+ static void* Realloc(void *ptr, uptr new_size, uptr align = kWordSize) {
if (!ptr)
return Allocate(new_size, align);
CHECK(internal_allocator()->FromPrimary(ptr));
@@ -63,7 +63,7 @@ struct DlSymAllocator {
}
uptr size = GetSize(ptr);
uptr memcpy_size = Min(new_size, size);
- void *new_ptr = Allocate(new_size, align);
+ void* new_ptr = Allocate(new_size, align);
if (new_ptr)
internal_memcpy(new_ptr, ptr, memcpy_size);
Free(ptr);
>From 9dda7dd430f71bcdf24251967ee53614dd1ece85 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Fri, 6 Mar 2026 14:44:33 +0530
Subject: [PATCH 04/11] fix build failure
---
compiler-rt/lib/asan/asan_malloc_linux.cpp | 38 ++++++++++++-------
.../sanitizer_allocator_dlsym.h | 2 +-
2 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp
index 3673279bb7a23..b81e52f2152f5 100644
--- a/compiler-rt/lib/asan/asan_malloc_linux.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp
@@ -53,6 +53,15 @@ INTERCEPTOR(void, free, void *ptr) {
}
#if SANITIZER_INTERCEPT_CFREE
+INTERCEPTOR(void, cfree, void *ptr) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_STACK_TRACE_FREE;
+ asan_free(ptr, &stack);
+}
+#endif // SANITIZER_INTERCEPT_CFREE
+
+# if SANITIZER_AIX
INTERCEPTOR(void*, __linux_vec_malloc, uptr size) {
if (DlsymAlloc::Use())
return DlsymAlloc::Allocate(size, 16);
@@ -76,15 +85,6 @@ INTERCEPTOR(void*, __linux_realloc, void* ptr, uptr size) {
return asan_vec_realloc(ptr, size, &stack);
}
-INTERCEPTOR(void, cfree, void *ptr) {
- if (DlsymAlloc::PointerIsMine(ptr))
- return DlsymAlloc::Free(ptr);
- GET_STACK_TRACE_FREE;
- asan_free(ptr, &stack);
-}
-#endif // SANITIZER_INTERCEPT_CFREE
-
-# if SANITIZER_AIX
// Unlike malloc, vec_malloc must return memory aligned to 16 bytes.
INTERCEPTOR(void*, vec_malloc, uptr size) {
if (DlsymAlloc::Use())
@@ -112,7 +112,11 @@ INTERCEPTOR(void*, vec_realloc, void* ptr, uptr size) {
INTERCEPTOR(void*, malloc, uptr size) {
if (DlsymAlloc::Use())
- return DlsymAlloc::Allocate(size, SANITIZER_AIX ? 16 : kWordSize);
+# if SANITIZER_AIX
+ return DlsymAlloc::Allocate(size, 16);
+# else
+ return DlsymAlloc::Allocate(size, kWordSize);
+# endif
GET_STACK_TRACE_MALLOC;
# if SANITIZER_AIX
return asan_vec_malloc(size, &stack);
@@ -123,9 +127,13 @@ INTERCEPTOR(void*, malloc, uptr size) {
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
if (DlsymAlloc::Use())
- return DlsymAlloc::Callocate(nmemb, size, SANITIZER_AIX ? 16 : kWordSize);
+# if SANITIZER_AIX
+ return DlsymAlloc::Callocate(nmemb, size, 16);
+# else
+ return DlsymAlloc::Callocate(nmemb, size, kWordSize);
+# endif
GET_STACK_TRACE_MALLOC;
-# if SANITIZER_AIX
+# if SANITIZER_AIX
return asan_vec_calloc(nmemb, size, &stack);
# else
return asan_calloc(nmemb, size, &stack);
@@ -134,7 +142,11 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
- return DlsymAlloc::Realloc(ptr, size, SANITIZER_AIX ? 16 : kWordSize);
+# if SANITIZER_AIX
+ return DlsymAlloc::Realloc(ptr, size, 16);
+# else
+ return DlsymAlloc::Realloc(ptr, size, kWordSize);
+# endif
GET_STACK_TRACE_MALLOC;
# if SANITIZER_AIX
return asan_vec_realloc(ptr, size, &stack);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
index 4c34be9c12334..2e8e2b12156aa 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
@@ -53,7 +53,7 @@ struct DlSymAllocator {
InternalFree(ptr);
}
- static void* Realloc(void *ptr, uptr new_size, uptr align = kWordSize) {
+ static void* Realloc(void* ptr, uptr new_size, uptr align = kWordSize) {
if (!ptr)
return Allocate(new_size, align);
CHECK(internal_allocator()->FromPrimary(ptr));
>From ee8662eef0b28c5bc4542f842badc4fbcd977b66 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Tue, 31 Mar 2026 12:37:54 +0530
Subject: [PATCH 05/11] Fix review comments to add perturb
---
compiler-rt/lib/asan/asan_allocator.cpp | 4 +---
compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp | 8 ++++++++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index b66ad90be97c0..cf35c7115dcbd 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -784,10 +784,8 @@ struct Allocator {
thread_stats.reallocs++;
thread_stats.realloced += new_size;
- // Preserve the original allocation's alignment
+ // Preserve the original allocation's alignment.
uptr orig_align = ComputeUserAlignment(m->user_requested_alignment_log);
- if (orig_align < 8)
- orig_align = 8;
void* new_ptr = Allocate(new_size, orig_align, stack, FROM_MALLOC, true);
if (new_ptr) {
u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
index 37602da0871d7..1ed414d25ec36 100644
--- a/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
+++ b/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
@@ -48,6 +48,12 @@ int main(int argc, char **argv) {
// --- 16-byte alignment checks ---
else if (strcmp(argv[1], "align") == 0) {
+ // Perturb the heap with small odd-sized allocations to advance the
+ // allocator's per-size-class pointer by a non-16-byte amount.
+ void *perturb[8];
+ for (int i = 0; i < 8; i++)
+ perturb[i] = malloc(i + 1);
+
void *vm = vec_malloc(32);
check_align("vec_malloc", vm);
// CHECK-ALIGN: OK: vec_malloc
@@ -96,6 +102,8 @@ int main(int argc, char **argv) {
free(re_null);
free(re_m);
free(re_vm);
+ for (int i = 0; i < 8; i++)
+ free(perturb[i]);
return 0;
} else {
return 1;
>From 4e05adc77f8b4de684f4046b8162ffe4c7fc99ae Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Tue, 7 Apr 2026 01:52:07 +0530
Subject: [PATCH 06/11] Address review comment and add additional comments
about test
---
.../lib/asan/AIX/asan.link_with_main_exec.txt | 12 +-
compiler-rt/lib/asan/asan_malloc_linux.cpp | 10 --
.../asan/TestCases/AIX/vec_alloc_align.cpp | 161 +++++++-----------
.../asan/TestCases/AIX/vec_malloc_calloc.cpp | 32 ++++
4 files changed, 98 insertions(+), 117 deletions(-)
create mode 100644 compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
diff --git a/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt b/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
index 4bc85e3e50256..0e02267803fbd 100644
--- a/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
+++ b/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
@@ -113,9 +113,9 @@ __asan_poison_stack_memory
__asan_unpoison_stack_memory
__asan_option_detect_stack_use_after_return
__asan_shadow_memory_dynamic_address
-__interceptor_vec_calloc
-__interceptor_vec_malloc
-__interceptor_vec_realloc
-vec_calloc
-vec_malloc
-vec_realloc
+__interceptor___linux_vec_malloc
+__linux_vec_malloc
+__interceptor___linux_vec_calloc
+__linux_vec_calloc
+__interceptor___linux_realloc
+__linux_realloc
diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp
index ba32d905201a2..6a40ff337f7be 100644
--- a/compiler-rt/lib/asan/asan_malloc_linux.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp
@@ -87,7 +87,6 @@ INTERCEPTOR(void, free_aligned_sized, void* ptr, uptr alignment, uptr size) {
INTERCEPTOR(void*, __linux_vec_malloc, uptr size) {
if (DlsymAlloc::Use())
return DlsymAlloc::Allocate(size, 16);
- AsanInitFromRtl();
GET_STACK_TRACE_MALLOC;
return asan_vec_malloc(size, &stack);
}
@@ -95,7 +94,6 @@ INTERCEPTOR(void*, __linux_vec_malloc, uptr size) {
INTERCEPTOR(void*, __linux_vec_calloc, uptr nmemb, uptr size) {
if (DlsymAlloc::Use())
return DlsymAlloc::Callocate(nmemb, size, 16);
- AsanInitFromRtl();
GET_STACK_TRACE_MALLOC;
return asan_vec_calloc(nmemb, size, &stack);
}
@@ -122,14 +120,6 @@ INTERCEPTOR(void*, vec_calloc, uptr nmemb, uptr size) {
GET_STACK_TRACE_MALLOC;
return asan_vec_calloc(nmemb, size, &stack);
}
-
-// Unlike realloc, vec_realloc must return memory aligned to 16 bytes.
-INTERCEPTOR(void*, vec_realloc, void* ptr, uptr size) {
- if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
- return DlsymAlloc::Realloc(ptr, size, 16);
- GET_STACK_TRACE_MALLOC;
- return asan_vec_realloc(ptr, size, &stack);
-}
# endif
INTERCEPTOR(void*, malloc, uptr size) {
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
index 1ed414d25ec36..88747753e747a 100644
--- a/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
+++ b/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
@@ -1,18 +1,19 @@
-// Verify vec_malloc, vec_calloc and vec_realloc interceptors, and that all
-// vec/plain allocators return 16-byte aligned memory on AIX.
+// Verify that vec_malloc, vec_calloc, vec_realloc, and the plain allocators
+// all return 16-byte aligned memory on AIX.
+//
+// Note: 16-byte alignment is structurally guaranteed by DefaultSizeClassMap
+// (kMinSizeLog=4, so every size class is a multiple of 16) combined with the
+// minimum 16-byte redzone. This test therefore documents/verifies the AIX ABI
+// guarantee end-to-end rather than catching regressions in the explicit
+// alignment=16 argument passed by asan_vec_malloc/asan_vec_calloc.
// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: not %run %t vec_malloc 2>&1 | FileCheck %s --check-prefix=CHECK-MALLOC
-// RUN: not %run %t vec_calloc 2>&1 | FileCheck %s --check-prefix=CHECK-CALLOC
-// RUN: not %run %t vec_realloc 2>&1 | FileCheck %s --check-prefix=CHECK-REALLOC
-// RUN: %run %t align 2>&1 | FileCheck %s --check-prefix=CHECK-ALIGN
+// RUN: %run %t 2>&1 | FileCheck %s
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-// Helper used by the "align" sub-test: prints OK/FAIL to stderr.
static void check_align(const char *label, void *ptr) {
if (((size_t)ptr & 15) != 0) {
fprintf(stderr, "FAIL: %s ptr %p not 16-byte aligned\n", label, ptr);
@@ -21,96 +22,54 @@ static void check_align(const char *label, void *ptr) {
fprintf(stderr, "OK: %s\n", label);
}
-int main(int argc, char **argv) {
- if (argc != 2)
- return 1;
-
- // --- overflow detection (existing) ---
-
- char *p;
- if (strcmp(argv[1], "vec_malloc") == 0)
- p = (char *)vec_malloc(10);
- // CHECK-MALLOC: {{READ of size 1 at 0x.* thread T0}}
- // CHECK-MALLOC: {{0x.* is located 0 bytes after 10-byte region}}
- // CHECK-MALLOC: {{0x.* in .vec_malloc}}
- else if (strcmp(argv[1], "vec_calloc") == 0)
- p = (char *)vec_calloc(10, 1);
- // CHECK-CALLOC: {{READ of size 1 at 0x.* thread T0}}
- // CHECK-CALLOC: {{0x.* is located 0 bytes after 10-byte region}}
- // CHECK-CALLOC: {{0x.* in .vec_calloc}}
- else if (strcmp(argv[1], "vec_realloc") == 0)
- p = (char *)vec_realloc(NULL, 10);
- // CHECK-REALLOC: {{READ of size 1 at 0x.* thread T0}}
- // CHECK-REALLOC: {{0x.* is located 0 bytes after 10-byte region}}
- // On AIX 32-bit vec_realloc resolves to the realloc symbol; match both.
- // CHECK-REALLOC: {{0x.* in .*realloc}}
-
- // --- 16-byte alignment checks ---
-
- else if (strcmp(argv[1], "align") == 0) {
- // Perturb the heap with small odd-sized allocations to advance the
- // allocator's per-size-class pointer by a non-16-byte amount.
- void *perturb[8];
- for (int i = 0; i < 8; i++)
- perturb[i] = malloc(i + 1);
-
- void *vm = vec_malloc(32);
- check_align("vec_malloc", vm);
- // CHECK-ALIGN: OK: vec_malloc
-
- void *vc = vec_calloc(1, 32);
- check_align("vec_calloc", vc);
- // CHECK-ALIGN: OK: vec_calloc
-
- void *vr_null = vec_realloc(NULL, 32);
- check_align("vec_realloc(NULL)", vr_null);
- // CHECK-ALIGN: OK: vec_realloc(NULL)
-
- void *vr_vm = vec_realloc(vm, 64);
- check_align("vec_realloc(vec_malloc_ptr)", vr_vm);
- // CHECK-ALIGN: OK: vec_realloc(vec_malloc_ptr)
-
- void *vr_vc = vec_realloc(vc, 64);
- check_align("vec_realloc(vec_calloc_ptr)", vr_vc);
- // CHECK-ALIGN: OK: vec_realloc(vec_calloc_ptr)
-
- void *m = malloc(32);
- check_align("malloc", m);
- // CHECK-ALIGN: OK: malloc
-
- void *c = calloc(1, 32);
- check_align("calloc", c);
- // CHECK-ALIGN: OK: calloc
-
- void *re_null = realloc(NULL, 32);
- check_align("realloc(NULL)", re_null);
- // CHECK-ALIGN: OK: realloc(NULL)
-
- void *re_m = realloc(m, 64);
- check_align("realloc(malloc_ptr)", re_m);
- // CHECK-ALIGN: OK: realloc(malloc_ptr)
-
- void *vm2 = vec_malloc(32);
- void *re_vm = realloc(vm2, 64);
- check_align("realloc(vec_malloc_ptr)", re_vm);
- // CHECK-ALIGN: OK: realloc(vec_malloc_ptr)
-
- free(vr_null);
- free(vr_vm);
- free(vr_vc);
- free(c);
- free(re_null);
- free(re_m);
- free(re_vm);
- for (int i = 0; i < 8; i++)
- free(perturb[i]);
- return 0;
- } else {
- return 1;
- }
-
- char x = p[10];
- free(p);
-
- return x;
-}
\ No newline at end of file
+int main() {
+ void *vm = vec_malloc(32);
+ check_align("vec_malloc", vm);
+ // CHECK: OK: vec_malloc
+
+ void *vc = vec_calloc(1, 32);
+ check_align("vec_calloc", vc);
+ // CHECK: OK: vec_calloc
+
+ void *vr_null = vec_realloc(NULL, 32);
+ check_align("vec_realloc(NULL)", vr_null);
+ // CHECK: OK: vec_realloc(NULL)
+
+ void *vr_vm = vec_realloc(vm, 64);
+ check_align("vec_realloc(vec_malloc_ptr)", vr_vm);
+ // CHECK: OK: vec_realloc(vec_malloc_ptr)
+
+ void *vr_vc = vec_realloc(vc, 64);
+ check_align("vec_realloc(vec_calloc_ptr)", vr_vc);
+ // CHECK: OK: vec_realloc(vec_calloc_ptr)
+
+ void *m = malloc(32);
+ check_align("malloc", m);
+ // CHECK: OK: malloc
+
+ void *c = calloc(1, 32);
+ check_align("calloc", c);
+ // CHECK: OK: calloc
+
+ void *re_null = realloc(NULL, 32);
+ check_align("realloc(NULL)", re_null);
+ // CHECK: OK: realloc(NULL)
+
+ void *re_m = realloc(m, 64);
+ check_align("realloc(malloc_ptr)", re_m);
+ // CHECK: OK: realloc(malloc_ptr)
+
+ void *vm2 = vec_malloc(32);
+ void *re_vm = realloc(vm2, 64);
+ check_align("realloc(vec_malloc_ptr)", re_vm);
+ // CHECK: OK: realloc(vec_malloc_ptr)
+
+ free(vr_null);
+ free(vr_vm);
+ free(vr_vc);
+ free(c);
+ free(re_null);
+ free(re_m);
+ free(re_vm);
+ return 0;
+}
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
new file mode 100644
index 0000000000000..ecdf17ef2c61f
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
@@ -0,0 +1,32 @@
+// Verify vec_malloc and vec_calloc interceptors on AIX.
+
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t vec_malloc 2>&1 | FileCheck %s --check-prefix=CHECK-MALLOC
+// RUN: not %run %t vec_calloc 2>&1 | FileCheck %s --check-prefix=CHECK-CALLOC
+
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+ if (argc != 2)
+ return 1;
+
+ char *p;
+ if (strcmp(argv[1], "vec_malloc") == 0)
+ p = (char *)vec_malloc(10);
+ // CHECK-MALLOC: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK-MALLOC: {{0x.* is located 0 bytes after 10-byte region}}
+ // CHECK-MALLOC: {{0x.* in .vec_malloc}}
+ else if (strcmp(argv[1], "vec_calloc") == 0)
+ p = (char *)vec_calloc(10, 1);
+ // CHECK-CALLOC: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK-CALLOC: {{0x.* is located 0 bytes after 10-byte region}}
+ // CHECK-CALLOC: {{0x.* in .vec_calloc}}
+ else
+ return 1;
+
+ char x = p[10];
+ free(p);
+
+ return x;
+}
>From 94e7d37e5be90fc1f0cb399551f89eca944fe763 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Tue, 7 Apr 2026 15:21:11 +0530
Subject: [PATCH 07/11] changes related to realloc alignment preservation
---
.../lib/asan/AIX/asan.link_with_main_exec.txt | 6 --
compiler-rt/lib/asan/asan_malloc_linux.cpp | 42 +----------
.../asan/TestCases/AIX/vec_alloc_align.cpp | 75 -------------------
.../test/asan/TestCases/AIX/vec_realloc.cpp | 36 +++++++++
4 files changed, 37 insertions(+), 122 deletions(-)
delete mode 100644 compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
create mode 100644 compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp
diff --git a/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt b/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
index 0e02267803fbd..5efc48c262369 100644
--- a/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
+++ b/compiler-rt/lib/asan/AIX/asan.link_with_main_exec.txt
@@ -113,9 +113,3 @@ __asan_poison_stack_memory
__asan_unpoison_stack_memory
__asan_option_detect_stack_use_after_return
__asan_shadow_memory_dynamic_address
-__interceptor___linux_vec_malloc
-__linux_vec_malloc
-__interceptor___linux_vec_calloc
-__linux_vec_calloc
-__interceptor___linux_realloc
-__linux_realloc
diff --git a/compiler-rt/lib/asan/asan_malloc_linux.cpp b/compiler-rt/lib/asan/asan_malloc_linux.cpp
index 6a40ff337f7be..a1835d760c042 100644
--- a/compiler-rt/lib/asan/asan_malloc_linux.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_linux.cpp
@@ -84,27 +84,6 @@ INTERCEPTOR(void, free_aligned_sized, void* ptr, uptr alignment, uptr size) {
# endif // SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
# if SANITIZER_AIX
-INTERCEPTOR(void*, __linux_vec_malloc, uptr size) {
- if (DlsymAlloc::Use())
- return DlsymAlloc::Allocate(size, 16);
- GET_STACK_TRACE_MALLOC;
- return asan_vec_malloc(size, &stack);
-}
-
-INTERCEPTOR(void*, __linux_vec_calloc, uptr nmemb, uptr size) {
- if (DlsymAlloc::Use())
- return DlsymAlloc::Callocate(nmemb, size, 16);
- GET_STACK_TRACE_MALLOC;
- return asan_vec_calloc(nmemb, size, &stack);
-}
-
-INTERCEPTOR(void*, __linux_realloc, void* ptr, uptr size) {
- if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
- return DlsymAlloc::Realloc(ptr, size, 16);
- GET_STACK_TRACE_MALLOC;
- return asan_vec_realloc(ptr, size, &stack);
-}
-
// Unlike malloc, vec_malloc must return memory aligned to 16 bytes.
INTERCEPTOR(void*, vec_malloc, uptr size) {
if (DlsymAlloc::Use())
@@ -124,41 +103,22 @@ INTERCEPTOR(void*, vec_calloc, uptr nmemb, uptr size) {
INTERCEPTOR(void*, malloc, uptr size) {
if (DlsymAlloc::Use())
-# if SANITIZER_AIX
- return DlsymAlloc::Allocate(size, 16);
-# else
return DlsymAlloc::Allocate(size, kWordSize);
-# endif
GET_STACK_TRACE_MALLOC;
-# if SANITIZER_AIX
- return asan_vec_malloc(size, &stack);
-# else
return asan_malloc(size, &stack);
-# endif
}
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
if (DlsymAlloc::Use())
-# if SANITIZER_AIX
- return DlsymAlloc::Callocate(nmemb, size, 16);
-# else
return DlsymAlloc::Callocate(nmemb, size, kWordSize);
-# endif
GET_STACK_TRACE_MALLOC;
-# if SANITIZER_AIX
- return asan_vec_calloc(nmemb, size, &stack);
-# else
return asan_calloc(nmemb, size, &stack);
-# endif
}
+// On AIX, route realloc through asan_vec_realloc.
INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
-# if SANITIZER_AIX
- return DlsymAlloc::Realloc(ptr, size, 16);
-# else
return DlsymAlloc::Realloc(ptr, size, kWordSize);
-# endif
GET_STACK_TRACE_MALLOC;
# if SANITIZER_AIX
return asan_vec_realloc(ptr, size, &stack);
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
deleted file mode 100644
index 88747753e747a..0000000000000
--- a/compiler-rt/test/asan/TestCases/AIX/vec_alloc_align.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-// Verify that vec_malloc, vec_calloc, vec_realloc, and the plain allocators
-// all return 16-byte aligned memory on AIX.
-//
-// Note: 16-byte alignment is structurally guaranteed by DefaultSizeClassMap
-// (kMinSizeLog=4, so every size class is a multiple of 16) combined with the
-// minimum 16-byte redzone. This test therefore documents/verifies the AIX ABI
-// guarantee end-to-end rather than catching regressions in the explicit
-// alignment=16 argument passed by asan_vec_malloc/asan_vec_calloc.
-
-// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static void check_align(const char *label, void *ptr) {
- if (((size_t)ptr & 15) != 0) {
- fprintf(stderr, "FAIL: %s ptr %p not 16-byte aligned\n", label, ptr);
- exit(1);
- }
- fprintf(stderr, "OK: %s\n", label);
-}
-
-int main() {
- void *vm = vec_malloc(32);
- check_align("vec_malloc", vm);
- // CHECK: OK: vec_malloc
-
- void *vc = vec_calloc(1, 32);
- check_align("vec_calloc", vc);
- // CHECK: OK: vec_calloc
-
- void *vr_null = vec_realloc(NULL, 32);
- check_align("vec_realloc(NULL)", vr_null);
- // CHECK: OK: vec_realloc(NULL)
-
- void *vr_vm = vec_realloc(vm, 64);
- check_align("vec_realloc(vec_malloc_ptr)", vr_vm);
- // CHECK: OK: vec_realloc(vec_malloc_ptr)
-
- void *vr_vc = vec_realloc(vc, 64);
- check_align("vec_realloc(vec_calloc_ptr)", vr_vc);
- // CHECK: OK: vec_realloc(vec_calloc_ptr)
-
- void *m = malloc(32);
- check_align("malloc", m);
- // CHECK: OK: malloc
-
- void *c = calloc(1, 32);
- check_align("calloc", c);
- // CHECK: OK: calloc
-
- void *re_null = realloc(NULL, 32);
- check_align("realloc(NULL)", re_null);
- // CHECK: OK: realloc(NULL)
-
- void *re_m = realloc(m, 64);
- check_align("realloc(malloc_ptr)", re_m);
- // CHECK: OK: realloc(malloc_ptr)
-
- void *vm2 = vec_malloc(32);
- void *re_vm = realloc(vm2, 64);
- check_align("realloc(vec_malloc_ptr)", re_vm);
- // CHECK: OK: realloc(vec_malloc_ptr)
-
- free(vr_null);
- free(vr_vm);
- free(vr_vc);
- free(c);
- free(re_null);
- free(re_m);
- free(re_vm);
- return 0;
-}
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp
new file mode 100644
index 0000000000000..f1d630f95c4d2
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp
@@ -0,0 +1,36 @@
+// Verify realloc correctly detects overflows.
+
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t realloc_vec_malloc 2>&1 | FileCheck %s --check-prefix=CHECK-REALLOC
+// RUN: not %run %t multiple_realloc 2>&1 | FileCheck %s --check-prefix=CHECK-MULTIPLE-REALLOC
+
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+ if (argc != 2)
+ return 1;
+
+ char *p;
+ if (strcmp(argv[1], "realloc_vec_malloc") == 0) {
+ char *orig = (char *)vec_malloc(5);
+ p = (char *)realloc(orig, 10);
+ }
+ // CHECK-REALLOC: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK-REALLOC: {{0x.* is located 0 bytes after 10-byte region}}
+ // CHECK-REALLOC: {{0x.* in .*realloc}}
+ else if (strcmp(argv[1], "multiple_realloc") == 0) {
+ char *orig = (char *)vec_malloc(5);
+ char *r1 = (char *)realloc(orig, 7);
+ p = (char *)realloc(r1, 10);
+ }
+ // CHECK-MULTIPLE-REALLOC: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK-MULTIPLE-REALLOC: {{0x.* is located 0 bytes after 10-byte region}}
+ // CHECK-MULTIPLE-REALLOC: {{0x.* in .*realloc}}
+ else
+ return 1;
+
+ char x = p[10];
+ free(p);
+ return x;
+}
>From dccd05164959ea74529f7057e63b7c387037b54d Mon Sep 17 00:00:00 2001
From: Midhunesh <midhuensh.p at ibm.com>
Date: Sun, 26 Apr 2026 14:57:06 -0400
Subject: [PATCH 08/11] fix formatting
---
compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp
index f1d630f95c4d2..2737cf632fa27 100644
--- a/compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp
+++ b/compiler-rt/test/asan/TestCases/AIX/vec_realloc.cpp
@@ -21,8 +21,8 @@ int main(int argc, char **argv) {
// CHECK-REALLOC: {{0x.* in .*realloc}}
else if (strcmp(argv[1], "multiple_realloc") == 0) {
char *orig = (char *)vec_malloc(5);
- char *r1 = (char *)realloc(orig, 7);
- p = (char *)realloc(r1, 10);
+ char *r1 = (char *)realloc(orig, 7);
+ p = (char *)realloc(r1, 10);
}
// CHECK-MULTIPLE-REALLOC: {{READ of size 1 at 0x.* thread T0}}
// CHECK-MULTIPLE-REALLOC: {{0x.* is located 0 bytes after 10-byte region}}
>From a20e37b01f5f3cd6ab765e2bd66ed6be0a85b9af Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Tue, 28 Apr 2026 09:07:45 +0530
Subject: [PATCH 09/11] Restore test vec_malloc_calloc.cpp
---
compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp b/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
index ecdf17ef2c61f..ea59bdd58d1e8 100644
--- a/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
+++ b/compiler-rt/test/asan/TestCases/AIX/vec_malloc_calloc.cpp
@@ -1,8 +1,8 @@
-// Verify vec_malloc and vec_calloc interceptors on AIX.
+// Verify vec_malloc and vec_calloc interceptors
// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: not %run %t vec_malloc 2>&1 | FileCheck %s --check-prefix=CHECK-MALLOC
-// RUN: not %run %t vec_calloc 2>&1 | FileCheck %s --check-prefix=CHECK-CALLOC
+// RUN: not %run %t vec_malloc 2>&1 | FileCheck %s --check-prefix=CHECK-MALLOC
+// RUN: not %run %t vec_calloc 2>&1 | FileCheck %s --check-prefix=CHECK-CALLOC
#include <stdlib.h>
#include <string.h>
>From 3316c88ceaa72141cfa64b71be9897066f862918 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhunesh.p at ibm.com>
Date: Mon, 4 May 2026 14:41:42 +0530
Subject: [PATCH 10/11] default alignment
---
compiler-rt/lib/asan/asan_allocator.cpp | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index 076498aaa62af..507608a6b5502 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -788,7 +788,8 @@ struct Allocator {
QuarantineChunk(m, ptr, stack);
}
- void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack) {
+ void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack,
+ uptr alignment = 8) {
CHECK(old_ptr && new_size);
uptr p = reinterpret_cast<uptr>(old_ptr);
uptr chunk_beg = p - kChunkHeaderSize;
@@ -798,9 +799,7 @@ struct Allocator {
thread_stats.reallocs++;
thread_stats.realloced += new_size;
- // Preserve the original allocation's alignment.
- uptr orig_align = ComputeUserAlignment(m->user_requested_alignment_log);
- void* new_ptr = Allocate(new_size, orig_align, stack, FROM_MALLOC, true);
+ void *new_ptr = Allocate(new_size, alignment, stack, FROM_MALLOC, true);
if (new_ptr) {
u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
if (chunk_state != CHUNK_ALLOCATED)
@@ -1089,7 +1088,14 @@ void* asan_vec_realloc(void* p, uptr size, BufferedStackTrace* stack) {
if (!p)
return SetErrnoOnNull(
instance.Allocate(size, 16, stack, FROM_MALLOC, true));
- return asan_realloc(p, size, stack);
+ if (size == 0) {
+ if (flags()->allocator_frees_and_returns_null_on_realloc_zero) {
+ instance.Deallocate(p, 0, 0, stack, FROM_MALLOC);
+ return nullptr;
+ }
+ size = 1;
+ }
+ return SetErrnoOnNull(instance.Reallocate(p, size, stack, 16));
}
#endif
>From 28b379a3c03e6fc95fc8384d691e956c75f55752 Mon Sep 17 00:00:00 2001
From: Midhunesh <midhuensh.p at ibm.com>
Date: Mon, 4 May 2026 05:20:16 -0400
Subject: [PATCH 11/11] fix formatting
---
compiler-rt/lib/asan/asan_allocator.cpp | 6 +++---
compiler-rt/lib/asan/asan_allocator.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index 507608a6b5502..962b403d40615 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -788,7 +788,7 @@ struct Allocator {
QuarantineChunk(m, ptr, stack);
}
- void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack,
+ void* Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack,
uptr alignment = 8) {
CHECK(old_ptr && new_size);
uptr p = reinterpret_cast<uptr>(old_ptr);
@@ -799,7 +799,7 @@ struct Allocator {
thread_stats.reallocs++;
thread_stats.realloced += new_size;
- void *new_ptr = Allocate(new_size, alignment, stack, FROM_MALLOC, true);
+ void* new_ptr = Allocate(new_size, alignment, stack, FROM_MALLOC, true);
if (new_ptr) {
u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
if (chunk_state != CHUNK_ALLOCATED)
@@ -1084,7 +1084,7 @@ void* asan_vec_calloc(uptr nmemb, uptr size, BufferedStackTrace* stack) {
return SetErrnoOnNull(instance.Calloc(nmemb, size, stack, 16));
}
-void* asan_vec_realloc(void* p, uptr size, BufferedStackTrace* stack) {
+void* asan_vec_realloc(void *p, uptr size, BufferedStackTrace *stack) {
if (!p)
return SetErrnoOnNull(
instance.Allocate(size, 16, stack, FROM_MALLOC, true));
diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h
index f4112662c3d03..9785ad18b749a 100644
--- a/compiler-rt/lib/asan/asan_allocator.h
+++ b/compiler-rt/lib/asan/asan_allocator.h
@@ -286,7 +286,7 @@ void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
#if SANITIZER_AIX
void* asan_vec_malloc(uptr size, BufferedStackTrace* stack);
void* asan_vec_calloc(uptr nmemb, uptr size, BufferedStackTrace* stack);
-void* asan_vec_realloc(void* p, uptr size, BufferedStackTrace* stack);
+void* asan_vec_realloc(void *p, uptr size, BufferedStackTrace *stack);
#endif
void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
void *asan_reallocarray(void *p, uptr nmemb, uptr size,
More information about the llvm-commits
mailing list