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 /malloc | |
parent | dc23cc80210799f8d8ab5b1ea2e00341e613a1a7 (diff) | |
download | glibc-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.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 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."); |