From f3a1dfef95b1f7fd1ff44d22479e423d89e753bd Mon Sep 17 00:00:00 2001 From: Kither <61571510+Kither12@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:37:03 +0700 Subject: [PATCH] Fix panic if tokens are placed after a redirection (#14035) # Description fixes #13835 The `concat` function from `span.rs` assumes that two consecutive span intervals must overlap. But when parsing `let` and `mut` expressions, we call `parts_including_redirection` which chains two slices of span and leads to the above condition not holding. So my solution here is to sort them after chaining. # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-parser/src/lite_parser.rs | 14 +++++++++----- crates/nu-parser/tests/test_parser.rs | 12 ++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/nu-parser/src/lite_parser.rs b/crates/nu-parser/src/lite_parser.rs index 0be57a7c9a..1a89271af2 100644 --- a/crates/nu-parser/src/lite_parser.rs +++ b/crates/nu-parser/src/lite_parser.rs @@ -136,11 +136,15 @@ impl LiteCommand { } pub fn parts_including_redirection(&self) -> impl Iterator + '_ { - self.parts.iter().copied().chain( - self.redirection - .iter() - .flat_map(|redirection| redirection.spans()), - ) + self.parts + .iter() + .copied() + .chain( + self.redirection + .iter() + .flat_map(|redirection| redirection.spans()), + ) + .sorted_unstable_by_key(|a| (a.start, a.end)) } } diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index 1ac3d7e900..c0722d64e4 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -1243,6 +1243,18 @@ fn test_nothing_comparison_eq() { assert!(matches!(&element.expr.expr, Expr::BinaryOp(..))); } +#[rstest] +#[case(b"let a o> file = 1")] +#[case(b"mut a o> file = 1")] +fn test_redirection_inside_letmut_no_panic(#[case] phase: &[u8]) { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + working_set.add_decl(Box::new(Let)); + working_set.add_decl(Box::new(Mut)); + + parse(&mut working_set, None, phase, true); +} + #[rstest] #[case(b"let a = 1 err> /dev/null")] #[case(b"let a = 1 out> /dev/null")]