[PATCH] malloc: Improve calloc [BZ #34582]

Yury Khrustalev yury.khrustalev@arm.com
Mon Sep 14 14:32:52 GMT 2026


On Fri, Sep 11, 2026 at 02:33:34PM +0000, Wilco Dijkstra wrote:
> 
> Add __libc_calloc_small for small calloc sizes to avoid the complex logic of 
> __libc_calloc2 which is unnecessary overhead for small blocks.  Cleanup
> __libc_calloc2 and only clear the size of the requested chunk (since we
> typically get the exact size after splitting off any tail).  This fixes
> BZ #34582.
> 
> Passes regress, OK for commit?

Does it make sense to add reproducers from BZ 34582 as testcases to the
tst-calloc test? With this patch some assertions in the reproducers still
fail (though it seems like the reproducers rely on UB).

A couple of comments below.

> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 5fc35a14f4ea95c27096ea45ca70d73048021d5f..3809fbb45f4a79215c84d1499bd35e83b69f11a9 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -1116,6 +1116,7 @@ checked_request2size (size_t req)
>  /* This is the size of the real usable data in the chunk.  Not valid for
>     dumped heap chunks.  */
>  #define memsize(p) (chunksize (p) - CHUNK_HDR_SZ + SIZE_SZ)
> +#define chunk2usable(n) (n - CHUNK_HDR_SZ + SIZE_SZ)

I think these two macros should depend on each other: I'd suggest to
define 'memsize(p)' as 'chunk2usable(chunksize(p))'.

Also, the name of the 'chunk2usable' macro should probably be something
like 'chunk_size_to_usable_size' since we have macros that begin with 'chunk2'
and work with pointers rather than sizes.

>
> ...
>
>  void *
> @@ -3406,17 +3410,19 @@ __libc_calloc (size_t n, size_t elem_size)
>  	{
>  	  if (tcache->entries[tc_idx] != NULL)
>  	    return clear_memory (tcache_get (tc_idx), tidx2usize (tc_idx));
> +
> +	  return __libc_calloc_small (chunk2usable (nb));
>  	}
>        else
>  	{
>  	  tc_idx = large_csize2tidx (nb);
>  	  void *mem = tcache_get_large (tc_idx, nb);
>  	  if (mem != NULL)
> -	    return memset (mem, 0, memsize (mem2chunk (mem)));
> +	    return memset (mem, 0, chunk2usable (nb));
>  	}
>      }
>  #endif
> -  return __libc_calloc2 (bytes);
> +  return __libc_calloc2 (chunk2usable (nb));

Here variable 'nb' is undeclared if USE_TCACHE is false (use of variable
outside #if USE_TCACHE ... #endif).

Also, I think __libc_calloc2's argument name should be 'usable[_size]',
same as __libc_calloc_small.

Thanks,
Yury



More information about the Libc-alpha mailing list