From c675ec66e912b3000e05d65bba473e8bf6e18c96 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 24 Mar 2026 14:13:50 +0900 Subject: merge revision(s) 1e7cf7b2bc1f9b356b2e980e1e18548618da6363: [Backport #21446] [PATCH] Fix refinement modification of method visibility in superclass Previously, this didn't work correctly, resulting in a SystemStackError. This fixes the issue by finding the related superclass method entry, and updating the orig_me in the refinement method to point to the superclass method. Fixes [Bug #21446] --- test/ruby/test_refinement.rb | 23 +++++++++++++++++++++++ version.h | 2 +- vm_method.c | 6 ++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index b05e651c90..a8d46f4d07 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -1939,6 +1939,29 @@ class TestRefinement < Test::Unit::TestCase end; end + def test_public_in_refine_for_method_in_superclass + assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") + begin; + bug21446 = '[ruby-core:122558] [Bug #21446]' + + class CowSuper + private + def moo() "Moo"; end + end + class Cow < CowSuper + end + + module PublicCows + refine(Cow) { + public :moo + } + end + + using PublicCows + assert_equal("Moo", Cow.new.moo, bug21446) + end; + end + module SuperToModule class Parent end diff --git a/version.h b/version.h index 26194701aa..31a4f79cb2 100644 --- a/version.h +++ b/version.h @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 10 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 198 +#define RUBY_PATCHLEVEL 199 #include "ruby/version.h" #include "ruby/internal/abi.h" diff --git a/vm_method.c b/vm_method.c index 855ddd14c8..4dc67ad37b 100644 --- a/vm_method.c +++ b/vm_method.c @@ -941,6 +941,7 @@ check_override_opt_method(VALUE klass, VALUE mid) } } +static inline rb_method_entry_t* search_method0(VALUE klass, ID id, VALUE *defined_class_ptr, bool skip_refined); /* * klass->method_table[mid] = method_entry(defined_class, visi, def) * @@ -981,7 +982,12 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil if (RB_TYPE_P(klass, T_MODULE) && FL_TEST(klass, RMODULE_IS_REFINEMENT)) { VALUE refined_class = rb_refinement_module_get_refined_class(klass); + bool search_superclass = type == VM_METHOD_TYPE_ZSUPER && !lookup_method_table(refined_class, mid); rb_add_refined_method_entry(refined_class, mid); + if (search_superclass) { + rb_method_entry_t *me = lookup_method_table(refined_class, mid); + me->def->body.refined.orig_me = search_method0(refined_class, mid, NULL, true); + } } if (type == VM_METHOD_TYPE_REFINED) { rb_method_entry_t *old_me = lookup_method_table(RCLASS_ORIGIN(klass), mid); -- cgit v1.2.3