Fix regression causing crash indenting commandline with "$()"

Commit b00899179f (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 4c43819d32 (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
This commit is contained in:
Johannes Altmanninger
2025-05-02 06:38:20 +02:00
parent 8abab0e2cc
commit 48704dc612
2 changed files with 11 additions and 3 deletions

View File

@@ -229,13 +229,16 @@ fn process_opening_quote(
inout_is_quoted: &mut Option<&mut bool>, inout_is_quoted: &mut Option<&mut bool>,
paran_count: i32, paran_count: i32,
quoted_cmdsubs: &mut Vec<i32>, quoted_cmdsubs: &mut Vec<i32>,
pos: usize, mut pos: usize,
last_dollar: &mut Option<usize>, last_dollar: &mut Option<usize>,
quote: Quote, quote: Quote,
) -> Option<usize> { ) -> Option<usize> {
let quote = match quote { let quote = match quote {
Quote::Real(q) => q, Quote::Real(q) => q,
Quote::VirtualDouble => '"', Quote::VirtualDouble => {
pos = pos.saturating_sub(1);
'"'
}
}; };
let q_end = quote_end(input.into(), pos, quote)?; let q_end = quote_end(input.into(), pos, quote)?;
// Found a valid closing quote. // Found a valid closing quote.
@@ -268,7 +271,7 @@ fn process_opening_quote(
&mut last_dollar, &mut last_dollar,
Quote::VirtualDouble, Quote::VirtualDouble,
) )
.unwrap_or(input.len()); .map_or(input.len(), |pos| pos + 1);
} }
while pos < input.len() { while pos < input.len() {

View File

@@ -441,5 +441,10 @@ macro_rules! validate {
0, r#"echo "$()"'"#, 0, r#"echo "$()"'"#,
0, "\n" 0, "\n"
); );
validate!(
0, r#"""#,
0, "\n",
0, r#"$()"$() ""#
);
})(); })();
} }