From 1f06f8405c8e2553574a8327944894722e147b9d Mon Sep 17 00:00:00 2001 From: Horasal <1991933+horasal@users.noreply.github.com> Date: Mon, 28 Aug 2023 20:38:11 +0900 Subject: [PATCH] handle empty pipeline while parsing let (fix Issue10083) (#10116) - fixes #10083 # Description nushell crashes in the following 2 condition: - `let a = {}` , then delete `{` - `let a = | {}`, then delete `{` When delete `{` the pipeline becomes empty but current `nu-parser` assume they are non-empty. This pr adds extra empty check to avoid crash. Co-authored-by: Horasal --- crates/nu-parser/src/parser.rs | 21 ++++++++++++++------- crates/nu-parser/tests/test_parser.rs | 12 ++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 85a510f9b1..ae1bb6a048 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -5476,10 +5476,14 @@ pub fn parse_pipeline( { let block = working_set.get_block(*block_id); - let element = block.pipelines[0].elements[0].clone(); - - if let PipelineElement::Expression(prepend, expr) = - element + if let Some(PipelineElement::Expression( + prepend, + expr, + )) = block + .pipelines + .first() + .and_then(|p| p.elements.first()) + .cloned() { if expr.has_in_variable(working_set) { let new_expr = PipelineElement::Expression( @@ -5608,9 +5612,12 @@ pub fn parse_pipeline( { let block = working_set.get_block(*block_id); - let element = block.pipelines[0].elements[0].clone(); - - if let PipelineElement::Expression(prepend, expr) = element { + if let Some(PipelineElement::Expression(prepend, expr)) = block + .pipelines + .first() + .and_then(|p| p.elements.first()) + .cloned() + { if expr.has_in_variable(working_set) { let new_expr = PipelineElement::Expression( prepend, diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index e6647e37d5..8278f702ab 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -1007,6 +1007,18 @@ mod string { } } +#[rstest] +#[case(b"let a = }")] +#[case(b"mut a = }")] +#[case(b"let a = | }")] +#[case(b"mut a = | }")] +fn test_semi_open_brace(#[case] phrase: &[u8]) { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + // this should not panic + let _block = parse(&mut working_set, None, phrase, true); +} + mod range { use super::*; use nu_protocol::ast::{RangeInclusion, RangeOperator};