[compiler-rt] [asan] Detect dereferencing zero-alloc as heap buffer overflow (PR #155943)

Thurston Dang via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 28 16:14:21 PDT 2025


https://github.com/thurstond created https://github.com/llvm/llvm-project/pull/155943

When a zero-byte allocation is requested, ASan actually allocates 1-byte for compatibility. This change poisons that byte, to detect dereferences.

Also updates the test from #155933

>From 4b202488d73b3e0ae66040a1f26dd481980c8653 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 28 Aug 2025 22:55:42 +0000
Subject: [PATCH] [asan] Detect dereferencing zero-alloc as heap buffer
 overflow

When a zero-byte allocation is requested, ASan actually allocates 1-byte
for compatibility. This change poisons that byte, to detect dereferences.

Also updates the test from #155933
---
 compiler-rt/lib/asan/asan_allocator.cpp        | 6 ++++++
 compiler-rt/test/asan/TestCases/zero_alloc.cpp | 4 ----
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
index 9ebe4d08ec8c1..752ba9ab32c71 100644
--- a/compiler-rt/lib/asan/asan_allocator.cpp
+++ b/compiler-rt/lib/asan/asan_allocator.cpp
@@ -547,6 +547,7 @@ struct Allocator {
         ComputeUserRequestedAlignmentLog(alignment);
     if (alignment < min_alignment)
       alignment = min_alignment;
+    bool upgraded_from_zero = false;
     if (size == 0) {
       // We'd be happy to avoid allocating memory for zero-size requests, but
       // some programs/tests depend on this behavior and assume that malloc
@@ -555,6 +556,7 @@ struct Allocator {
       // consecutive "new" calls must be different even if the allocated size
       // is zero.
       size = 1;
+      upgraded_from_zero = true;
     }
     CHECK(IsPowerOfTwo(alignment));
     uptr rz_log = ComputeRZLog(size);
@@ -637,6 +639,10 @@ struct Allocator {
       *shadow = fl.poison_partial ? (size & (ASAN_SHADOW_GRANULARITY - 1)) : 0;
     }
 
+    if (upgraded_from_zero)
+      PoisonShadow(user_beg, ASAN_SHADOW_GRANULARITY,
+                   kAsanHeapLeftRedzoneMagic);
+
     AsanStats &thread_stats = GetCurrentThreadStats();
     thread_stats.mallocs++;
     thread_stats.malloced += size;
diff --git a/compiler-rt/test/asan/TestCases/zero_alloc.cpp b/compiler-rt/test/asan/TestCases/zero_alloc.cpp
index d25164a1e2eb9..e843a5a41f429 100644
--- a/compiler-rt/test/asan/TestCases/zero_alloc.cpp
+++ b/compiler-rt/test/asan/TestCases/zero_alloc.cpp
@@ -1,9 +1,5 @@
 // RUN: %clang_asan -Wno-alloc-size -fsanitize-recover=address %s -o %t && %env_asan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s
 
-// ASan doesn't catch this because internally it translates 0-byte allocations
-// into 1-byte
-// XFAIL: *
-
 #include <malloc.h>
 #include <stdio.h>
 



More information about the llvm-commits mailing list