[patch v1] malloc: add malloc_zero_aborts tunable

DJ Delorie dj@redhat.com
Thu Feb 12 19:15:02 GMT 2026


Given the recent discussions on this topic, I thought it would be
useful (and/or fun) to give users a way to turn "implementation
defined" into "will crash immediately."  I included realloc but could
make that separate.  I'll do manual updates and figure out tail
recursion if we decide we even want this ;-)

    malloc: add malloc_zero_aborts tunable
    
    If set (ex: GLIBC_TUNABLES=glibc.malloc.malloc_zero_aborts=1)
    then any call of malloc(0) or realloc(ptr,0) will immediately
    abort.

diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index 040a544c0e..20c0659ad0 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -79,6 +79,10 @@ glibc {
       type: SIZE_T
       minval: 0
     }
+    malloc_zero_aborts {
+      type: SIZE_T
+      minval: 0
+    }
   }
 
   rtld {
diff --git a/malloc/arena.c b/malloc/arena.c
index cabeb0d8ce..cddc0951ec 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -240,6 +240,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_max, size_t)
 TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t)
 #endif
 TUNABLE_CALLBACK_FNDECL (set_hugetlb, size_t)
+TUNABLE_CALLBACK_FNDECL (set_malloc_zero_aborts, size_t)
 
 #if USE_TCACHE
 static void tcache_key_initialize (void);
@@ -291,6 +292,7 @@ __ptmalloc_init (void)
   TUNABLE_GET (tcache_count, size_t, TUNABLE_CALLBACK (set_tcache_count));
 # endif
   TUNABLE_GET (hugetlb, size_t, TUNABLE_CALLBACK (set_hugetlb));
+  TUNABLE_GET (malloc_zero_aborts, size_t, TUNABLE_CALLBACK (set_malloc_zero_aborts));
 
   if (mp_.hp_pagesize > 0 && mp_.hp_pagesize <= heap_max_size ())
     {
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 0ff016e549..431c770325 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1798,6 +1798,8 @@ struct malloc_par
   /* Maximum number of chunks in each bucket.  */
   size_t tcache_count;
 #endif
+
+  size_t malloc_zero_aborts;
 };
 
 /* There are several instances of this struct ("arenas") in this
@@ -1823,6 +1825,7 @@ static struct malloc_par mp_ =
   .trim_threshold = DEFAULT_TRIM_THRESHOLD,
 #define NARENAS_FROM_NCORES(n) ((n) * (sizeof (long) == 4 ? 2 : 8))
   .arena_test = NARENAS_FROM_NCORES (1),
+  .malloc_zero_aborts = 0,
   .thp_mode = malloc_thp_mode_not_supported
 #if USE_TCACHE
   ,
@@ -3295,6 +3298,9 @@ __libc_malloc2 (size_t bytes)
 void *
 __libc_malloc (size_t bytes)
 {
+  if (bytes == 0 && mp_.malloc_zero_aborts)
+    abort();
+
 #if USE_TCACHE
   size_t nb = checked_request2size (bytes);
 
@@ -3401,6 +3407,9 @@ __libc_realloc (void *oldmem, size_t bytes)
   if (oldmem == NULL)
     return __libc_malloc (bytes);
 
+  if (bytes == 0 && mp_.malloc_zero_aborts)
+    abort();
+
 #if REALLOC_ZERO_BYTES_FREES
   if (bytes == 0)
     {
@@ -5078,6 +5087,13 @@ do_set_hugetlb (size_t value)
   return 0;
 }
 
+static __always_inline int
+do_set_malloc_zero_aborts (size_t value)
+{
+  mp_.malloc_zero_aborts = value;
+  return 0;
+}
+
 int
 __libc_mallopt (int param_number, int value)
 {



More information about the Libc-alpha mailing list