Skip to content

Commit 9d08d67

Browse files
committed
shellIntegration-bash.sh: implement value-escaping for P and E codes
1 parent 01e2aad commit 9d08d67

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

src/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,43 @@ if [ -z "$VSCODE_SHELL_INTEGRATION" ]; then
3737
builtin return
3838
fi
3939

40+
# The property (P) and command (E) codes embed values which require escaping.
41+
# Backslashes are doubled. Non-alphanumeric characters are converted to escaped hex.
42+
__vsc_escape_value() {
43+
# Process text byte by byte, not by codepoint.
44+
builtin local LC_ALL=C str="${1}" i byte token out=''
45+
46+
for (( i=0; i < "${#str}"; ++i )); do
47+
byte="${str:$i:1}"
48+
49+
# Backslashes must be doubled.
50+
if [ "$byte" = "\\" ]; then
51+
token="\\\\"
52+
# Conservatively pass alphanumerics through.
53+
elif [[ "$byte" == [0-9A-Za-z] ]]; then
54+
token="$byte"
55+
# Hex-encode anything else.
56+
# (Importantly including: semicolon, newline, and control chars).
57+
else
58+
# The printf '0x%02X' "'$byte'" converts the character to a hex integer.
59+
# See printf's specification:
60+
# > If the leading character is a single-quote or double-quote, the value shall be the numeric value in the
61+
# > underlying codeset of the character following the single-quote or double-quote.
62+
# However, the result is a sign-extended int, so a high bit like 0xD7 becomes 0xFFF…FD7
63+
# We mask that word with 0xFF to get lowest 8 bits, and then encode that byte as "\xD7" per our escaping scheme.
64+
builtin printf -v token '\\x%02X' "$(( $(builtin printf '0x%X' "'$byte'") & 0xFF ))"
65+
# └──┬──┘ └┬┘└┬─┘ └─┬──┘ └──┬──┘ └───┬──┘
66+
# store in "token" ─╯ │ │ the hex value ───────────╯ │ │
67+
# the '\x…'-prefixed ─────╯ │ of the byte as an integer ────────╯ │
68+
# 0-padded, two hex digits ──╯ masked to one byte (due to sign extension) ─╯
69+
fi
70+
71+
out+="$token"
72+
done
73+
74+
builtin printf '%s\n' "${out}"
75+
}
76+
4077
# Send the IsWindows property if the environment looks like Windows
4178
if [[ "$(uname -s)" =~ ^CYGWIN*|MINGW*|MSYS* ]]; then
4279
builtin printf '\e]633;P;IsWindows=True\a'
@@ -67,12 +104,12 @@ __vsc_prompt_end() {
67104
}
68105

69106
__vsc_update_cwd() {
70-
builtin printf '\e]633;P;Cwd=%s\a' "$PWD"
107+
builtin printf '\e]633;P;Cwd=%s\a' "$(__vsc_escape_value "$PWD")"
71108
}
72109

73110
__vsc_command_output_start() {
74111
builtin printf '\e]633;C\a'
75-
builtin printf '\e]633;E;%s\a' "$__vsc_current_command"
112+
builtin printf '\e]633;E;%s\a' "$(__vsc_escape_value "${__vsc_current_command}")"
76113
}
77114

78115
__vsc_continuation_start() {

0 commit comments

Comments
 (0)