summaryrefslogtreecommitdiff
path: root/allchblk.c
diff options
context:
space:
mode:
authorhboehm <hboehm>2008-01-30 02:37:16 +0100
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 19:06:42 +0200
commite06eebf7d27981c196cfdb831a2fcbd4a3e86af5 (patch)
treede2a8fc6c6d4901dfe47b82df5d0e5c25011ac54 /allchblk.c
parent44a3b48838fdfeb8b0bfce884edf0a83561d2742 (diff)
2008-01-29 Hans Boehm <Hans.Boehm@hp.com>
* allchblk.c (GC_merge_unmapped, GC_freehblk): Refuse to create blocks large enough that their size, when interpreted as a signed value, would be negative. * include/private/gc_priv.h: Comment hb_sz range limit.
Diffstat (limited to 'allchblk.c')
-rw-r--r--allchblk.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/allchblk.c b/allchblk.c
index b3daa59..49cc863 100644
--- a/allchblk.c
+++ b/allchblk.c
@@ -429,9 +429,10 @@ void GC_merge_unmapped(void)
size = hhdr->hb_sz;
next = (struct hblk *)((word)h + size);
GET_HDR(next, nexthdr);
+ nextsize = nexthdr -> hb_sz;
/* Coalesce with successor, if possible */
- if (0 != nexthdr && HBLK_IS_FREE(nexthdr)) {
- nextsize = nexthdr -> hb_sz;
+ if (0 != nexthdr && HBLK_IS_FREE(nexthdr)
+ && (signed_word) (size + next_size) > 0 /* no pot. overflow */) {
if (IS_MAPPED(hhdr)) {
GC_ASSERT(!IS_MAPPED(nexthdr));
/* make both consistent, so that we can merge */
@@ -808,6 +809,11 @@ signed_word size;
GET_HDR(hbp, hhdr);
size = hhdr->hb_sz;
size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
+ if (size <= 0)
+ ABORT("Deallocating excessively large block. Too large an allocation?");
+ /* Probably possible if we try to allocate more than half the address */
+ /* space at once. If we dont catch it here, strange things happen */
+ /* later. */
GC_remove_counts(hbp, (word)size);
hhdr->hb_sz = size;
# ifdef USE_MUNMAP
@@ -826,7 +832,9 @@ signed_word size;
GET_HDR(next, nexthdr);
prev = GC_free_block_ending_at(hbp);
/* Coalesce with successor, if possible */
- if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr)) {
+ if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr)
+ && (signed_word)(hhdr -> hb_sz + nexthdr -> hb_sz) > 0
+ /* no overflow */) {
GC_remove_from_fl(nexthdr, FL_UNKNOWN);
hhdr -> hb_sz += nexthdr -> hb_sz;
GC_remove_header(next);
@@ -834,7 +842,8 @@ signed_word size;
/* Coalesce with predecessor, if possible. */
if (0 != prev) {
prevhdr = HDR(prev);
- if (IS_MAPPED(prevhdr)) {
+ if (IS_MAPPED(prevhdr)
+ && (signed_word)(hhdr -> hb_sz + prevhdr -> hb_sz) > 0) {
GC_remove_from_fl(prevhdr, FL_UNKNOWN);
prevhdr -> hb_sz += hhdr -> hb_sz;
# ifdef USE_MUNMAP