Skip to content

Commit c0fccaa

Browse files
committed
Coerce SyntaxError location argument from any sequence
The second argument to SyntaxError(msg, ...) is now coerced from any sequence like CPython's PySequence_Tuple, so a list works and a non-sequence raises TypeError, instead of the exact-tuple downcast that silently dropped both cases. Assisted-by: Claude Code:claude-fable-5
1 parent 172292a commit c0fccaa

1 file changed

Lines changed: 15 additions & 20 deletions

File tree

crates/vm/src/exceptions.rs

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,14 +2783,7 @@ pub(super) mod types {
27832783

27842784
fn slot_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
27852785
let msg = args.args.first().cloned();
2786-
let location_tuple = if args.args.len() == 2 {
2787-
args.args[1]
2788-
.clone()
2789-
.downcast::<crate::builtins::PyTuple>()
2790-
.ok()
2791-
} else {
2792-
None
2793-
};
2786+
let location_arg = (args.args.len() == 2).then(|| args.args[1].clone());
27942787

27952788
PyBaseException::slot_init(zelf.clone(), args, vm)?;
27962789
let exc: &Py<Self> = zelf.downcast_ref::<Self>().unwrap();
@@ -2800,19 +2793,21 @@ pub(super) mod types {
28002793
}
28012794

28022795
// SyntaxError(msg, (filename, lineno, offset, text[, end_lineno, end_offset]))
2803-
if let Some(location_tuple) = location_tuple {
2804-
let location_tup_len = location_tuple.len();
2796+
// The location argument is coerced from any sequence like CPython's
2797+
// PySequence_Tuple; a non-sequence raises TypeError.
2798+
if let Some(location_arg) = location_arg {
2799+
let location: Vec<PyObjectRef> = location_arg.try_to_value(vm)?;
28052800

2806-
match location_tup_len {
2801+
match location.len() {
28072802
4 | 6 => {}
28082803
5 => {
28092804
return Err(vm.new_type_error(
28102805
"end_offset must be provided when end_lineno is provided",
28112806
));
28122807
}
2813-
_ => {
2808+
len => {
28142809
return Err(vm.new_type_error(format!(
2815-
"function takes exactly 4 or 6 arguments ({location_tup_len} given)"
2810+
"function takes exactly 4 or 6 arguments ({len} given)"
28162811
)));
28172812
}
28182813
}
@@ -2821,18 +2816,18 @@ pub(super) mod types {
28212816
exc.end_offset.swap_to_temporary_refs(None, vm);
28222817

28232818
exc.filename
2824-
.swap_to_temporary_refs(Some(location_tuple[0].to_owned()), vm);
2819+
.swap_to_temporary_refs(Some(location[0].clone()), vm);
28252820
exc.lineno
2826-
.swap_to_temporary_refs(Some(location_tuple[1].to_owned()), vm);
2821+
.swap_to_temporary_refs(Some(location[1].clone()), vm);
28272822
exc.offset
2828-
.swap_to_temporary_refs(Some(location_tuple[2].to_owned()), vm);
2823+
.swap_to_temporary_refs(Some(location[2].clone()), vm);
28292824
exc.text
2830-
.swap_to_temporary_refs(Some(location_tuple[3].to_owned()), vm);
2831-
if location_tup_len == 6 {
2825+
.swap_to_temporary_refs(Some(location[3].clone()), vm);
2826+
if location.len() == 6 {
28322827
exc.end_lineno
2833-
.swap_to_temporary_refs(Some(location_tuple[4].to_owned()), vm);
2828+
.swap_to_temporary_refs(Some(location[4].clone()), vm);
28342829
exc.end_offset
2835-
.swap_to_temporary_refs(Some(location_tuple[5].to_owned()), vm);
2830+
.swap_to_temporary_refs(Some(location[5].clone()), vm);
28362831
}
28372832
}
28382833

0 commit comments

Comments
 (0)