summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2024-07-08 16:08:42 -0700
committerTakashi Kokubun <[email protected]>2024-07-08 16:08:42 -0700
commit17e21d815583ef7d6be03f29e90a219602497626 (patch)
tree8d94cd4ef7fad0307f69ef03fbd3945e6eb07cf6
parentdf8a08fb6a1f173a9c25db15fbe390096f39c2ff (diff)
merge revision(s) fc33559c: [Backport #20570]
clear `kw_flag` if given hash is nil https://bugs.ruby-lang.org/issues/20570 is caused I missed to clear the `kw_flag` even if `keyword_hash` is nil.
-rw-r--r--test/ruby/test_keyword.rb18
-rw-r--r--version.h2
-rw-r--r--vm_args.c21
3 files changed, 34 insertions, 7 deletions
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 9aca787dff..bc816751fd 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -4432,6 +4432,24 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_equal({one: 1, two: 2}, f.call(one:, two:))
end
+ def m_bug20570(*a, **nil)
+ a
+ end
+
+ def test_splat_arg_with_prohibited_keyword
+ assert_equal([], m_bug20570(*[]))
+ assert_equal([1], m_bug20570(*[1]))
+ assert_equal([1, 2], m_bug20570(*[1, 2]))
+ h = nil
+ assert_equal([], m_bug20570(*[], **h))
+ assert_equal([1], m_bug20570(*[1], **h))
+ assert_equal([1, 2], m_bug20570(*[1, 2], **h))
+
+ assert_equal([], m_bug20570(*[], **nil))
+ assert_equal([1], m_bug20570(*[1], **nil))
+ assert_equal([1, 2], m_bug20570(*[1, 2], **nil))
+ end
+
private def one
1
end
diff --git a/version.h b/version.h
index dd442f5c6b..f7a72f688c 100644
--- a/version.h
+++ b/version.h
@@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 3
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 93
+#define RUBY_PATCHLEVEL 94
#include "ruby/version.h"
#include "ruby/internal/abi.h"
diff --git a/vm_args.c b/vm_args.c
index 14ae550d2f..1b720a89c4 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -434,7 +434,10 @@ fill_keys_values(st_data_t key, st_data_t val, st_data_t ptr)
static inline int
ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned int * kw_flag, VALUE * converted_keyword_hash)
{
- if (!RB_TYPE_P(keyword_hash, T_HASH)) {
+ if (keyword_hash == Qnil) {
+ goto ignore;
+ }
+ else if (!RB_TYPE_P(keyword_hash, T_HASH)) {
keyword_hash = rb_to_hash_type(keyword_hash);
}
@@ -445,9 +448,17 @@ ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned
keyword_hash = rb_hash_dup(keyword_hash);
}
*converted_keyword_hash = keyword_hash;
- return !(ISEQ_BODY(iseq)->param.flags.has_kw) &&
- !(ISEQ_BODY(iseq)->param.flags.has_kwrest) &&
- RHASH_EMPTY_P(keyword_hash);
+
+ if (!(ISEQ_BODY(iseq)->param.flags.has_kw) &&
+ !(ISEQ_BODY(iseq)->param.flags.has_kwrest) &&
+ RHASH_EMPTY_P(keyword_hash)) {
+ ignore:
+ *kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT);
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
static VALUE
@@ -577,7 +588,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
arg_rest_dup(args);
rb_ary_pop(args->rest);
given_argc--;
- kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT);
}
else {
if (rest_last != converted_keyword_hash) {
@@ -608,7 +618,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
if (ignore_keyword_hash_p(last_arg, iseq, &kw_flag, &converted_keyword_hash)) {
args->argc--;
given_argc--;
- kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT);
}
else {
if (!(kw_flag & VM_CALL_KW_SPLAT_MUT)) {