aboutsummaryrefslogtreecommitdiff
path: root/malloc
diff options
context:
space:
mode:
authorSzabolcs Nagy <szabolcs.nagy@arm.com>2022-12-19 13:18:10 +0000
committerSzabolcs Nagy <szabolcs.nagy@arm.com>2022-12-19 14:59:06 +0000
commitbbce0c75f35f55b9f5e43dd4fa01a82cc27bf020 (patch)
treed9ab159f3cd796bd4cc9d4e331cd8b82c501f9dc /malloc
parentdc23cc80210799f8d8ab5b1ea2e00341e613a1a7 (diff)
downloadglibc-bbce0c75f35f55b9f5e43dd4fa01a82cc27bf020.zip
glibc-bbce0c75f35f55b9f5e43dd4fa01a82cc27bf020.tar.gz
glibc-bbce0c75f35f55b9f5e43dd4fa01a82cc27bf020.tar.bz2
cheri: malloc: Fix realloc to copy all relevant bytes
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.
Diffstat (limited to 'malloc')
-rw-r--r--malloc/malloc.c4
-rw-r--r--malloc/tst-realloc.c19
2 files changed, 21 insertions, 2 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 392116a..ededc5c 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -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;
}
diff --git a/malloc/tst-realloc.c b/malloc/tst-realloc.c
index 5eb62a7..2e14d31 100644
--- a/malloc/tst-realloc.c
+++ b/malloc/tst-realloc.c
@@ -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.");