git: a3fbf20c0558 - main - Merge commit a5fa4dba6e2e from llvm-project (by PiJoules):

From: Dimitry Andric <dim_at_FreeBSD.org>
Date: Sat, 10 Oct 2026 22:44:56 UTC
The branch main has been updated by dim:

URL: https://cgit.FreeBSD.org/src/commit/?id=a3fbf20c0558ee3c2b88adc0c944e66d074cab7b

commit a3fbf20c0558ee3c2b88adc0c944e66d074cab7b
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2026-10-10 21:47:47 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2026-10-10 22:44:17 +0000

    Merge commit a5fa4dba6e2e from llvm-project (by PiJoules):
    
      [compiler-rt] Add interceptors for free_[aligned_]sized for asan+hwasan (#189109)
    
    This avoids a jemalloc assertion when running sanitized applications
    against glib, which uses free_sized(3).
    
    PR:             298943
    MFC after:      1 week
---
 .../compiler-rt/lib/asan/asan_allocator.cpp        | 13 +++++++++
 .../compiler-rt/lib/asan/asan_allocator.h          |  3 ++
 .../compiler-rt/lib/asan/asan_malloc_linux.cpp     | 22 +++++++++++++++
 .../lib/hwasan/hwasan_allocation_functions.cpp     | 32 ++++++++++++++++++++++
 4 files changed, 70 insertions(+)

diff --git a/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.cpp b/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.cpp
index 9ebe4d08ec8c..377c6a77f4d0 100644
--- a/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.cpp
@@ -1011,6 +1011,19 @@ void asan_free(void *ptr, BufferedStackTrace *stack) {
   instance.Deallocate(ptr, 0, 0, stack, FROM_MALLOC);
 }
 
+// TODO: Both the size and alignment arguments of Allocator::Deallocate
+// are actually unused when the alloc type is FROM_MALLOC. We should look
+// into why this is the case, but for now passing the arguments like so
+// is the correct thing to do.
+void asan_free_sized(void* ptr, uptr size, BufferedStackTrace* stack) {
+  instance.Deallocate(ptr, size, /*delete_alignment=*/0, stack, FROM_MALLOC);
+}
+
+void asan_free_aligned_sized(void* ptr, uptr alignment, uptr size,
+                             BufferedStackTrace* stack) {
+  instance.Deallocate(ptr, size, alignment, stack, FROM_MALLOC);
+}
+
 void *asan_malloc(uptr size, BufferedStackTrace *stack) {
   return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC, true));
 }
diff --git a/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.h b/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.h
index fdf456473fb0..4957c61243fb 100644
--- a/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.h
+++ b/contrib/llvm-project/compiler-rt/lib/asan/asan_allocator.h
@@ -272,6 +272,9 @@ struct AsanThreadLocalMallocStorage {
 
 void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack);
 void asan_free(void *ptr, BufferedStackTrace *stack);
+void asan_free_sized(void* ptr, uptr size, BufferedStackTrace* stack);
+void asan_free_aligned_sized(void* ptr, uptr alignment, uptr size,
+                             BufferedStackTrace* stack);
 
 void *asan_malloc(uptr size, BufferedStackTrace *stack);
 void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
diff --git a/contrib/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp b/contrib/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp
index add57318785b..ae1bb7617bcc 100644
--- a/contrib/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp
+++ b/contrib/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp
@@ -61,6 +61,28 @@ INTERCEPTOR(void, cfree, void *ptr) {
 }
 #endif // SANITIZER_INTERCEPT_CFREE
 
+#  if SANITIZER_INTERCEPT_FREE_SIZED
+INTERCEPTOR(void, free_sized, void* ptr, uptr size) {
+  if (UNLIKELY(!ptr))
+    return;
+  if (DlsymAlloc::PointerIsMine(ptr))
+    return DlsymAlloc::Free(ptr);
+  GET_STACK_TRACE_FREE;
+  asan_free_sized(ptr, size, &stack);
+}
+#  endif  // SANITIZER_INTERCEPT_FREE_SIZED
+
+#  if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+INTERCEPTOR(void, free_aligned_sized, void* ptr, uptr alignment, uptr size) {
+  if (UNLIKELY(!ptr))
+    return;
+  if (DlsymAlloc::PointerIsMine(ptr))
+    return DlsymAlloc::Free(ptr);
+  GET_STACK_TRACE_FREE;
+  asan_free_aligned_sized(ptr, alignment, size, &stack);
+}
+#  endif  // SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+
 INTERCEPTOR(void*, malloc, uptr size) {
   if (DlsymAlloc::Use())
     return DlsymAlloc::Allocate(size);
diff --git a/contrib/llvm-project/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp b/contrib/llvm-project/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp
index 25ca0a3b0b68..ee2794f4cfbf 100644
--- a/contrib/llvm-project/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp
+++ b/contrib/llvm-project/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp
@@ -17,6 +17,7 @@
 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
 #include "sanitizer_common/sanitizer_allocator_interface.h"
 #include "sanitizer_common/sanitizer_mallinfo.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
 
 using namespace __hwasan;
 
@@ -96,6 +97,30 @@ void __sanitizer_cfree(void *ptr) {
   hwasan_free(ptr, &stack);
 }
 
+#if SANITIZER_INTERCEPT_FREE_SIZED
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_free_sized(void* ptr, uptr size) {
+  if (!ptr)
+    return;
+  if (DlsymAlloc::PointerIsMine(ptr))
+    return DlsymAlloc::Free(ptr);
+  GET_MALLOC_STACK_TRACE;
+  hwasan_free(ptr, &stack);
+}
+#endif
+
+#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_free_aligned_sized(void* ptr, uptr alignment, uptr size) {
+  if (!ptr)
+    return;
+  if (DlsymAlloc::PointerIsMine(ptr))
+    return DlsymAlloc::Free(ptr);
+  GET_MALLOC_STACK_TRACE;
+  hwasan_free(ptr, &stack);
+}
+#endif
+
 SANITIZER_INTERFACE_ATTRIBUTE
 uptr __sanitizer_malloc_usable_size(const void *ptr) {
   return __sanitizer_get_allocated_size(ptr);
@@ -170,6 +195,13 @@ INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size);
 INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size);
 INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size);
 INTERCEPTOR_ALIAS(void, free, void *ptr);
+#  if SANITIZER_INTERCEPT_FREE_SIZED
+INTERCEPTOR_ALIAS(void, free_sized, void* ptr, SIZE_T size);
+#  endif
+#  if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
+INTERCEPTOR_ALIAS(void, free_aligned_sized, void* ptr, SIZE_T alignment,
+                  SIZE_T size);
+#  endif
 INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr);
 INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size);
 INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size);