From 076ca02a120f545345f9ef3cbde29c16c5b7dd71 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 8 Feb 2022 18:16:35 -0600 Subject: [PATCH] Don't ever allow `~` as a startingDirectory (#12437) Basically, some WSL distros ship fragments that replace the `commandline` with the executable for their distro (`ubuntu.exe`, etc.). We didn't expect that when we changed the `startingDirectory` for them all to `~`. 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 "~" ``` If we find that we were unable to mangle `~` into the user's WSL `commandline`, then we will re-evaluate that `startingDirectory` as `%USERPROFILE%`, which is at least something sensible, if albeit not what they wanted. * regressed in #12315 * [x] Closes #12353 * [x] Tested with a (`ubuntu1804.exe`, `~`) profile - launched successfully, where 1.13 in market fails. * [x] added tests (cherry picked from commit 1870feeca3db191355aa45dd8cc910ede1c9e222) --- src/types/ut_types/UtilsTests.cpp | 24 ++++++++++++++++++++++++ src/types/utils.cpp | 9 ++++++++- 2 files changed, 32 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..4f8a1fd0974 100644 --- a/src/types/utils.cpp +++ b/src/types/utils.cpp @@ -670,8 +670,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 } + startingDirectory == L"~" ? wil::ExpandEnvironmentStringsW(L"%USERPROFILE%") : + std::wstring{ startingDirectory } }; }