From ec8900e3eb7f0008a635fb6fbabde3eb7802536b Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 15 May 2025 14:04:36 +0200 Subject: [PATCH] rb_gc_impl_copy_finalizer: generate a new object id Fix a regression introduced by: https://github.com/ruby/ruby/pull/13155 --- gc/default/default.c | 3 ++- gc/mmtk/mmtk.c | 3 ++- object.c | 2 +- test/ruby/test_objectspace.rb | 21 ++++++++++++++++++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/gc/default/default.c b/gc/default/default.c index 5c6c2a9417..131086c338 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -2805,7 +2805,8 @@ rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj) int lev = rb_gc_vm_lock(); if (RB_LIKELY(st_lookup(finalizer_table, obj, &data))) { - table = (VALUE)data; + table = rb_ary_dup((VALUE)data); + RARRAY_ASET(table, 0, rb_obj_id(dest)); st_insert(finalizer_table, dest, table); FL_SET(dest, FL_FINALIZE); } diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 09a8c0bc5c..70cd5f405c 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -985,7 +985,8 @@ rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj) int lev = rb_gc_vm_lock(); if (RB_LIKELY(st_lookup(objspace->finalizer_table, obj, &data))) { - table = (VALUE)data; + table = rb_ary_dup((VALUE)data); + RARRAY_ASET(table, 0, rb_obj_id(dest)); st_insert(objspace->finalizer_table, dest, table); FL_SET(dest, FL_FINALIZE); } diff --git a/object.c b/object.c index 85b96fe31a..15eeda8689 100644 --- a/object.c +++ b/object.c @@ -409,11 +409,11 @@ init_copy(VALUE dest, VALUE obj) RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR); // Copies the shape id from obj to dest RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR); - rb_gc_copy_attributes(dest, obj); rb_copy_generic_ivar(dest, obj); if (RB_TYPE_P(obj, T_OBJECT)) { rb_obj_copy_ivar(dest, obj); } + rb_gc_copy_attributes(dest, obj); } static VALUE immutable_obj_clone(VALUE obj, VALUE kwfreeze); diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb index ef85edc5ee..f27f586ab7 100644 --- a/test/ruby/test_objectspace.rb +++ b/test/ruby/test_objectspace.rb @@ -94,7 +94,7 @@ End end def test_finalizer - assert_in_out_err(["-e", <<-END], "", %w(:ok :ok :ok :ok), []) + assert_in_out_err(["-e", <<-END], "", %w(:ok :ok :ok), []) a = [] ObjectSpace.define_finalizer(a) { p :ok } b = a.dup @@ -137,6 +137,25 @@ End } end + def test_finalizer_copy + assert_in_out_err(["-e", <<~'RUBY'], "", %w(:ok), []) + def fin + ids = Set.new + ->(id) { puts "object_id (#{id}) reused" unless ids.add?(id) } + end + + OBJ = Object.new + ObjectSpace.define_finalizer(OBJ, fin) + OBJ.freeze + + 10.times do + OBJ.clone + end + + p :ok + RUBY + end + def test_finalizer_with_super assert_in_out_err(["-e", <<-END], "", %w(:ok), []) class A