@samitouri / QOSAMI-WSL / commits / c14172d1

Fix incorrect wslpath translatation of \\wsl.localhost when the current distro is a subset of the target distro (#40687)

* Fix incorrect wslpath translatation of \\wsl.localhost when the current distro is a subset of the target distro * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Format * Restore CRLF line endings in test/linux/unit_tests/wslpath.c The previous format commit inadvertently converted wslpath.c from CRLF to LF, making the diff appear to touch every line and diverging from the line-ending convention used by the rest of test/linux/unit_tests/ (which is CRLF). Also drop a stray carriage return on the `Validate that distro names ...` comment so the line parses as plain CRLF and clang-format stops flagging it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Blue committed Jun 5, 2026 at 12:37 UTC c14172d10e04544883f92909190370e21437aa27
4 files changed +50 -14
src/linux/init/util.cpp
+15 -2
@@ -3168,8 +3168,21 @@ try
3168 }
3169 else
3170 {
3171 + auto matchesPrefix = [Path](const std::string_view& prefix) {
3172 + if (!wsl::shared::string::StartsWith(Path, prefix, true))
3173 + {
3174 + return false;
3175 + }
3176 +
3177 + // Validate that the next character is a path separator or the end of the string to prevent matching other distribution paths like:
3178 + // \\wsl.localhost\<distro-name>-<suffix>
3179 +
3180 + auto nextChar = Path[prefix.size()];
3181 + return nextChar == '\0' || nextChar == PATH_SEP || nextChar == PATH_SEP_NT;
3182 + };
3183 +
3184 auto PrefixLength = Prefix.length();
3172 - if (!wsl::shared::string::StartsWith(Path, Prefix, true))
3185 + if (!matchesPrefix(Prefix))
3186 {
3187 //
3188 // Check the old \\wsl$ prefix if it's not \\wsl.localhost.
@@ -3177,7 +3190,7 @@ try
3190
3191 std::string CompatPrefix{PLAN9_RDR_COMPAT_PREFIX};
3192 CompatPrefix += DistributionName;
3180 - if (!wsl::shared::string::StartsWith(Path, CompatPrefix, true))
3193 + if (!matchesPrefix(CompatPrefix))
3194 {
3195 return {};
3196 }
test/linux/unit_tests/lxtutil.c
+24 -10
@@ -492,13 +492,15 @@ int LxtCheckWslPathTranslation(char* Path, const char* ExpectedPath, bool WinPat
492 Description:
493
494 This routine checks whether translating a path with wslpath matches the
495 - specified result.
495 + specified result. Pass NULL as ExpectedPath to assert that wslpath fails
496 + to translate the path.
497
498 Arguments:
499
500 Path - Supplies the path to translate.
501
501 - ExpectedPath - Supplies the expected translated path.
502 + ExpectedPath - Supplies the expected translated path, or NULL to assert
503 + that wslpath fails.
504
505 WinPath - Supplies a value that indicates whether the specified path is a
506 Windows path. When true, the expected path must be a Linux path and
@@ -515,15 +517,22 @@ Return Value:
517 int Result;
518 char TranslatedPath[4096];
519
518 - LxtCheckResult(LxtExecuteWslPath(Path, WinPath, TranslatedPath, sizeof(TranslatedPath)));
519 - LxtCheckStringEqual(ExpectedPath, TranslatedPath);
520 - LxtLogInfo("%s => %s", Path, TranslatedPath);
520 + LxtCheckResult(LxtExecuteWslPath(Path, WinPath, TranslatedPath, sizeof(TranslatedPath), ExpectedPath == NULL ? 1 : 0));
521 + if (ExpectedPath == NULL)
522 + {
523 + LxtLogInfo("%s => (failed as expected)", Path);
524 + }
525 + else
526 + {
527 + LxtCheckStringEqual(ExpectedPath, TranslatedPath);
528 + LxtLogInfo("%s => %s", Path, TranslatedPath);
529 + }
530
531 ErrorExit:
532 return Result;
533 }
534
526 -int LxtExecuteAndReadOutput(char** Argv, char* OutputBuffer, size_t OutputBufferSize)
535 +int LxtExecuteAndReadOutput(char** Argv, char* OutputBuffer, size_t OutputBufferSize, int ExpectedExitCode)
536
537 /*++
538
@@ -543,6 +552,8 @@ Arguments:
552
553 OutputBufferSize - Supplies the size of the output buffer.
554
555 + ExpectedExitCode - Supplies the expected exit code of the child process.
556 +
557 Return Value:
558
559 Returns 0 on success, -1 on failure.
@@ -585,10 +596,10 @@ Return Value:
596 OutputBuffer[BytesRead] = '\0';
597
598 //
588 - // Make sure the executable exited successfully.
599 + // Make sure the executable exited with the expected status.
600 //
601
591 - LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
602 + LxtCheckResult(LxtWaitPidPoll(ChildPid, ExpectedExitCode << 8));
603
604 ErrorExit:
605 LxtClosePipe(&Pipe);
@@ -596,7 +607,7 @@ ErrorExit:
607 return Result;
608 }
609
599 -int LxtExecuteWslPath(char* Path, bool WinPath, char* OutputBuffer, size_t OutputBufferSize)
610 +int LxtExecuteWslPath(char* Path, bool WinPath, char* OutputBuffer, size_t OutputBufferSize, int ExpectedExitCode)
611
612 /*++
613
@@ -618,6 +629,9 @@ Arguments:
629
630 OutputBufferSize - Supplies the size of the output buffer.
631
632 + ExpectedExitCode - Supplies the expected exit code of wslpath. Pass 1 when
633 + the translation is expected to fail.
634 +
635 Return Value:
636
637 Returns 0 on success, -1 on failure.
@@ -648,7 +662,7 @@ Return Value:
662 // Execute wslpath.
663 //
664
651 - LxtCheckResult(LxtExecuteAndReadOutput(Argv, OutputBuffer, OutputBufferSize));
665 + LxtCheckResult(LxtExecuteAndReadOutput(Argv, OutputBuffer, OutputBufferSize, ExpectedExitCode));
666
667 //
668 // Wslpath outputs a new line at the end. Strip it to make things easier on
test/linux/unit_tests/lxtutil.h
+2 -2
@@ -262,9 +262,9 @@ int LxtClosePipe(PLXT_PIPE Pipe);
262
263 int LxtCreatePipe(PLXT_PIPE Pipe);
264
265 -int LxtExecuteAndReadOutput(char** Argv, char* OutputBuffer, size_t OutputBufferSize);
265 +int LxtExecuteAndReadOutput(char** Argv, char* OutputBuffer, size_t OutputBufferSize, int ExpectedExitCode);
266
267 -int LxtExecuteWslPath(char* Path, bool WinPath, char* OutputBuffer, size_t OutputBufferSize);
267 +int LxtExecuteWslPath(char* Path, bool WinPath, char* OutputBuffer, size_t OutputBufferSize, int ExpectedExitCode);
268
269 int LxtJoinThread(pid_t* Tid);
270
test/linux/unit_tests/wslpath.c
+9
@@ -381,6 +381,15 @@ Return Value:
381 LxtCheckResult(LxtCheckWslPathTranslation("\\\\?\\C:\\Users\\", "/mnt/c/Users/", true));
382 LxtCheckResult(LxtCheckWslPathTranslation(".", ".", true));
383
384 + //
385 + // Validate that distro names that only share the current distro name as a prefix are correctly treated as an error.
386 + //
387 +
388 + LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "-other\\foo", NULL, true));
389 + LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_PREFIX "X\\foo", NULL, true));
390 + LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_COMPAT_PREFIX "-other\\foo", NULL, true));
391 + LxtCheckResult(LxtCheckWslPathTranslation(WSLPATH_DISTRO_COMPAT_PREFIX "X\\foo", NULL, true));
392 +
393 ErrorExit:
394 return Result;
395 }