From 1a0b356d4069d4f8f0a0b805c2a15e61e4ab0d08 Mon Sep 17 00:00:00 2001 From: Randy Stauner Date: Mon, 12 Jan 2026 18:35:12 -0700 Subject: [PATCH] Add pushtoarray insn to fix segfault with forwarding + splat Example insns diff for `def x = [3]; def a(...) = b(*x, 2, 3, ...)` == disasm: # local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] "..."@0 0000 putself ( 1)[Ca] 0000 putself 0000 opt_send_without_block 0000 splatarray true 0000 putobject 2 0000 putobject 3 +0000 pushtoarray 2 0000 getlocal_WC_0 "..."@0 0000 sendforward , nil 0000 leave [Re] This matches the insns produced by parse.y --- bootstraptest/test_method.rb | 7 +++++++ prism_compile.c | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb index 997675200e..78aab73485 100644 --- a/bootstraptest/test_method.rb +++ b/bootstraptest/test_method.rb @@ -1427,3 +1427,10 @@ assert_equal 'ok', <<~RUBY test RUBY + +assert_equal '[1, 2, 3]', %q{ + def target(*args) = args + def x = [1] + def forwarder(...) = target(*x, 2, ...) + forwarder(3).inspect +}, '[Bug #21832] post-splat args before forwarding' diff --git a/prism_compile.c b/prism_compile.c index 36a0b6ce50..7889681130 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1833,6 +1833,10 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b // foo(*a, b, c: :d) // foo(*a, b, **c) // + // If the next node is a forwarding argument: + // + // foo(*a, b, ...) + // // If the next node is NULL (we have hit the end): // // foo(*a, b) @@ -1855,6 +1859,10 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b PUSH_INSN(ret, location, concatarray); break; } + case PM_FORWARDING_ARGUMENTS_NODE: { + PUSH_INSN1(ret, location, pushtoarray, INT2FIX(post_splat_counter)); + break; + } default: break; }