diff options
author | Alan Wu <[email protected]> | 2024-02-21 17:42:23 -0500 |
---|---|---|
committer | GitHub <[email protected]> | 2024-02-21 14:42:23 -0800 |
commit | 0be09967fee9eda531260e027094d619e034c425 (patch) | |
tree | 556f29ce44d65e98c690094700dc159d79a5b14e | |
parent | 551f64745fa0ba0ea70812f63495f2fa7dd5afe4 (diff) |
YJIT: Grab stack operands after SP change in String#byteslice (#10060)
Previously, `StackOperand`s caching `sp_offset` was held across a
jit_prepare_call_with_gc(), which invalidates the offsets. With the
right register allocation state, the canary overlapped with the old
address of the receiver and YJIT clobbered the receiver writing the
canary.
-rw-r--r-- | test/ruby/test_yjit.rb | 6 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 11 |
2 files changed, 12 insertions, 5 deletions
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 35036aad4e..8936e567d1 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1594,6 +1594,12 @@ class TestYJIT < Test::Unit::TestCase RUBY end + def test_byteslice_sp_invalidation + assert_compiles(<<~'RUBY', result: 'ok', no_send_fallbacks: true) + "okng".itself.byteslice(0, 2) + RUBY + end + private def code_gc_helpers diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 0064ed15cc..5e9d42de62 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5398,12 +5398,8 @@ fn jit_rb_str_byteslice( return false } - let len = asm.stack_opnd(0); - let beg = asm.stack_opnd(1); - let recv = asm.stack_opnd(2); - // rb_str_byte_substr should be leaf if indexes are fixnums - match (asm.ctx.get_opnd_type(beg.into()), asm.ctx.get_opnd_type(len.into())) { + match (asm.ctx.get_opnd_type(StackOpnd(0)), asm.ctx.get_opnd_type(StackOpnd(1))) { (Type::Fixnum, Type::Fixnum) => {}, // Raises when non-integers are passed in, which requires the method frame // to be pushed for the backtrace @@ -5414,6 +5410,11 @@ fn jit_rb_str_byteslice( // rb_str_byte_substr allocates a substring jit_prepare_call_with_gc(jit, asm); + // Get stack operands after potential SP change + let len = asm.stack_opnd(0); + let beg = asm.stack_opnd(1); + let recv = asm.stack_opnd(2); + let ret_opnd = asm.ccall(rb_str_byte_substr as *const u8, vec![recv, beg, len]); asm.stack_pop(3); |