зеркало из https://github.com/github/ruby.git
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.
This commit is contained in:
Родитель
551f64745f
Коммит
0be09967fe
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче