Project

General

Profile

Actions

Bug #21757

closed

Splatted args array is mutated when passing unexpected kwargs

Bug #21757: Splatted args array is mutated when passing unexpected kwargs

Added by apotonick (Nick Sutterer) 23 days ago. Updated 16 days ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 3.4.7 (2025-10-08 revision 7a5688e2a2) +PRISM [x86_64-linux]
[ruby-core:123980]

Description

The bug is very simple to provoke.

proc = ->(*) { } # we do NOT expect any keyword arguments.

args = [1, 2]

proc.(*args, bug: true)

pp args #=> [1, 2, {bug: true}]

The args array now has a third element which is exactly what got passed as keyword arguments. This is only in Ruby 3.4, 3.3 and below discard the "unexpected" keyword arguments as expected.

Updated by jeremyevans0 (Jeremy Evans) 23 days ago Actions #1 [ruby-core:123984]

  • Assignee set to jeremyevans0 (Jeremy Evans)
  • Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.2: DONTNEED, 3.3: DONTNEED, 3.4: REQUIRED

Thank you for the report. This is a bug in the allocationless anonymous splat optimization in Ruby 3.4, still present in the master branch. I'll work on a fix.

Updated by jeremyevans0 (Jeremy Evans) 23 days ago Actions #2 [ruby-core:123991]

I submitted a pull request to fix this: https://github.com/ruby/ruby/pull/15383

Updated by jeremyevans (Jeremy Evans) 16 days ago Actions #3

  • Status changed from Open to Closed

Applied in changeset git|6409715212d22699bd2751a363b050a5d8b94b83.


Fix allocationless anonymous splat keyword argument check

Previously, if an argument splat and keywords are provided by
the caller, it did not check whether the method/proc accepted
keywords before avoiding the allocation. This is incorrect,
because if the method/proc does not accept keywords, the
keywords passed by the caller are added as a positional
argument, so there must be an allocation to avoid mutating
the positional splat argument.

Add a check that if the caller passes keywords, the
method/proc must accept keywords in order to optimize.
If the caller passes a keyword splat, either the
method/proc must accept keywords, or the keyword splat must
be empty in order to optimize.

If keywords are explicitly disallowed via **nil, the
optimization should be skipped, because the array is mutated
before the ArgumentError exception is raised.

In addition to a test for the correct behavior, add an
allocation test for a method that accepts an anonymous splat
without keywords.

Fixes [Bug #21757]

Actions

Also available in: PDF Atom