diff options
author | Peter Zhu <[email protected]> | 2021-11-11 11:55:35 -0500 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2021-11-11 14:08:38 -0500 |
commit | 84202963c52e02cecad3e6b2fad478bfbeee1bc7 (patch) | |
tree | 6386a26ce4b2a78947f8dcbe1774976fe9ecc5d1 | |
parent | a9a94540d68b523ecc4e2181e50b320cd5d176f1 (diff) |
[Bug #18329] Fix crash when calling non-existent super method
The cme is NULL when a method does not exist, so check it before
accessing the callcache.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5108
-rw-r--r-- | test/ruby/test_super.rb | 31 | ||||
-rw-r--r-- | vm_insnhelper.c | 3 |
2 files changed, 33 insertions, 1 deletions
diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index d94f4679d3..3afde9b0e3 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -521,6 +521,37 @@ class TestSuper < Test::Unit::TestCase assert_equal(%w[B A], result, bug9721) end + # [Bug #18329] + def test_super_missing_prepended_module + a = Module.new do + def probe(*methods) + prepend(probing_module(methods)) + end + + def probing_module(methods) + Module.new do + methods.each do |method| + define_method(method) do |*args, **kwargs, &block| + super(*args, **kwargs, &block) + end + end + end + end + end + + b = Class.new do + extend a + + probe :danger!, :missing + + def danger!; end + end + + o = b.new + o.danger! + 2.times { o.missing rescue NoMethodError } + end + def test_from_eval bug10263 = '[ruby-core:65122] [Bug #10263a]' a = Class.new do diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 86bdfd2fb6..b9950f4fe2 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1936,7 +1936,8 @@ vm_search_method_fastpath(VALUE cd_owner, struct rb_call_data *cd, VALUE klass) #if OPT_INLINE_METHOD_CACHE if (LIKELY(vm_cc_class_check(cc, klass))) { - if (LIKELY(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)))) { + const struct rb_callable_method_entry_struct *cme = vm_cc_cme(cc); + if (LIKELY(cme && !METHOD_ENTRY_INVALIDATED(cme))) { VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc))); RB_DEBUG_COUNTER_INC(mc_inline_hit); VM_ASSERT(vm_cc_cme(cc) == NULL || // not found |