Project

General

Profile

Actions

Bug #22504

closed

Empty keyword hash mishandled when calling a Method proc through the C API

Bug #22504: Empty keyword hash mishandled when calling a Method proc through the C API

Added by nozomemein (Nozomi Hijikata) 5 days ago. Updated 5 days ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 4.0.9 (2026-10-23 revision 3e93b23afc) +PRISM [arm64-darwin25]
[ruby-core:127322]

Description

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

# extconf.rb
require "mkmf"
create_makefile("proc_kw")
// 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);
}
# 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], {}].
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 clears kw_splat when removing the empty keyword hash, matching CALLER_SETUP_ARG.

This was originally reported through ZJIT in Shopify/ruby#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?

Actions

Also available in: PDF Atom