]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
cheri: malloc: Fix realloc to copy all relevant bytes
authorSzabolcs Nagy <szabolcs.nagy@arm.com>
Mon, 19 Dec 2022 13:18:10 +0000 (13:18 +0000)
committerSzabolcs Nagy <szabolcs.nagy@arm.com>
Mon, 19 Dec 2022 14:59:06 +0000 (14:59 +0000)
New code in realloc that handles when new allocation is needed for
alignment reasons (for capability narrowing) used the wrong size in
memcpy (size was off by SIZE_SZ unless memory tagging was enabled)
and used wrongly tagged pointer for untagging the old memory.

Due to this bug realloc sometimes failed to copy tail bytes of an old
allocation to the new allocation when capability narrowing is enabled.

malloc/malloc.c
malloc/tst-realloc.c

index 392116a5ac91d1300c181178bb5435c09d2d0815..ededc5cfe2ccffc286b994f1cce02fdf15f15e2c 100644 (file)
@@ -3762,9 +3762,9 @@ __libc_realloc (void *oldmem, size_t bytes)
       void *newmem = _mid_memalign (align, bytes, 0);
       if (!cap_narrow_check (newmem, oldmem))
        return newmem;
-      size_t sz = oldsize - CHUNK_HDR_SZ;
+      size_t sz = memsize (oldp);
       memcpy (newmem, oldmem, sz < bytes ? sz : bytes);
-      (void) tag_region (oldmem, sz);
+      (void) tag_region (chunk2mem (oldp), sz);
       _int_free (ar_ptr, oldp, 0);
       return newmem;
     }
index 5eb62a770f2fed32464cc115f5ed44994bbac98d..2e14d318ab719e4040011f6ff9ae93ff14c92672 100644 (file)
@@ -83,6 +83,25 @@ do_test (void)
 
   free (p);
 
+  /* Check as above with larger size increase.  */
+  p = malloc (34);
+  if (p == NULL)
+    FAIL_EXIT1 ("malloc (34) failed.");
+  memset (p, 'a', 34);
+  p = realloc (p, 80000);
+  if (p == NULL)
+    FAIL_EXIT1 ("realloc (p, 80000) failed.");
+  c = p;
+  ok = 1;
+  for (i = 0; i < 34; i++)
+    {
+      if (c[i] != 'a')
+        ok = 0;
+    }
+  if (ok == 0)
+    FAIL_EXIT1 ("first 34 bytes were not preserved");
+  free (p);
+
   p = realloc (NULL, 100);
   if (p == NULL)
     FAIL_EXIT1 ("realloc (NULL, 100) failed.");