Skip to content

Commit dc855f7

Browse files
a4lgDHowett
authored andcommitted
Escape single quotes while translating dropped Win32 paths (#18007)
When file/folder is dropped to the terminal, its path is translated and quoted with a pair of single quotes if necessary. However, the terminal control does not escape single quotes (allowed in the Win32 subsystem) that need escapes when translated. On the translation styles other than `"none"` (note: all other translation styles are currently intended for the POSIX shell), it causes incorrect path to be pasted when the path contains one or more single quotes (see #18006 for an example). With this commit, the terminal control escapes a single quote with a valid escape sequence `'\''` (finish quote, print a single quote then begin quote again) when the path translation is required. * Changed escape sequence from `'"'"'` to much shorter `'\''`. * Reflected comments by the reviewer. * Overhaul after addition of multiple path translation styles (not just WSL but Cygwin and MSYS). * More clarification both in the code and in the commit message. * Minor clarification both in the code and in the commit message. * #18006 * #16214 * #18195 This is a follow-up of #16214 and #18195, fixing #18006. Closes #18006 Supersedes 7878728 (cherry picked from commit ae90d52) Service-Card-Id: PVTI_lADOAF3p4s4AmhmQzgVEvdU Service-Version: 1.22
1 parent 0ac82a8 commit dc855f7

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

src/cascadia/TerminalControl/TermControl.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
6666
/* Cygwin */ L"/cygdrive/",
6767
/* MSYS2 */ L"/",
6868
};
69+
static constexpr wil::zwstring_view sSingleQuoteEscape = L"'\\''";
70+
static constexpr auto cchSingleQuoteEscape = sSingleQuoteEscape.size();
6971

7072
if (translationStyle == PathTranslationStyle::None)
7173
{
@@ -75,6 +77,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
7577
// All of the other path translation modes current result in /-delimited paths
7678
std::replace(fullPath.begin(), fullPath.end(), L'\\', L'/');
7779

80+
// Escape single quotes, assuming translated paths are always quoted by a pair of single quotes.
81+
size_t pos = 0;
82+
while ((pos = fullPath.find(L'\'', pos)) != std::wstring::npos)
83+
{
84+
// ' -> '\'' (for POSIX shell)
85+
fullPath.replace(pos, 1, sSingleQuoteEscape);
86+
// Arithmetic overflow cannot occur here.
87+
pos += cchSingleQuoteEscape;
88+
}
89+
7890
if (fullPath.size() >= 2 && fullPath.at(1) == L':')
7991
{
8092
// C:/foo/bar -> Cc/foo/bar

0 commit comments

Comments
 (0)