summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhboehm <hboehm>2008-01-30 01:37:16 +0000
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 21:06:42 +0400
commite06eebf7d27981c196cfdb831a2fcbd4a3e86af5 (patch)
treede2a8fc6c6d4901dfe47b82df5d0e5c25011ac54
parent44a3b48838fdfeb8b0bfce884edf0a83561d2742 (diff)
downloadbdwgc-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--ChangeLog7
-rw-r--r--allchblk.c17
-rw-r--r--include/private/gc_priv.h3
3 files changed, 23 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 026d0521..2860f2ab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/allchblk.c b/allchblk.c
index b3daa591..49cc863b 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
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