[PATCH v5 5/7] malloc: mangle tcache entries pointers

Cupertino Miranda cupertino.miranda@oracle.com
Fri Mar 21 12:01:00 GMT 2025


tcache entries are store in mangled linked lists of chunks.
However the initial pointer stored in tcache->entries[index] is stored
unmangled.
Due to this difference, tcache_get_n contains 2 extra conditions to
disambiguate between the original pointer from tcache entries, or the
next pointer within the content of the chunk.

This patch slightly improves tcache_get_n by removing the condition
related to refering to the first pointer by also mangling the pointers
stored in tcache->entries.
The mangling of the entries should also happen on tcache_init as NULL
pointers are also mangled.
---
 malloc/malloc.c | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/malloc/malloc.c b/malloc/malloc.c
index ea2da0c9fc..c942e3f8d1 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3164,8 +3164,8 @@ tcache_put (mchunkptr chunk, size_t tc_idx)
      detect a double free.  */
   e->key = tcache_key;
 
-  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
-  tcache->entries[tc_idx] = e;
+  e->next = PROTECT_PTR (&e->next, REVEAL_PTR (tcache->entries[tc_idx]));
+  tcache->entries[tc_idx] = PROTECT_PTR (&(tcache->entries[tc_idx]), e);
   ++(tcache->counts[tc_idx]);
 }
 
@@ -3175,19 +3175,12 @@ tcache_put (mchunkptr chunk, size_t tc_idx)
 static __always_inline void *
 tcache_get_n (size_t tc_idx, tcache_entry **ep)
 {
-  tcache_entry *e;
-  if (ep == &(tcache->entries[tc_idx]))
-    e = *ep;
-  else
-    e = REVEAL_PTR (*ep);
+  tcache_entry *e = REVEAL_PTR (*ep);
 
   if (__glibc_unlikely (!aligned_OK (e)))
     malloc_printerr ("malloc(): unaligned tcache chunk detected");
 
-  if (ep == &(tcache->entries[tc_idx]))
-      *ep = REVEAL_PTR (e->next);
-  else
-    *ep = PROTECT_PTR (ep, REVEAL_PTR (e->next));
+  *ep = PROTECT_PTR (ep, REVEAL_PTR (e->next));
 
   --(tcache->counts[tc_idx]);
   e->key = 0;
@@ -3228,7 +3221,7 @@ tcache_double_free_verify (tcache_entry *e, size_t tc_idx)
   tcache_entry *tmp;
   size_t cnt = 0;
   LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
-  for (tmp = tcache->entries[tc_idx];
+  for (tmp = REVEAL_PTR (tcache->entries[tc_idx]);
        tmp;
        tmp = REVEAL_PTR (tmp->next), ++cnt)
     {
@@ -3290,13 +3283,13 @@ tcache_thread_shutdown (void)
      heap for coalescing.  */
   for (i = 0; i < TCACHE_MAX_BINS; ++i)
     {
-      while (tcache_tmp->entries[i])
+      while (REVEAL_PTR (tcache_tmp->entries[i]))
 	{
-	  tcache_entry *e = tcache_tmp->entries[i];
+	  tcache_entry *e = REVEAL_PTR (tcache_tmp->entries[i]);
 	  if (__glibc_unlikely (!aligned_OK (e)))
 	    malloc_printerr ("tcache_thread_shutdown(): "
 			     "unaligned tcache chunk detected");
-	  tcache_tmp->entries[i] = REVEAL_PTR (e->next);
+	  tcache_tmp->entries[i] = PROTECT_PTR (&(tcache_tmp->entries[i]), REVEAL_PTR (e->next));
 	  __libc_free (e);
 	}
     }
@@ -3337,6 +3330,8 @@ tcache_init(void)
       memset (tcache, 0, sizeof (tcache_perthread_struct));
     }
 
+  for (int i = 0; i < mp_.tcache_bins; i++)
+    tcache->entries[i] = PROTECT_PTR (&(tcache->entries[i]), NULL);
 }
 
 # define MAYBE_INIT_TCACHE() \
@@ -3699,7 +3694,7 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
       {
 	/* The tcache itself isn't encoded, but the chain is.  */
 	tcache_entry **tep = & tcache->entries[tc_idx];
-	tcache_entry *te = *tep;
+	tcache_entry *te = REVEAL_PTR (*tep);
 	while (te != NULL && !PTR_IS_ALIGNED (te, alignment))
 	  {
 	    tep = & (te->next);
-- 
2.39.5



More information about the Libc-alpha mailing list