Bug #21865
closedCrash on signal raise
Description
This crashes on Ruby 4.0
$ ruby -e 'loop { File.open("./test.rb", kwarg: true) {} }'&
[1] 93542
$ kill -TERM 93542
[BUG] Segmentation fault at 0x000000000000001f
Note the 0x1f (i.e. 15, which is Signal.list["TERM"]).
While preparing the exception we pass argc=2, with argv containing the signal class and the fixnum for the TERM. https://github.com/ruby/ruby/blob/86dba8cfaeabb3b86df921da24b3243b9ce4ab2a/thread.c#L2759-L2766
That eventually gets passed through to https://github.com/ruby/ruby/blob/86dba8cfaeabb3b86df921da24b3243b9ce4ab2a/class.c#L3162-L3165, where we set the signal fixnum as last and treat it like a hash. But 0x1f is a fixnum, not a hash, so that crashes.
rb_scan_args_keyword_p returns true in this case even though last is not a hash because kw_flag is RB_SCAN_ARGS_PASS_CALLED_KEYWORDS (which I think causes it to look at the last frame to see if keywords were passed, rather than checking whether last is a hash. I don't think we push any frames in this case, so it's looking at whatever the last frame before the signal happened to be). Should we still check that it's a hash regardless?
I believe the bug was introduced in https://github.com/ruby/ruby/commit/64f508ade8c8535b7d3ecdd217886aa52fddd43c.