Merge pull request #6305 from dearblue/method_missing

Protect keyword arguments in `prepare_missing()`
This commit is contained in:
Yukihiro "Matz" Matsumoto
2024-07-20 22:04:50 +09:00
committed by GitHub
2 changed files with 31 additions and 1 deletions
+30
View File
@@ -138,6 +138,36 @@ assert 'Method#call with undefined method' do
assert_raise(NoMethodError) { m.call(:arg1, :arg2) }
end
assert 'Method#call with undefined method -- only kwargs' do
c = Class.new {
attr_accessor :m, :argv, :kwargs
def respond_to_missing?(m, b)
m == :foo
end
def method_missing(m, *argv, **kwargs)
@m = m
@argv = argv
@kwargs = kwargs
super
end
}
cc = c.new
assert_kind_of Method, cc.method(:foo)
# Calling cc.method(:foo) works
assert_raise(NoMethodError) { cc.method(:foo).call(kwarg1: :val1, kwarg2: :val2) }
assert_equal :foo, cc.m
assert_equal [], cc.argv
assert_equal({ kwarg1: :val1, kwarg2: :val2 }, cc.kwargs)
# calling cc.foo fails
assert_raise(NoMethodError) { cc.foo(kwarg1: :val1, kwarg2: :val2) }
assert_equal :foo, cc.m
assert_equal [], cc.argv
assert_equal({ kwarg1: :val1, kwarg2: :val2 }, cc.kwargs)
end
assert 'Method#source_location' do
skip if proc{}.source_location.nil?
+1 -1
View File
@@ -629,7 +629,6 @@ prepare_missing(mrb_state *mrb, mrb_callinfo *ci, mrb_value recv, mrb_sym mid, m
stack_extend(mrb, 4);
argv = &ci->stack[1]; /* maybe reallocated */
argv[0] = args;
if (ci->nk == 0) {
argv[1] = blk;
}
@@ -638,6 +637,7 @@ prepare_missing(mrb_state *mrb, mrb_callinfo *ci, mrb_value recv, mrb_sym mid, m
argv[1] = argv[ci->n];
argv[2] = blk;
}
argv[0] = args; /* must be replaced after saving argv[0] as it may be a keyword argument */
ci->n = CALL_MAXARGS;
/* ci->nk is already set to zero or CALL_MAXARGS */
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));