From 015084f5051b4e2ecc349aa3ad5cf162d9cb669f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 8 Feb 2022 14:33:21 -0600 Subject: [PATCH] Don't ever allow `~` as a startingDirectory Basically, some WSL distros ship fragments that replace the commandline with the executable for their distro (`ubuntu.exe`, etc.). We didn't exxpect that. Unfortunately, `~` is really never a valid path for a process on windows, so those distros would now fail with ``` [error 2147942667 (0x8007010b) when launching `ubuntu1804.exe'] Could not access starting directory "~" ``` * [x] Closes #12353 * [x] Tested with a (`ubuntu1804.exe`, `~`) profile - launched successfully, where 1.13 in market fails. --- src/types/ut_types/UtilsTests.cpp | 24 ++++++++++++++++++++++++ src/types/utils.cpp | 11 ++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/types/ut_types/UtilsTests.cpp b/src/types/ut_types/UtilsTests.cpp index e49ee6ef6e1..14b0ffa58b7 100644 --- a/src/types/ut_types/UtilsTests.cpp +++ b/src/types/ut_types/UtilsTests.cpp @@ -479,5 +479,29 @@ void UtilsTests::TestMangleWSLPaths() VERIFY_ARE_EQUAL(LR"("wsl" --cd "\\wsl.localhost\Ubuntu\home\user" -d Ubuntu)", commandline); VERIFY_ARE_EQUAL(L"", path); } + + /// Tests for GH #12353 + + const auto expectedUserProfilePath = wil::ExpandEnvironmentStringsW(L"%USERPROFILE%"); + { + auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(wsl -d Ubuntu)", L"~"); + VERIFY_ARE_EQUAL(LR"("wsl" --cd "~" -d Ubuntu)", commandline); + VERIFY_ARE_EQUAL(L"", path); + } + { + auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(wsl ~ -d Ubuntu)", L"~"); + VERIFY_ARE_EQUAL(LR"(wsl ~ -d Ubuntu)", commandline); + VERIFY_ARE_EQUAL(expectedUserProfilePath, path); + } + { + auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(ubuntu ~ -d Ubuntu)", L"~"); + VERIFY_ARE_EQUAL(LR"(ubuntu ~ -d Ubuntu)", commandline); + VERIFY_ARE_EQUAL(expectedUserProfilePath, path); + } + { + auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(powershell.exe)", L"~"); + VERIFY_ARE_EQUAL(LR"(powershell.exe)", commandline); + VERIFY_ARE_EQUAL(expectedUserProfilePath, path); + } } #endif diff --git a/src/types/utils.cpp b/src/types/utils.cpp index 45c6b22c9d0..ebab1255e39 100644 --- a/src/types/utils.cpp +++ b/src/types/utils.cpp @@ -600,6 +600,7 @@ bool Utils::IsElevated() std::tuple Utils::MangleStartingDirectoryForWSL(std::wstring_view commandLine, std::wstring_view startingDirectory) { + bool executableWasWSL{ false }; do { if (startingDirectory.size() > 0 && commandLine.size() >= 3) @@ -611,6 +612,7 @@ std::tuple Utils::MangleStartingDirectoryForWSL(std: const auto executableFilename{ executablePath.filename().wstring() }; if (executableFilename == L"wsl" || executableFilename == L"wsl.exe") { + executableWasWSL = true; // We've got a WSL -- let's just make sure it's the right one. if (executablePath.has_parent_path()) { @@ -670,8 +672,15 @@ std::tuple Utils::MangleStartingDirectoryForWSL(std: } } while (false); + // GH #12353: `~` is never a valid windows path. We can only accept that as + // a startingDirectory when the exe is specifically wsl.exe, because that + // can override the real startingDirectory. If the user set the + // startingDirectory to ~, but the commandline to something like pwsh.exe, + // that won't actually work. In that case, mangle the startingDirectory to + // %userprofile%, so it's at least something reasonable. return { std::wstring{ commandLine }, - std::wstring{ startingDirectory } + std::wstring{ startingDirectory == L"~" ? wil::ExpandEnvironmentStringsW(L"%USERPROFILE%") : + startingDirectory } }; }