Fix incorrect string -> wstring conversion, causing utf16 corruption (#41406)

Blue committed Aug 21, 2026 at 17:54 UTC aeacef12f9c7a29c423868ba990c82aff044509e
3 files changed +26 -4
src/shared/inc/stringshared.h
+4 -4
@@ -1253,7 +1253,7 @@ struct std::formatter<char*, wchar_t>
1253 template <typename TCtx>
1254 auto format(const char* str, TCtx& ctx) const
1255 {
1256 - return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
1256 + return std::format_to(ctx.out(), L"{}", wsl::shared::string::MultiByteToWide(str));
1257 }
1258 };
1259
@@ -1269,7 +1269,7 @@ struct std::formatter<const char*, wchar_t>
1269 template <typename TCtx>
1270 auto format(const char* str, TCtx& ctx) const
1271 {
1272 - return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
1272 + return std::format_to(ctx.out(), L"{}", wsl::shared::string::MultiByteToWide(str));
1273 }
1274 };
1275
@@ -1285,7 +1285,7 @@ struct std::formatter<char[N], wchar_t>
1285 template <typename TCtx>
1286 auto format(const char str[N], TCtx& ctx) const
1287 {
1288 - return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
1288 + return std::format_to(ctx.out(), L"{}", wsl::shared::string::MultiByteToWide(str));
1289 }
1290 };
1291
@@ -1301,7 +1301,7 @@ struct std::formatter<std::basic_string<char, Traits, Allocator>, wchar_t>
1301 template <typename TCtx>
1302 auto format(const std::basic_string<char, Traits, Allocator>& str, TCtx& ctx) const
1303 {
1304 - return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
1304 + return std::format_to(ctx.out(), L"{}", wsl::shared::string::MultiByteToWide(str));
1305 }
1306 };
1307
test/windows/StringUnitTests.cpp
+8
@@ -77,6 +77,14 @@ class StringUnitTests
77 {
78 WSL_TEST_CLASS(StringUnitTests)
79
80 + TEST_METHOD(FormatUtf8StringAsWideString)
81 + {
82 + const std::string input{"安装依赖"};
83 + const auto expected = wsl::shared::string::MultiByteToWide(input);
84 +
85 + VERIFY_ARE_EQUAL(expected, std::format(L"{}", input));
86 + }
87 +
88 TEST_METHOD(ParseMemorySize_LegacyForms)
89 {
90 const std::vector<std::pair<LPCSTR, std::optional<uint64_t>>> TestCases{
test/windows/wslc/e2e/WSLCE2EImageBuildTests.cpp
+14
@@ -119,6 +119,20 @@ class WSLCE2EImageBuildTests
119 VERIFY_ARE_EQUAL(BuiltImage.NameAndTag(), wsl::shared::string::MultiByteToWide(inspectData.RepoTags.value()[0]));
120 }
121
122 + WSLC_TEST_METHOD(WSLCE2E_Image_Build_UnicodeOutput_Success)
123 + {
124 + auto testRoot = std::filesystem::current_path() / L"wslc-e2e-build-unicode-output";
125 + auto cleanup = SetupTestDirectory(testRoot);
126 +
127 + auto dockerfilePath = testRoot / L"Dockerfile";
128 + WriteTestFileContent(dockerfilePath, "FROM debian:latest\nRUN echo 安装依赖\n");
129 +
130 + auto buildResult = RunWslc(std::format(
131 + L"build \"{}\" -f \"{}\" --output type=cacheonly", SharedOutputBuildContext().wstring(), dockerfilePath.wstring()));
132 + buildResult.Verify({.ExitCode = 0});
133 + VERIFY_IS_TRUE(buildResult.StderrContainsSubstring(wsl::shared::string::MultiByteToWide("安装依赖")));
134 + }
135 +
136 WSLC_TEST_METHOD(WSLCE2E_Image_Build_BuildArgsFileAndMultipleTags_Success)
137 {
138 auto imageCleanup1 = DeleteImageOnExit(BuiltImageTag1);