merge revision(s) 0eb634ae73: [Backport #19464]

YJIT: Detect and reject `send(:alias_for_send, :foo)`

	Previously, YJIT failed to put the stack into the correct shape when
	`BasicObject#send` calls an alias method for the send method itself.
	This can manifest as strange `NoMethodError`s in the final non-send
	receiver, as [seen][1] with the kt-paperclip gem. I also found a case
	where it makes YJIT fail the stack size assertion while compiling
	`leave`.

	YJIT's `BasicObject#__send__` implementation already rejects sends to
	`send`, but didn't detect sends to aliases of `send`. Adjust the
	detection and reject these cases.

	Fixes [Bug #19464]

	[1]: https://github.com/Shopify/yjit/issues/306
	---
	 test/ruby/test_yjit.rb | 20 ++++++++++++++++++++
	 yjit/src/codegen.rs    | 25 ++++++++++---------------
	 2 files changed, 30 insertions(+), 15 deletions(-)
This commit is contained in:
NARUSE, Yui 2023-03-15 16:36:32 +09:00
parent db28f7003f
commit b73a073597
3 changed files with 31 additions and 16 deletions

View file

@ -1121,6 +1121,26 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
def test_nested_send
#[Bug #19464]
assert_compiles(<<~RUBY, result: [:ok, :ok])
klass = Class.new do
class << self
alias_method :my_send, :send
def bar = :ok
def foo = bar
end
end
with_break = -> { break klass.send(:my_send, :foo) }
wo_break = -> { klass.send(:my_send, :foo) }
[with_break[], wo_break[]]
RUBY
end
private
def code_gc_helpers