1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

YJIT: Fix check for required kwargs

Previously, YJIT would not check that all the required keywords were
specified in the case that there were optional arguments specified. In
this case YJIT would incorrectly call the method with invalid arguments.
This commit is contained in:
John Hawthorn 2021-12-16 15:08:07 -08:00
parent 83aa68447c
commit c2197bf821
Notes: git 2021-12-18 08:26:25 +09:00
2 changed files with 19 additions and 2 deletions

View file

@ -2234,6 +2234,14 @@ assert_equal '[:ok]', %q{
5.times.map { kwargs() rescue :ok }.uniq
}
assert_equal '[:ok]', %q{
def kwargs(a:, b: nil)
value
end
5.times.map { kwargs(b: 123) rescue :ok }.uniq
}
assert_equal '[[1, 2]]', %q{
def kwargs(left:, right:)
[left, right]

View file

@ -3562,6 +3562,8 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r
// keyword parameters.
const struct rb_iseq_param_keyword *keyword = iseq->body->param.keyword;
int required_kwargs_filled = 0;
if (keyword->num > 30) {
// We have so many keywords that (1 << num) encoded as a FIXNUM
// (which shifts it left one more) no longer fits inside a 32-bit
@ -3604,9 +3606,16 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r
GEN_COUNTER_INC(cb, send_iseq_kwargs_mismatch);
return YJIT_CANT_COMPILE;
}
// Keep a count to ensure all required kwargs are specified
if (callee_idx < keyword->required_num) {
required_kwargs_filled++;
}
}
} else if (keyword->required_num != 0) {
// No keywords provided so if any are required this is a mismatch
}
RUBY_ASSERT(required_kwargs_filled <= keyword->required_num);
if (required_kwargs_filled != keyword->required_num) {
GEN_COUNTER_INC(cb, send_iseq_kwargs_mismatch);
return YJIT_CANT_COMPILE;
}