summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2017-06-15 12:54:40 -0400
committerRich Felker <dalias@aerifal.cx>2017-06-15 12:54:40 -0400
commit1c86c7f5c26dd0569df7afc23ee9866fb3f645dc (patch)
tree0d512c978c4ced20a1dd2f00d38dd44cc65a06e9
parent10800088099ec4c27c1db6c613c8bbf9f76e4057 (diff)
downloadmusl-1c86c7f5c26dd0569df7afc23ee9866fb3f645dc.tar.gz
handle mremap failure in realloc of mmap-serviced allocations
mremap seems to always fail on nommu, and on some non-Linux implementations of the Linux syscall API, it at least fails to increase allocation size, and may fail to move (i.e. defragment) the existing mapping when shrinking it too. instead of failing realloc or leaving an over-sized allocation that may waste a large amount of memory, fallback to malloc-memcpy-free if mremap fails.
-rw-r--r--src/malloc/malloc.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c
index c38c46fe..d5ee4280 100644
--- a/src/malloc/malloc.c
+++ b/src/malloc/malloc.c
@@ -406,7 +406,7 @@ void *realloc(void *p, size_t n)
if (oldlen == newlen) return p;
base = __mremap(base, oldlen, newlen, MREMAP_MAYMOVE);
if (base == (void *)-1)
- return newlen < oldlen ? p : 0;
+ goto copy_realloc;
self = (void *)(base + extra);
self->csize = newlen - extra;
return CHUNK_TO_MEM(self);
@@ -439,6 +439,7 @@ void *realloc(void *p, size_t n)
return CHUNK_TO_MEM(self);
}
+copy_realloc:
/* As a last resort, allocate a new chunk and copy to it. */
new = malloc(n-OVERHEAD);
if (!new) return 0;