From 0597cbcb1d895028e954db9711681e987c56729d Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 18 Feb 2025 16:26:07 -0500 Subject: [PATCH] Fix crash for special constants in too complex generic ivars We should skip reference updating for entries in too complex generic ivars that are special constants. This fixes the following crash: MAX_SHAPES = 0x80000 MAX_SHAPES.times do |i| o = [] o.instance_variable_set(:"@foo#{i}", 1) end o = [] o.instance_variable_set(:"@a", 123) GC.compact --- gc.c | 2 ++ test/ruby/test_gc_compact.rb | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/gc.c b/gc.c index 402e0acb98..bd3e8aea4d 100644 --- a/gc.c +++ b/gc.c @@ -3441,6 +3441,8 @@ vm_weak_table_gen_ivar_foreach_too_complex_i(st_data_t _key, st_data_t value, st GC_ASSERT(!iter_data->weak_only); + if (SPECIAL_CONST_P((VALUE)value)) return ST_CONTINUE; + return iter_data->callback((VALUE)value, iter_data->data); } diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb index 4c8aa20215..2a72ecfc5f 100644 --- a/test/ruby/test_gc_compact.rb +++ b/test/ruby/test_gc_compact.rb @@ -452,4 +452,21 @@ class TestGCCompact < Test::Unit::TestCase assert_raise(FrozenError) { a.set_a } end; end + + def test_moving_too_compex_generic_ivar + omit "not compiled with SHAPE_DEBUG" unless defined?(RubyVM::Shape) + + assert_separately([], <<~RUBY) + RubyVM::Shape.exhaust_shapes + + obj = [] + obj.instance_variable_set(:@fixnum, 123) + obj.instance_variable_set(:@str, "hello") + + GC.verify_compaction_references(expand_heap: true, toward: :empty) + + assert_equal(123, obj.instance_variable_get(:@fixnum)) + assert_equal("hello", obj.instance_variable_get(:@str)) + RUBY + end end