diff options
author | Peter Zhu <peter@peterzhu.ca> | 2022-05-04 09:50:48 -0400 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2022-05-09 08:45:24 -0400 |
commit | 033e58cf2c6829e14fa38e0a364911361090aa83 (patch) | |
tree | f3f1f49a431a97905b1cba0217b95cca5bcc6910 /gc.c | |
parent | a41fbc2c95cc2f7ba9071aca091d8262a8f2cf60 (diff) | |
download | ruby-033e58cf2c6829e14fa38e0a364911361090aa83.tar.gz |
Fix gc_page_sweep when last bitmap plane is not used
Depending on alignment, the last bitmap plane may not used. Then it will
appear as if all of the objects on that plane is unmarked, which will
cause a buffer overrun when we try to free the object. This commit
changes the loop to calculate the number of planes used
(bitmap_plane_count).
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 11 |
1 files changed, 8 insertions, 3 deletions
@@ -5405,8 +5405,6 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context { struct heap_page *sweep_page = ctx->page; - int i; - uintptr_t p; bits_t *bits, bitset; @@ -5429,6 +5427,13 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context bits[BITMAP_INDEX(p) + page_rvalue_count / BITS_BITLENGTH] |= ~(((bits_t)1 << out_of_range_bits) - 1); } + /* The last bitmap plane may not be used if the last plane does not have + * have enough space for the slot_size. In that case, the last plane must + * be skipped since none of the bits will be set. */ + int bitmap_plane_count = CEILDIV(NUM_IN_PAGE(p) + page_rvalue_count, BITS_BITLENGTH); + GC_ASSERT(bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT - 1 || + bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT); + // Skip out of range slots at the head of the page bitset = ~bits[0]; bitset >>= NUM_IN_PAGE(p); @@ -5437,7 +5442,7 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context } p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE; - for (i=1; i < HEAP_PAGE_BITMAP_LIMIT; i++) { + for (int i = 1; i < bitmap_plane_count; i++) { bitset = ~bits[i]; if (bitset) { gc_sweep_plane(objspace, heap, p, bitset, ctx); |