diff options
author | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2022-12-19 13:18:10 +0000 |
---|---|---|
committer | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2022-12-19 14:59:06 +0000 |
commit | bbce0c75f35f55b9f5e43dd4fa01a82cc27bf020 (patch) | |
tree | d9ab159f3cd796bd4cc9d4e331cd8b82c501f9dc | |
parent | dc23cc80210799f8d8ab5b1ea2e00341e613a1a7 (diff) | |
download | glibc-bbce0c75f35f55b9f5e43dd4fa01a82cc27bf020.tar.gz glibc-bbce0c75f35f55b9f5e43dd4fa01a82cc27bf020.tar.xz glibc-bbce0c75f35f55b9f5e43dd4fa01a82cc27bf020.zip |
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.
-rw-r--r-- | malloc/malloc.c | 4 | ||||
-rw-r--r-- | malloc/tst-realloc.c | 19 |
2 files changed, 21 insertions, 2 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c index 392116a5ac..ededc5cfe2 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 5eb62a770f..2e14d318ab 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."); |