From 89408d2f38bdc8adc3024445138ec2bbc5b8adf1 Mon Sep 17 00:00:00 2001 From: kai lin Date: Thu, 30 Jul 2026 17:18:30 -0400 Subject: [PATCH] Fix Windows GetEnv mangling non-ASCII environment values On Windows, GetEnv read variables through the narrow _dupenv_s, which returns the value in the active ANSI code page (e.g. CP-1252). Non-ASCII values -- such as a home path with an accented username -- were then reinterpreted as UTF-8 and came out mangled, so ~/.aws/credentials and ~/.aws/config failed to load and the profile provider fell back to an anonymous request (GitHub issue #3865). Read env vars through the wide _wdupenv_s and convert explicitly to UTF-8, since Windows stores them natively as UTF-16. Mirrors the same fix in the CRT (awslabs/aws-c-common#1260). Non-MSVC compilers keep the existing std::getenv path. Adds a Windows-only regression test that injects a non-ASCII value via the wide CRT API and asserts GetEnv returns the correct UTF-8 bytes. --- .../source/platform/windows/Environment.cpp | 19 +++++++----------- .../utils/FileSystemUtilsTest.cpp | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/aws-cpp-sdk-core/source/platform/windows/Environment.cpp b/src/aws-cpp-sdk-core/source/platform/windows/Environment.cpp index b70cc1cd2129..dad3c467efc6 100644 --- a/src/aws-cpp-sdk-core/source/platform/windows/Environment.cpp +++ b/src/aws-cpp-sdk-core/source/platform/windows/Environment.cpp @@ -4,6 +4,7 @@ */ #include +#include #include #include @@ -13,25 +14,19 @@ namespace Aws namespace Environment { -/* -using std::getenv generates a warning on windows so we use _dupenv_s instead. The character array returned by this function is our responsibility to clean up, so rather than returning raw strings -that would need to be manually freed in all the client functions, just copy it into a Aws::String instead, freeing it here. - -since _dupenv_s is a non-standard function, on non-Microsoft compilers we will fall back to using std::getenv instead. -*/ Aws::String GetEnv(const char *variableName) { -#ifdef _MSC_VER - char* variableValue = nullptr; +#ifdef _MSC_VER + wchar_t* variableValue = nullptr; std::size_t valueSize = 0; - auto queryResult = _dupenv_s(&variableValue, &valueSize, variableName); + const auto queryResult = _wdupenv_s(&variableValue, &valueSize, Aws::Utils::StringUtils::ToWString(variableName).c_str()); Aws::String result; - if(queryResult == 0 && variableValue != nullptr && valueSize > 0) + if(queryResult == 0 && variableValue != nullptr) { - result.assign(variableValue, valueSize - 1); // don't copy the c-string terminator byte - free(variableValue); + result = Aws::Utils::StringUtils::FromWString(variableValue); } + free(variableValue); return result; #else diff --git a/tests/aws-cpp-sdk-core-tests/utils/FileSystemUtilsTest.cpp b/tests/aws-cpp-sdk-core-tests/utils/FileSystemUtilsTest.cpp index feadde87dfe9..2b9fe8f540e1 100644 --- a/tests/aws-cpp-sdk-core-tests/utils/FileSystemUtilsTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/utils/FileSystemUtilsTest.cpp @@ -3,11 +3,15 @@ * SPDX-License-Identifier: Apache-2.0. */ +#include #include #include #include #include #include +#ifdef _MSC_VER +#include // _wputenv_s +#endif #if defined(HAS_PATHCONF) #include #include @@ -32,6 +36,22 @@ TEST_F(FileTest, HomeDirectory) ASSERT_EQ(Aws::FileSystem::PATH_DELIM, homeDirectory.back()); } +TEST_F(FileTest, GetEnvReturnsNonAsciiValueAsUtf8) +{ +#ifdef _MSC_VER + const char* varName = "AWS_SDK_TEST_NONASCII"; + // Set via the wide CRT API so the true Unicode value is stored, not a pre-mangled narrow one. + ASSERT_EQ(0, _wputenv_s(L"AWS_SDK_TEST_NONASCII", L"José")); + + const auto value = Aws::Environment::GetEnv(varName); + _wputenv_s(L"AWS_SDK_TEST_NONASCII", L""); + + ASSERT_EQ(Aws::String("Jos\xC3\xA9"), value); // "José" in UTF-8 +#else + GTEST_SKIP() << "Non-ASCII environment encoding fix is Windows-specific."; +#endif +} + TEST_F(FileTest, TestInvalidDirectoryPath) { auto badDir = Aws::FileSystem::OpenDirectory("boogieMan");