Project

General

Profile

Actions

Bug #20230

closed

Fix crash when passing large keyword splat to method accepting keywords and keyword splat

Added by jeremyevans0 (Jeremy Evans) 3 months ago. Updated 3 months ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:116523]

Description

The following code causes a crash in Ruby 2.2-3.3 and master:

h = {}
1000000.times{|i| h[i.to_s.to_sym] = i}
def f(kw: 1, **kws) end
f(**h)

Inside a thread or fiber, the size of the keyword splat could be much smaller and still cause a crash. This is similar to the issue in #4040, but for keyword splats instead of positional splats.

I found this issue while optimizing method calling by reducing implicit allocations. Given the following code:

def f(kw: , **kws) end
kw = {kw: 1}
f(**kw)

The f(**kw) call previously allocated two hashes callee side instead of a single hash. This is because setup_parameters_complex would extract the keywords from the keyword splat hash to the C stack, to attempt to mirror the case when literal keywords are passed without a keyword splat. Then, make_rest_kw_hash would build a new hash based on the extracted keywords that weren't used for literal keywords.

I have submitted a pull request which changes the implementation so that if a keyword splat is passed, literal keywords are deleted from the keyword splat hash (or a copy of the hash if the hash is not mutable): https://github.com/ruby/ruby/pull/9776

In addition to fixing the bug, the new implementation also eliminates the unnecessary hash allocation.

Updated by jeremyevans0 (Jeremy Evans) 3 months ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF

Like0
Like0