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

(cherry picked from commit 48704dc612)
This commit is contained in:
Johannes Altmanninger
2025-05-02 06:38:20 +02:00
parent 35849c57dc
commit 6fb22a4fd1
2 changed files with 11 additions and 3 deletions

View File

@@ -227,13 +227,16 @@ fn process_opening_quote(
inout_is_quoted: &mut Option<&mut bool>,
paran_count: i32,
quoted_cmdsubs: &mut Vec<i32>,
pos: usize,
mut pos: usize,
last_dollar: &mut Option<usize>,
quote: Quote,
) -> Option<usize> {
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.
@@ -266,7 +269,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() {

View File

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