summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjasone <jasone@FreeBSD.org>2007-06-15 22:00:16 +0000
committerjasone <jasone@FreeBSD.org>2007-06-15 22:00:16 +0000
commita3eda1cfc45efc2b862707c8014da7a7bf59c0e7 (patch)
tree9fefa0a84e199261e2c58baf1ba2a579030873c5 /lib
parent11712476ccd6b220ca8897566c90e821a3516ef9 (diff)
downloadFreeBSD-src-a3eda1cfc45efc2b862707c8014da7a7bf59c0e7.zip
FreeBSD-src-a3eda1cfc45efc2b862707c8014da7a7bf59c0e7.tar.gz
Fix junk/zero filling for realloc(). Junk filling was missing in one case,
and zero filling was broken in a way that could cause memory corruption. Update comments.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/malloc.c84
1 files changed, 48 insertions, 36 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 4bb2a92..7e59c2d 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (C) 2006 Jason Evans <jasone@FreeBSD.org>.
+ * Copyright (C) 2006,2007 Jason Evans <jasone@FreeBSD.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,36 +47,37 @@
* categories according to size class. Assuming runtime defaults, 4 kB pages
* and a 16 byte quantum, the size classes in each category are as follows:
*
- * |====================================|
- * | Category | Subcategory | Size |
- * |====================================|
- * | Small | Tiny | 2 |
- * | | | 4 |
- * | | | 8 |
- * | |----------------+--------|
- * | | Quantum-spaced | 16 |
- * | | | 32 |
- * | | | 48 |
- * | | | ... |
- * | | | 480 |
- * | | | 496 |
- * | | | 512 |
- * | |----------------+--------|
- * | | Sub-page | 1 kB |
- * | | | 2 kB |
- * |====================================|
- * | Large | 4 kB |
- * | | 8 kB |
- * | | 16 kB |
- * | | ... |
- * | | 256 kB |
- * | | 512 kB |
- * |====================================|
- * | Huge | 1 MB |
- * | | 2 MB |
- * | | 3 MB |
- * | | ... |
- * |====================================|
+ * |=====================================|
+ * | Category | Subcategory | Size |
+ * |=====================================|
+ * | Small | Tiny | 2 |
+ * | | | 4 |
+ * | | | 8 |
+ * | |----------------+---------|
+ * | | Quantum-spaced | 16 |
+ * | | | 32 |
+ * | | | 48 |
+ * | | | ... |
+ * | | | 480 |
+ * | | | 496 |
+ * | | | 512 |
+ * | |----------------+---------|
+ * | | Sub-page | 1 kB |
+ * | | | 2 kB |
+ * |=====================================|
+ * | Large | 4 kB |
+ * | | 8 kB |
+ * | | 12 kB |
+ * | | ... |
+ * | | 1012 kB |
+ * | | 1016 kB |
+ * | | 1020 kB |
+ * |=====================================|
+ * | Huge | 1 MB |
+ * | | 2 MB |
+ * | | 3 MB |
+ * | | ... |
+ * |=====================================|
*
* A different mechanism is used for each category:
*
@@ -1419,7 +1420,7 @@ chunk_dealloc(void *chunk, size_t size)
/*
* Choose an arena based on a per-thread value (fast-path code, calls slow-path
- * code if necessary.
+ * code if necessary).
*/
static inline arena_t *
choose_arena(void)
@@ -1438,7 +1439,7 @@ choose_arena(void)
* app switches to threaded mode, the initial thread may end up
* being assigned to some other arena, but this one-time switch
* shouldn't cause significant issues.
- * */
+ */
return (arenas[0]);
}
@@ -1898,7 +1899,9 @@ arena_run_alloc(arena_t *arena, size_t size)
}
}
- /* No usable runs. Allocate a new chunk, then try again. */
+ /*
+ * No usable runs. Create a new chunk from which to allocate the run.
+ */
chunk = arena_chunk_alloc(arena);
if (chunk == NULL)
return (NULL);
@@ -2401,6 +2404,7 @@ arena_ralloc(void *ptr, size_t size, size_t oldsize)
if (ret == NULL)
return (NULL);
+ /* Junk/zero-filling were already done by arena_malloc(). */
if (size < oldsize)
memcpy(ret, ptr, size);
else
@@ -2411,7 +2415,7 @@ IN_PLACE:
if (opt_junk && size < oldsize)
memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
else if (opt_zero && size > oldsize)
- memset((void *)((uintptr_t)ptr + size), 0, oldsize - size);
+ memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize);
return (ptr);
}
@@ -2757,8 +2761,16 @@ huge_ralloc(void *ptr, size_t size, size_t oldsize)
/* Avoid moving the allocation if the size class would not change. */
if (oldsize > arena_maxclass &&
- CHUNK_CEILING(size) == CHUNK_CEILING(oldsize))
+ CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) {
+ if (opt_junk && size < oldsize) {
+ memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize
+ - size);
+ } else if (opt_zero && size > oldsize) {
+ memset((void *)((uintptr_t)ptr + oldsize), 0, size
+ - oldsize);
+ }
return (ptr);
+ }
/*
* If we get here, then size and oldsize are different enough that we
OpenPOWER on IntegriCloud