Skip to content

Commit 0d367ce

Browse files
luke-gruberk0kubun
authored andcommitted
Fix bad NameError raised using sendforward instruction through vcall
If you called a VCALL method and the method takes forwarding arguments and then you forward those arguments along using the sendforward instruction, the method_missing class was wrongly chosen as NameError instead of NoMethodError. This is because the VM looked at the CallInfo of the vcall and determined it needed to raise NameError. Now we detect that case and raise NoMethodError. [Backport #21535]
1 parent 5a42d26 commit 0d367ce

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

test/ruby/test_nomethod_error.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,32 @@ def name
106106

107107
assert_match(/undefined method.+this_method_does_not_exist.+for.+Module/, err.to_s)
108108
end
109+
110+
def test_send_forward_raises
111+
t = EnvUtil.labeled_class("Test") do
112+
def foo(...)
113+
forward(...)
114+
end
115+
end
116+
obj = t.new
117+
assert_raise(NoMethodError) do
118+
obj.foo
119+
end
120+
end
121+
122+
# [Bug #21535]
123+
def test_send_forward_raises_when_called_through_vcall
124+
t = EnvUtil.labeled_class("Test") do
125+
def foo(...)
126+
forward(...)
127+
end
128+
def foo_indirect
129+
foo # vcall
130+
end
131+
end
132+
obj = t.new
133+
assert_raise(NoMethodError) do
134+
obj.foo_indirect
135+
end
136+
end
109137
end

vm_insnhelper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4185,7 +4185,7 @@ static enum method_missing_reason
41854185
ci_missing_reason(const struct rb_callinfo *ci)
41864186
{
41874187
enum method_missing_reason stat = MISSING_NOENTRY;
4188-
if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
4188+
if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
41894189
if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
41904190
if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
41914191
return stat;

0 commit comments

Comments
 (0)