[vcpkg] Hardem expand environment strings path with explicit integer overflow checks and resistance to CP_ACP. (#11315)

This commit is contained in:
Billy O'Neal 2020-05-18 12:48:09 -07:00 committed by GitHub
parent 87b2ae5500
commit 0e9e59f2c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,5 +1,6 @@
#include "pch.h" #include "pch.h"
#include <limits.h>
#include <vcpkg/base/strings.h> #include <vcpkg/base/strings.h>
#include <vcpkg/base/system.print.h> #include <vcpkg/base/system.print.h>
#include <vcpkg/base/system.process.h> #include <vcpkg/base/system.process.h>
@ -7,17 +8,17 @@
#include <vcpkg/help.h> #include <vcpkg/help.h>
#include <vcpkg/paragraphs.h> #include <vcpkg/paragraphs.h>
namespace vcpkg::Commands::Edit
{
#if defined(_WIN32) #if defined(_WIN32)
static std::vector<fs::path> find_from_registry() namespace
{
std::vector<fs::path> find_from_registry()
{ {
std::vector<fs::path> output; std::vector<fs::path> output;
struct RegKey struct RegKey
{ {
HKEY root; HKEY root;
StringLiteral subkey; vcpkg::StringLiteral subkey;
} REGKEYS[] = { } REGKEYS[] = {
{HKEY_LOCAL_MACHINE, {HKEY_LOCAL_MACHINE,
R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)"}, R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)"},
@ -33,8 +34,8 @@ namespace vcpkg::Commands::Edit
for (auto&& keypath : REGKEYS) for (auto&& keypath : REGKEYS)
{ {
const Optional<std::string> code_installpath = const vcpkg::Optional<std::string> code_installpath =
System::get_registry_string(keypath.root, keypath.subkey, "InstallLocation"); vcpkg::System::get_registry_string(keypath.root, keypath.subkey, "InstallLocation");
if (const auto c = code_installpath.get()) if (const auto c = code_installpath.get())
{ {
const fs::path install_path = fs::u8path(*c); const fs::path install_path = fs::u8path(*c);
@ -44,8 +45,39 @@ namespace vcpkg::Commands::Edit
} }
return output; return output;
} }
std::string expand_environment_strings(const std::string& input)
{
const auto widened = vcpkg::Strings::to_utf16(input);
std::wstring result;
result.resize(result.capacity());
bool done;
do
{
if (result.size() == ULONG_MAX)
{
vcpkg::Checks::exit_fail(VCPKG_LINE_INFO); // integer overflow
}
const auto required_size =
ExpandEnvironmentStringsW(widened.c_str(), &result[0], static_cast<unsigned long>(result.size() + 1));
if (required_size == 0)
{
vcpkg::System::print2(vcpkg::System::Color::error, "Error: could not expand the environment string:\n");
vcpkg::System::print2(vcpkg::System::Color::error, input);
vcpkg::Checks::exit_fail(VCPKG_LINE_INFO);
}
done = required_size <= result.size() + 1;
result.resize(required_size - 1);
} while (!done);
return vcpkg::Strings::to_utf8(result);
}
}
#endif #endif
namespace vcpkg::Commands::Edit
{
static constexpr StringLiteral OPTION_BUILDTREES = "--buildtrees"; static constexpr StringLiteral OPTION_BUILDTREES = "--buildtrees";
static constexpr StringLiteral OPTION_ALL = "--all"; static constexpr StringLiteral OPTION_ALL = "--all";
@ -171,17 +203,12 @@ namespace vcpkg::Commands::Edit
const auto txt_default = System::get_registry_string(HKEY_CLASSES_ROOT, R"(.txt\ShellNew)", "ItemName"); const auto txt_default = System::get_registry_string(HKEY_CLASSES_ROOT, R"(.txt\ShellNew)", "ItemName");
if (const auto entry = txt_default.get()) if (const auto entry = txt_default.get())
{ {
#ifdef UNICODE auto full_path = expand_environment_strings(*entry);
LPWSTR dst = new wchar_t[MAX_PATH]; auto first = full_path.begin();
ExpandEnvironmentStrings(Strings::to_utf16(*entry).c_str(), dst, MAX_PATH); const auto last = full_path.end();
auto full_path = Strings::to_utf8(dst); first = std::find_if_not(first, last, [](const char c) { return c == '@'; });
#else const auto comma = std::find(first, last, ',');
LPSTR dst = new char[MAX_PATH]; candidate_paths.push_back(fs::u8path(first, comma));
ExpandEnvironmentStrings(entry->c_str(), dst, MAX_PATH);
auto full_path = std::string(dst);
#endif
auto begin = full_path.find_first_not_of('@');
candidate_paths.push_back(fs::u8path(full_path.substr(begin, full_path.find_first_of(',') - begin)));
} }
#elif defined(__APPLE__) #elif defined(__APPLE__)
candidate_paths.push_back( candidate_paths.push_back(