diff options
author | hboehm <hboehm> | 2008-01-30 01:37:16 +0000 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-26 21:06:42 +0400 |
commit | e06eebf7d27981c196cfdb831a2fcbd4a3e86af5 (patch) | |
tree | de2a8fc6c6d4901dfe47b82df5d0e5c25011ac54 | |
parent | 44a3b48838fdfeb8b0bfce884edf0a83561d2742 (diff) | |
download | bdwgc-e06eebf7d27981c196cfdb831a2fcbd4a3e86af5.tar.gz |
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.
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | allchblk.c | 17 | ||||
-rw-r--r-- | include/private/gc_priv.h | 3 |
3 files changed, 23 insertions, 4 deletions
@@ -1,3 +1,10 @@ +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. + 2008-01-29 Hans Boehm <Hans.Boehm@hp.com> (with help from Manuel Serrano) * mark.c (GC_push_next_marked): correct comment. @@ -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 diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 94e63003..c0a7108b 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -711,6 +711,9 @@ struct hblkhdr { /* changed. */ size_t hb_sz; /* If in use, size in bytes, of objects in the block. */ /* if free, the size in bytes of the whole block */ + /* We assume that this is convertible to signed_word */ + /* without generating a negative result. We avoid */ + /* generating free blocks larger than that. */ word hb_descr; /* object descriptor for marking. See */ /* mark.h. */ # ifdef MARK_BIT_PER_OBJ |