Skip to content

Commit

Permalink
Escape single quotes while translating dropped Win32 paths
Browse files Browse the repository at this point in the history
When file/folder is dropped to the terminal, its path is translated and
quoted with a pair of single quotes if necessary.

However, despite that the Win32 subsystem allows single quote, the
terminal control does not escape it.  It causes a path containing one or
more single quotes incorrect on the POSIX shell context
(see Issue #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).
  • Loading branch information
a4lg committed Nov 22, 2024
1 parent 6047f37 commit d7b92af
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
/* Cygwin */ L"/cygdrive/",
/* MSYS2 */ L"/",
};
static constexpr wil::zwstring_view sSingleQuoteEscape = L"'\\''";
static constexpr auto cchSingleQuoteEscape = sSingleQuoteEscape.size();

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

// Escape single quotes, assuming translated paths are always quoted by single quotes.
size_t pos = 0;
while ((pos = fullPath.find(L'\'', pos)) != std::wstring::npos)
{
// ' -> '\''
fullPath.replace(pos, 1, sSingleQuoteEscape);
// Arithmetic overflow is not a problem since an exception would have thrown above on such cases.
pos += cchSingleQuoteEscape;
}

if (fullPath.size() >= 2 && fullPath.at(1) == L':')
{
// C:/foo/bar -> Cc/foo/bar
Expand Down

0 comments on commit d7b92af

Please sign in to comment.