Don't use results of quoted command substitution in adjacent variable expansion

Given

    set var a
    echo "$var$(echo b)"

the double-quoted string is expanded right-to-left, so we construct an
intermediate "$varb".  Since the variable "varb" is undefined, this wrongly
expands to the empty string (should be "ab"). Fix this by isolating the
expanded command substitution internally. We do the same when handling
unquoted command substitutions.

Fixes #8849
This commit is contained in:
Johannes Altmanninger 2022-04-03 11:06:40 +02:00
parent 1a0b1ae238
commit 1b668f5675
3 changed files with 6 additions and 0 deletions

View File

@ -19,6 +19,7 @@ Deprecations and removed features
Scripting improvements Scripting improvements
---------------------- ----------------------
- Quoted command substitution that directly follow a variable expansion (like ``echo "$var$(echo x)"``) no longer affect the variable expansion (:issue:`8849`).
- ``math`` can now handle underscores (``_``) as visual separators in numbers (:issue:`8611`, :issue:`8496`):: - ``math`` can now handle underscores (``_``) as visual separators in numbers (:issue:`8611`, :issue:`8496`)::
math 5 + 2_123_252 math 5 + 2_123_252

View File

@ -758,7 +758,9 @@ static expand_result_t expand_cmdsubst(wcstring input, const operation_context_t
whole_item.reserve(paren_begin + 1 + sub_res_joined.size() + 1 + whole_item.reserve(paren_begin + 1 + sub_res_joined.size() + 1 +
tail_item.completion.size()); tail_item.completion.size());
whole_item.append(input, 0, paren_begin - have_dollar); whole_item.append(input, 0, paren_begin - have_dollar);
whole_item.push_back(INTERNAL_SEPARATOR);
whole_item.append(sub_res_joined); whole_item.append(sub_res_joined);
whole_item.push_back(INTERNAL_SEPARATOR);
whole_item.append(tail_item.completion.substr(const_strlen(L"\""))); whole_item.append(tail_item.completion.substr(const_strlen(L"\"")));
if (!out->add(std::move(whole_item))) { if (!out->add(std::move(whole_item))) {
return append_overflow_error(errors); return append_overflow_error(errors);

View File

@ -63,3 +63,6 @@ echo "($(echo A)B$(echo C))"
echo "quoted1""quoted2"(echo unquoted3)"$(echo quoted4)_$(echo quoted5)" echo "quoted1""quoted2"(echo unquoted3)"$(echo quoted4)_$(echo quoted5)"
# CHECK: quoted1quoted2unquoted3quoted4_quoted5 # CHECK: quoted1quoted2unquoted3quoted4_quoted5
var=a echo "$var$(echo b)"
# CHECK: ab