Skip to content

Commit

Permalink
Do not apply anon_rest optimization when passed array uses keyword-fl…
Browse files Browse the repository at this point in the history
…agged hash

The optimization sets args->rest_dupped to avoid allocating an array,
but this is not safe if the splat array ends in a keyword flagged
hash.  Unset args->rest_dupped in this case.

Fixes [Bug #20388]
  • Loading branch information
jeremyevans authored and tenderlove committed Mar 22, 2024
1 parent a2ac28d commit 2dbcc12
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 0 deletions.
13 changes: 13 additions & 0 deletions test/ruby/test_keyword.rb
Expand Up @@ -2835,6 +2835,19 @@ def bar(*a, **kw)
assert_equal({a: 1}, kw)
end

def test_anon_splat_ruby2_keywords_bug_20388
extend(Module.new{def process(action, ...) 1 end})
extend(Module.new do
def process(action, *args)
args.freeze
super
end
ruby2_keywords :process
end)

assert_equal(1, process(:foo, bar: :baz))
end

def test_top_ruby2_keywords
assert_in_out_err([], <<-INPUT, ["[1, 2, 3]", "{:k=>1}"], [])
def bar(*a, **kw)
Expand Down
3 changes: 3 additions & 0 deletions vm_args.c
Expand Up @@ -687,6 +687,9 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
rest_last = rb_hash_dup(rest_last);
kw_flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT;

// Unset rest_dupped set by anon_rest as we may need to modify splat in this case
args->rest_dupped = false;

if (ignore_keyword_hash_p(rest_last, iseq, &kw_flag, &converted_keyword_hash)) {
arg_rest_dup(args);
rb_ary_pop(args->rest);
Expand Down

0 comments on commit 2dbcc12

Please sign in to comment.