summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libc/stdlib/malloc.c47
1 files changed, 33 insertions, 14 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index c0542fc9c8..3f544006fc 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: malloc.c,v 1.163 2014/05/12 19:02:20 tedu Exp $ */ 1/* $OpenBSD: malloc.c,v 1.164 2014/05/18 17:49:47 tedu Exp $ */
2/* 2/*
3 * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2008, 2010, 2011 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> 4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -966,34 +966,47 @@ malloc_bytes(struct dir_info *d, size_t size, void *f)
966 return ((char *)bp->page + k); 966 return ((char *)bp->page + k);
967} 967}
968 968
969 969static uint32_t
970/* 970find_chunknum(struct dir_info *d, struct region_info *r, void *ptr)
971 * Free a chunk, and possibly the page it's on, if the page becomes empty.
972 */
973static void
974free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
975{ 971{
976 struct chunk_head *mp;
977 struct chunk_info *info; 972 struct chunk_info *info;
978 int i, listnum; 973 uint32_t chunknum;
979 974
980 info = (struct chunk_info *)r->size; 975 info = (struct chunk_info *)r->size;
981 if (info->canary != d->canary1) 976 if (info->canary != d->canary1)
982 wrterror("chunk info corrupted", NULL); 977 wrterror("chunk info corrupted", NULL);
983 978
984 /* Find the chunk number on the page */ 979 /* Find the chunk number on the page */
985 i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift; 980 chunknum = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
986 981
987 if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) { 982 if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) {
988 wrterror("modified chunk-pointer", ptr); 983 wrterror("modified chunk-pointer", ptr);
989 return; 984 return -1;
990 } 985 }
991 if (info->bits[i / MALLOC_BITS] & (1U << (i % MALLOC_BITS))) { 986 if (info->bits[chunknum / MALLOC_BITS] &
987 (1U << (chunknum % MALLOC_BITS))) {
992 wrterror("chunk is already free", ptr); 988 wrterror("chunk is already free", ptr);
993 return; 989 return -1;
994 } 990 }
991 return chunknum;
992}
995 993
996 info->bits[i / MALLOC_BITS] |= 1U << (i % MALLOC_BITS); 994/*
995 * Free a chunk, and possibly the page it's on, if the page becomes empty.
996 */
997static void
998free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
999{
1000 struct chunk_head *mp;
1001 struct chunk_info *info;
1002 uint32_t chunknum;
1003 int listnum;
1004
1005 info = (struct chunk_info *)r->size;
1006 if ((chunknum = find_chunknum(d, r, ptr)) == -1)
1007 return;
1008
1009 info->bits[chunknum / MALLOC_BITS] |= 1U << (chunknum % MALLOC_BITS);
997 info->free++; 1010 info->free++;
998 1011
999 if (info->free == 1) { 1012 if (info->free == 1) {
@@ -1204,9 +1217,15 @@ ofree(void *p)
1204 if (mopts.malloc_junk && sz > 0) 1217 if (mopts.malloc_junk && sz > 0)
1205 memset(p, SOME_FREEJUNK, sz); 1218 memset(p, SOME_FREEJUNK, sz);
1206 if (!mopts.malloc_freenow) { 1219 if (!mopts.malloc_freenow) {
1220 if (find_chunknum(g_pool, r, p) == -1)
1221 return;
1207 i = getrbyte() & MALLOC_DELAYED_CHUNK_MASK; 1222 i = getrbyte() & MALLOC_DELAYED_CHUNK_MASK;
1208 tmp = p; 1223 tmp = p;
1209 p = g_pool->delayed_chunks[i]; 1224 p = g_pool->delayed_chunks[i];
1225 if (tmp == p) {
1226 wrterror("double free", p);
1227 return;
1228 }
1210 g_pool->delayed_chunks[i] = tmp; 1229 g_pool->delayed_chunks[i] = tmp;
1211 } 1230 }
1212 if (p != NULL) { 1231 if (p != NULL) {