Skip to content

Commit

Permalink
Disallow escaped characters in variable expansion
Browse files Browse the repository at this point in the history
Prior to this fix, an escaped character like \x41 (hex for ascii A)
was interpreted the same was as A, so that $\x41 would be the same
as $A. Fix this by inserting an INTERNAL_SEPARATOR before these escapes,
so that we no longer treat it as part of the variable name.

This also affects brackets; don't treat echo $foo\1331\135 the same as
echo $foo[1].

Fixes #7969
  • Loading branch information
ridiculousfish committed May 5, 2021
1 parent 3f35012 commit 555af37
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Notable improvements and fixes

Syntax changes and new commands
-------------------------------
- Escaped characters like ``\x41`` are no longer valid in a variable name (:issue:`7969`).

Deprecations and removed features
---------------------------------
Expand Down
5 changes: 4 additions & 1 deletion src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ static maybe_t<wchar_t> string_last_char(const wcstring &str) {
}

/// Given a null terminated string starting with a backslash, read the escape as if it is unquoted,
/// appending to result. Return the number of characters consumed, or 0 on error.
/// appending to result. Return the number of characters consumed, or none on error.
maybe_t<size_t> read_unquoted_escape(const wchar_t *input, wcstring *result, bool allow_incomplete,
bool unescape_special) {
assert(input[0] == L'\\' && "Not an escape");
Expand Down Expand Up @@ -1244,6 +1244,9 @@ maybe_t<size_t> read_unquoted_escape(const wchar_t *input, wcstring *result, boo
}

if (res <= max_val) {
// Prepend internal sep so this does not get treated as part of a variable.
// See #7969.
if (unescape_special) result->push_back(INTERNAL_SEPARATOR);
result_char_or_none =
static_cast<wchar_t>((byte_literal ? ENCODE_DIRECT_BASE : 0) + res);
} else {
Expand Down
14 changes: 14 additions & 0 deletions tests/checks/slices.fish
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,17 @@ echo $list # CHECK: 2 1 3
set -l list 1 2 3
set list[2..] $list[-1..2]
echo $list # CHECK: 1 3 2

# Regression test for #7969.
set fo shorty
set foo A B C
echo $foo[1]
# CHECK: A
echo $foo\1331\135
# CHECK: A[1] B[1] C[1]
echo $foo\x5b1\x5d
# CHECK: A[1] B[1] C[1]
echo $foo\1331\135
# CHECK: A[1] B[1] C[1]
echo $fo\157
# CHECK: shortyo

0 comments on commit 555af37

Please sign in to comment.