Skip to content

Commit 6b2a223

Browse files
committed
YJIT: Bail out if proc would be stored above stack top
Fixes [Bug #21266].
1 parent 6ed5574 commit 6b2a223

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

bootstraptest/test_yjit.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4889,6 +4889,16 @@ def tests
48894889
tests
48904890
}
48914891

4892+
# regression test for splat with &proc{} when the target has rest (Bug #21266)
4893+
assert_equal '[]', %q{
4894+
def foo(args) = bar(*args, &proc { _1 })
4895+
def bar(_, _, _, _, *rest) = yield rest
4896+
4897+
GC.stress = true
4898+
foo([1,2,3,4])
4899+
foo([1,2,3,4])
4900+
}
4901+
48924902
# regression test for invalidating an empty block
48934903
assert_equal '0', %q{
48944904
def foo = (* = 1).pred

yjit/src/codegen.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7890,6 +7890,11 @@ fn gen_send_iseq(
78907890
gen_counter_incr(jit, asm, Counter::send_iseq_clobbering_block_arg);
78917891
return None;
78927892
}
7893+
if iseq_has_rest {
7894+
// The proc would be stored above the current stack top, where GC can't see it
7895+
gen_counter_incr(jit, asm, Counter::send_iseq_block_arg_gc_unsafe);
7896+
return None;
7897+
}
78937898
let proc = asm.stack_pop(1); // Pop first, as argc doesn't account for the block arg
78947899
let callee_specval = asm.ctx.sp_opnd(callee_specval);
78957900
asm.store(callee_specval, proc);

yjit/src/stats.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ make_counters! {
354354
send_iseq_arity_error,
355355
send_iseq_block_arg_type,
356356
send_iseq_clobbering_block_arg,
357+
send_iseq_block_arg_gc_unsafe,
357358
send_iseq_complex_discard_extras,
358359
send_iseq_leaf_builtin_block_arg_block_param,
359360
send_iseq_kw_splat_non_nil,

0 commit comments

Comments
 (0)