winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 4f7ce38037c0392ef856c3c407f216c9a357f55f
parent 92b3e73bb85a16e02a4c3044d6693a58ea9d6f5e
Author: JohnMcPMS <johnmcp@microsoft.com>
Date:   Thu,  3 Dec 2020 14:24:25 -0800

Fix registry reading code to allow for a single null byte on a wide string value (#662)

Move to RegGetValue which normalizes null characters at the end of registry strings
Diffstat:
M.github/actions/spelling/expect.txt | 4+++-
Msrc/AppInstallerCLITests/Registry.cpp | 24++++++++++++++++++++++++
Msrc/AppInstallerCLITests/TestCommon.cpp | 4++--
Msrc/AppInstallerCLITests/TestCommon.h | 2+-
Msrc/AppInstallerCommonCore/Registry.cpp | 2+-
5 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt @@ -135,6 +135,7 @@ IHost IID IInstalled incosistencies +INET inl inor iosfwd @@ -207,6 +208,7 @@ mysilentwithprogress mytool Newtonsoft nfinity +NOEXPAND noreturn nuffing nullopt @@ -240,6 +242,7 @@ REGSAM REINSTALLMODE rhs rosoft +RRF rrr rzkzqaqjwj schematab @@ -326,4 +329,3 @@ Wunused WZDNCRFJ xf xl -INET diff --git a/src/AppInstallerCLITests/Registry.cpp b/src/AppInstallerCLITests/Registry.cpp @@ -80,6 +80,30 @@ TEST_CASE("Values_String", "[registry]") REQUIRE(value->GetValue<Value::Type::String>() == ConvertToUTF8(valueValue)); } +TEST_CASE("Values_WideStringWithNarrowNull", "[registry]") +{ + std::wstring valueName = L"TestValueName"; + std::wstring valueValue = L"TestValueValue"; + + wil::unique_hkey root = RegCreateVolatileTestRoot(); + + // Copy the bytes from the string value into a byte vector + std::vector<BYTE> valueBytes; + valueBytes.resize((valueValue.length() + 1) * sizeof(wchar_t)); + memcpy_s(valueBytes.data(), valueBytes.size(), valueValue.c_str(), (valueValue.length() + 1) * sizeof(wchar_t)); + // Remove the last byte to make a narrow null + valueBytes.resize(valueBytes.size() - 1); + + SetRegistryValue(root.get(), valueName, valueBytes, REG_SZ); + + Key key{ root.get(), L"" }; + + auto value = key[valueName]; + REQUIRE(value); + REQUIRE(value->GetType() == Value::Type::String); + REQUIRE(value->GetValue<Value::Type::String>() == ConvertToUTF8(valueValue)); +} + TEST_CASE("Values_ExpandString", "[registry]") { std::wstring valueName = L"TestValueName"; diff --git a/src/AppInstallerCLITests/TestCommon.cpp b/src/AppInstallerCLITests/TestCommon.cpp @@ -179,9 +179,9 @@ namespace TestCommon THROW_IF_WIN32_ERROR(RegSetValueExW(key, name.c_str(), 0, type, reinterpret_cast<const BYTE*>(value.c_str()), static_cast<DWORD>(sizeof(wchar_t) * (value.size() + 1)))); } - void SetRegistryValue(HKEY key, const std::wstring& name, const std::vector<BYTE>& value) + void SetRegistryValue(HKEY key, const std::wstring& name, const std::vector<BYTE>& value, DWORD type) { - THROW_IF_WIN32_ERROR(RegSetValueExW(key, name.c_str(), 0, REG_BINARY, reinterpret_cast<const BYTE*>(value.data()), static_cast<DWORD>(value.size()))); + THROW_IF_WIN32_ERROR(RegSetValueExW(key, name.c_str(), 0, type, reinterpret_cast<const BYTE*>(value.data()), static_cast<DWORD>(value.size()))); } void SetRegistryValue(HKEY key, const std::wstring& name, DWORD value) diff --git a/src/AppInstallerCLITests/TestCommon.h b/src/AppInstallerCLITests/TestCommon.h @@ -106,7 +106,7 @@ namespace TestCommon // Set registry values. void SetRegistryValue(HKEY key, const std::wstring& name, const std::wstring& value, DWORD type = REG_SZ); - void SetRegistryValue(HKEY key, const std::wstring& name, const std::vector<BYTE>& value); + void SetRegistryValue(HKEY key, const std::wstring& name, const std::vector<BYTE>& value, DWORD type = REG_BINARY); void SetRegistryValue(HKEY key, const std::wstring& name, DWORD value); } diff --git a/src/AppInstallerCommonCore/Registry.cpp b/src/AppInstallerCommonCore/Registry.cpp @@ -231,7 +231,7 @@ namespace AppInstaller::Registry while (data.size() < (64 << 20)) { byteCount = wil::safe_cast<DWORD>(data.size()); - status = RegQueryValueExW(m_key.get(), name.c_str(), nullptr, &type, data.data(), &byteCount); + status = RegGetValueW(m_key.get(), nullptr, name.c_str(), RRF_RT_ANY | RRF_NOEXPAND, &type, data.data(), &byteCount); if (status == ERROR_MORE_DATA && byteCount > data.size()) {