Skip to content

Commit d5fc9b5

Browse files
committed
ZJIT: Reject direct send for hash passed as positional arg to keyword-only method
1 parent 727612b commit d5fc9b5

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

zjit/src/codegen_tests.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,38 @@ fn test_send_kwarg_optional_static_with_side_exit() {
821821
"), @"[10, 2, 10]");
822822
}
823823

824+
#[test]
825+
fn test_send_hash_to_kwarg_only_method() {
826+
assert_snapshot!(inspect(r#"
827+
def callee(a:) = a
828+
829+
def entry
830+
callee({a: 1})
831+
rescue ArgumentError
832+
"ArgumentError"
833+
end
834+
835+
entry
836+
entry
837+
"#), @r#""ArgumentError""#);
838+
}
839+
840+
#[test]
841+
fn test_send_hash_to_optional_kwarg_only_method() {
842+
assert_snapshot!(inspect(r#"
843+
def callee(a: nil) = a
844+
845+
def entry
846+
callee({a: 1})
847+
rescue ArgumentError
848+
"ArgumentError"
849+
end
850+
851+
entry
852+
entry
853+
"#), @r#""ArgumentError""#);
854+
}
855+
824856
#[test]
825857
fn test_send_all_arg_types() {
826858
assert_snapshot!(inspect("

zjit/src/hir.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,15 @@ fn can_direct_send(function: &mut Function, block: BlockId, iseq: *const rb_iseq
19331933
return false;
19341934
}
19351935

1936+
// Caller passing a hash as a positional arg but callee expects keyword-only args will
1937+
// raise ArgumentError at runtime. Fall back to VM dispatch to handle this correctly.
1938+
if kwarg.is_null() && !keyword.is_null() {
1939+
if lead_num == 0 && opt_num == 0 && caller_positional > 0 {
1940+
function.set_dynamic_send_reason(send_insn, ArgcParamMismatch);
1941+
return false;
1942+
}
1943+
}
1944+
19361945
can_send
19371946
}
19381947

0 commit comments

Comments
 (0)