From 48704dc6129632dc4fa8f38c13f2786ccb68ba9f Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Fri, 2 May 2025 06:38:20 +0200 Subject: [PATCH] Fix regression causing crash indenting commandline with "$()" Commit b00899179f1 (Don't indent multi-line quoted strings; do indent inside (), 2024-04-28) changed how we compute indents for string tokens with command substitutions: echo "begin not indented end $( begin indented end)"( begin indented end ) For the leading quoted part of the string, we compute indentation only for the first character (the opening quote), see 4c43819d329 (Fix crash indenting quoted suffix after command substitution, 2024-09-28). The command substitutions, we do indent as usual. To implement the above, we need to separate quoted from non-quoted parts. This logic crashes when indent_string_part() is wrongly passed is_double_quoted=true. This is because, given the string "$()"$(), parse_util_locate_cmdsub calls quote_end() at index 4 (the second quote). This is wrong because that function should only be called at opening quotes; this is a closing quote. The opening quote is virtual here. Hack around this. Fixes #11444 --- src/parse_util.rs | 9 ++++++--- src/tests/parse_util.rs | 5 +++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/parse_util.rs b/src/parse_util.rs index bfc20929f..a403481df 100644 --- a/src/parse_util.rs +++ b/src/parse_util.rs @@ -229,13 +229,16 @@ fn process_opening_quote( inout_is_quoted: &mut Option<&mut bool>, paran_count: i32, quoted_cmdsubs: &mut Vec, - pos: usize, + mut pos: usize, last_dollar: &mut Option, quote: Quote, ) -> Option { let quote = match quote { Quote::Real(q) => q, - Quote::VirtualDouble => '"', + Quote::VirtualDouble => { + pos = pos.saturating_sub(1); + '"' + } }; let q_end = quote_end(input.into(), pos, quote)?; // Found a valid closing quote. @@ -268,7 +271,7 @@ fn process_opening_quote( &mut last_dollar, Quote::VirtualDouble, ) - .unwrap_or(input.len()); + .map_or(input.len(), |pos| pos + 1); } while pos < input.len() { diff --git a/src/tests/parse_util.rs b/src/tests/parse_util.rs index b41a94649..3402bc967 100644 --- a/src/tests/parse_util.rs +++ b/src/tests/parse_util.rs @@ -441,5 +441,10 @@ macro_rules! validate { 0, r#"echo "$()"'"#, 0, "\n" ); + validate!( + 0, r#"""#, + 0, "\n", + 0, r#"$()"$() ""# + ); })(); }