From: "k0kubun (Takashi Kokubun) via ruby-core" Date: 2026-11-04T02:21:15+00:00 Subject: [ruby-core:127324] [Ruby Bug#22504] Empty keyword hash mishandled when calling a Method proc through the C API Issue #22504 has been updated by k0kubun (Takashi Kokubun). merged https://github.com/ruby/ruby/pull/19607 to master ---------------------------------------- Bug #22504: Empty keyword hash mishandled when calling a Method proc through the C API https://bugs.ruby-lang.org/issues/22504#change-119753 * Author: nozomemein (Nozomi Hijikata) * Status: Closed * ruby -v: ruby 4.0.9 (2026-10-23 revision 3e93b23afc) +PRISM [arm64-darwin25] * Backport: 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- Calling a Proc created by `Method#to_proc` through `rb_proc_call_kw` or `rb_proc_call_with_block_kw` with `RB_PASS_KEYWORDS` and an empty keyword hash can raise `TypeError`, even though the equivalent Ruby call succeeds. ### Reproduction ```rb # extconf.rb require "mkmf" create_makefile("proc_kw") ``` ```c // proc_kw.c #include "ruby.h" static VALUE call_kw(VALUE self, VALUE proc, VALUE args) { return rb_proc_call_kw(proc, args, RB_PASS_KEYWORDS); } static VALUE call_with_block_kw(VALUE self, VALUE proc, VALUE args) { return rb_proc_call_with_block_kw(proc, RARRAY_LENINT(args), RARRAY_PTR(args), Qnil, RB_PASS_KEYWORDS); } void Init_proc_kw(void) { VALUE mod = rb_define_module("ProcKW"); rb_define_singleton_method(mod, "call_kw", call_kw, 2); rb_define_singleton_method(mod, "call_with_block_kw", call_with_block_kw, 2); } ``` ```rb # repro.rb require_relative "proc_kw" def target(*args, **kwargs) = [args, kwargs] pr = method(:target).to_proc p pr.call(1, **{}) # => [[1], {}] p ProcKW.call_kw(pr, [1, {}]) # => TypeError. This should be [[1], {}]. p ProcKW.call_with_block_kw(pr, [1, {}]) # => TypeError. This should be [[1], {}]. ``` ```sh ruby extconf.rb make ruby repro.rb ``` ### Cause and proposed fix In the `block_type_ifunc` branch of `invoke_block_from_c_proc`, the empty keyword hash is removed by decrementing `argc`, but `kw_splat` remains set. The forwarded call consequently treats the last positional argument as a keyword hash. [PR #19607](https://github.com/ruby/ruby/pull/19607) clears `kw_splat` when removing the empty keyword hash, matching `CALLER_SETUP_ARG`. This was originally reported through ZJIT in [Shopify/ruby#1092](https://github.com/Shopify/ruby/issues/1092) , but the underlying VM bug also affects these C APIs independently of ZJIT. I also confirmed this on Ruby 3.3.13 and 3.4.12 ### Backport consideration Should this fix also be backported? -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/