summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2022-05-04 09:50:48 -0400
committerPeter Zhu <peter@peterzhu.ca>2022-05-09 08:45:24 -0400
commit033e58cf2c6829e14fa38e0a364911361090aa83 (patch)
treef3f1f49a431a97905b1cba0217b95cca5bcc6910 /gc.c
parenta41fbc2c95cc2f7ba9071aca091d8262a8f2cf60 (diff)
downloadruby-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.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/gc.c b/gc.c
index 3710bafce3..b24a2f08a8 100644
--- a/gc.c
+++ b/gc.c
@@ -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);