[z-applocal] Reduce nonexistent and non-PE files to warnings. (#1274)
This commit is contained in:
Родитель
4c1df40a3c
Коммит
a35ce804e1
|
@ -0,0 +1,3 @@
|
|||
cd %~dp0
|
||||
cl /c static-lib.cpp /Fostatic-lib.obj
|
||||
lib static-lib.obj /out:static-lib.lib
|
|
@ -0,0 +1 @@
|
|||
int use_from_static_lib() { return 42; }
|
|
@ -76,4 +76,40 @@ if ($IsWindows) {
|
|||
|
||||
Require-FileExists "$pluginsDir/k4a.dll"
|
||||
Require-FileExists "$pluginsDir/depthengine_2_0.dll"
|
||||
|
||||
# Tests that nonexistent files are merely warnings
|
||||
$nonexistentDll = Join-Path $basicDir 'nonexisting.dll'
|
||||
Require-FileNotExists $nonexistentDll
|
||||
$nonexistentOutput = Run-VcpkgAndCaptureOutput z-applocal `
|
||||
--target-binary=$nonexistentDll `
|
||||
--installed-bin-dir=$basicDir/installed/bin
|
||||
Throw-IfNotFailed
|
||||
if ($nonexistentOutput -match 'error:')
|
||||
{
|
||||
throw "Nonexistent emitted an error"
|
||||
}
|
||||
|
||||
if ($nonexistentOutput -notmatch 'warning: no such file or directory')
|
||||
{
|
||||
throw "Nonexistent didn't emit expected warning"
|
||||
}
|
||||
|
||||
# Tests that static libs emit a 'does not appear to be executable' warning
|
||||
$staticLibDir = "$TestingRoot/applocal/static-lib"
|
||||
Run-Vcpkg env "$staticLibDir/build.bat"
|
||||
$staticLibFile = "$staticLibDir/static-lib.lib"
|
||||
Require-FileExists $staticLibFile
|
||||
$staticLibOutput = Run-VcpkgAndCaptureOutput z-applocal `
|
||||
--target-binary=$staticLibFile `
|
||||
--installed-bin-dir=$basicDir/installed/bin
|
||||
Throw-IfNotFailed
|
||||
if ($staticLibOutput -match 'error:')
|
||||
{
|
||||
throw "Static library emitted an error"
|
||||
}
|
||||
|
||||
if ($staticLibOutput -notmatch 'warning: this file does not appear to be executable')
|
||||
{
|
||||
throw "Static library didn't emit expected warning"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <vcpkg/base/fwd/cofffilereader.h>
|
||||
#include <vcpkg/base/fwd/expected.h>
|
||||
#include <vcpkg/base/fwd/files.h>
|
||||
|
||||
#include <vcpkg/base/expected.h>
|
||||
#include <vcpkg/base/fwd/optional.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -419,7 +419,8 @@ namespace vcpkg
|
|||
};
|
||||
|
||||
std::vector<std::string> tokenize_command_line(StringView cmd_line);
|
||||
ExpectedL<DllMetadata> try_read_dll_metadata(ReadFilePointer& f);
|
||||
ExpectedL<Optional<DllMetadata>> try_read_dll_metadata(ReadFilePointer& f);
|
||||
ExpectedL<DllMetadata> try_read_dll_metadata_required(ReadFilePointer& f);
|
||||
ExpectedL<bool> try_read_if_dll_has_exports(const DllMetadata& dll, ReadFilePointer& f);
|
||||
ExpectedL<std::vector<std::string>> try_read_dll_imported_dll_names(const DllMetadata& dll, ReadFilePointer& f);
|
||||
ExpectedL<LibInformation> read_lib_information(ReadFilePointer& f);
|
||||
|
|
|
@ -81,6 +81,8 @@ namespace vcpkg
|
|||
ExpectedL<Unit> try_seek_to(long long offset);
|
||||
ExpectedL<Unit> try_seek_to(long long offset, int origin);
|
||||
|
||||
void close() noexcept;
|
||||
|
||||
~FilePointer();
|
||||
};
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ DECLARE_MESSAGE(APackagePattern, (), "", "a package pattern")
|
|||
DECLARE_MESSAGE(APackagePatternArray, (), "", "a package pattern array")
|
||||
DECLARE_MESSAGE(APath, (), "", "a path")
|
||||
DECLARE_MESSAGE(AppliedUserIntegration, (), "", "Applied user-wide integration for this vcpkg root.")
|
||||
DECLARE_MESSAGE(ApplocalProcessing, (msg::path), "", "vcpkg applocal processing: {path}")
|
||||
DECLARE_MESSAGE(ApplocalProcessing, (), "", "deploying dependencies")
|
||||
DECLARE_MESSAGE(ARegistry, (), "", "a registry")
|
||||
DECLARE_MESSAGE(ARegistryImplementationKind, (), "", "a registry implementation kind")
|
||||
DECLARE_MESSAGE(ARegistryPath, (), "", "a registry path")
|
||||
|
@ -1295,6 +1295,7 @@ DECLARE_MESSAGE(FailedVendorAuthentication,
|
|||
"",
|
||||
"One or more {vendor} credential providers failed to authenticate. See '{url}' for more details "
|
||||
"on how to provide credentials.")
|
||||
DECLARE_MESSAGE(FileIsNotExecutable, (), "", "this file does not appear to be executable")
|
||||
DECLARE_MESSAGE(FilesContainAbsolutePath1,
|
||||
(),
|
||||
"This message is printed before a list of found absolute paths, followed by FilesContainAbsolutePath2, "
|
||||
|
@ -2291,10 +2292,6 @@ DECLARE_MESSAGE(PERvaNotFound,
|
|||
"{value:#X} is the Relative Virtual Address sought. Portable executable is a term-of-art, see "
|
||||
"https://learn.microsoft.com/windows/win32/debug/pe-format",
|
||||
"While parsing Portable Executable {path}, could not find RVA {value:#X}.")
|
||||
DECLARE_MESSAGE(PESignatureMismatch,
|
||||
(msg::path),
|
||||
"Portable Executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format",
|
||||
"While parsing Portable Executable {path}, signature mismatch.")
|
||||
DECLARE_MESSAGE(PerformingPostBuildValidation, (), "", "-- Performing post-build validation")
|
||||
DECLARE_MESSAGE(PortBugAllowRestrictedHeaders,
|
||||
(msg::env_var),
|
||||
|
|
|
@ -140,8 +140,7 @@
|
|||
"_AndroidHomeDirMissingProps.comment": "Note: 'source.properties' is code and should not be translated. An example of {env_var} is VCPKG_DEFAULT_TRIPLET. An example of {path} is /foo/bar.",
|
||||
"AnotherInstallationInProgress": "Another installation is in progress on the machine, sleeping 6s before retrying.",
|
||||
"AppliedUserIntegration": "Applied user-wide integration for this vcpkg root.",
|
||||
"ApplocalProcessing": "vcpkg applocal processing: {path}",
|
||||
"_ApplocalProcessing.comment": "An example of {path} is /foo/bar.",
|
||||
"ApplocalProcessing": "deploying dependencies",
|
||||
"ArtifactsBootstrapFailed": "vcpkg-artifacts is not installed and could not be bootstrapped.",
|
||||
"ArtifactsNotInstalledReadonlyRoot": "vcpkg-artifacts is not installed, and it can't be installed because VCPKG_ROOT is assumed to be readonly. Reinstalling vcpkg using the 'one liner' may fix this problem.",
|
||||
"ArtifactsNotOfficialWarning": "Using vcpkg-artifacts with an unofficial ",
|
||||
|
@ -806,6 +805,7 @@
|
|||
"_FetchingRegistryInfo.comment": "{value} is a reference An example of {url} is https://github.com/microsoft/vcpkg.",
|
||||
"FieldKindDidNotHaveExpectedValue": "\"kind\" did not have an expected value: (expected one of: {expected}; found {actual})",
|
||||
"_FieldKindDidNotHaveExpectedValue.comment": "{expected} is a list of literal kinds the user must type, separated by commas, {actual} is what the user supplied",
|
||||
"FileIsNotExecutable": "this file does not appear to be executable",
|
||||
"FileNotFound": "{path}: file not found",
|
||||
"_FileNotFound.comment": "An example of {path} is /foo/bar.",
|
||||
"FileReadFailed": "Failed to read {count} bytes from {path} at offset {byte_offset}.",
|
||||
|
@ -1266,8 +1266,6 @@
|
|||
"_PEPlusTagInvalid.comment": "Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format An example of {path} is /foo/bar.",
|
||||
"PERvaNotFound": "While parsing Portable Executable {path}, could not find RVA {value:#X}.",
|
||||
"_PERvaNotFound.comment": "{value:#X} is the Relative Virtual Address sought. Portable executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format An example of {path} is /foo/bar.",
|
||||
"PESignatureMismatch": "While parsing Portable Executable {path}, signature mismatch.",
|
||||
"_PESignatureMismatch.comment": "Portable Executable is a term-of-art, see https://learn.microsoft.com/windows/win32/debug/pe-format An example of {path} is /foo/bar.",
|
||||
"PackageAlreadyRemoved": "unable to remove {spec}: already removed",
|
||||
"_PackageAlreadyRemoved.comment": "An example of {spec} is zlib:x64-windows.",
|
||||
"PackageDiscoveryHeader": "Package Discovery",
|
||||
|
|
|
@ -22,11 +22,28 @@ namespace
|
|||
static_assert(sizeof(SectionTableHeader) == 40,
|
||||
"The SectionTableHeader struct must match its on-disk representation.");
|
||||
|
||||
ExpectedL<Unit> read_pe_signature_and_get_coff_header_offset(ReadFilePointer& f)
|
||||
// reads f as a portable executable and checks for magic number signatures.
|
||||
// if an I/O error occurs, returns the error; otherwise,
|
||||
// returns iff signatures match
|
||||
ExpectedL<bool> read_pe_signature_and_get_coff_header_offset(ReadFilePointer& f)
|
||||
{
|
||||
static constexpr StringLiteral EXPECTED_MZ_HEADER = "MZ";
|
||||
{
|
||||
char mz_signature[EXPECTED_MZ_HEADER.size()];
|
||||
auto maybe_read_mz = f.try_read_all_from(0, mz_signature, sizeof(mz_signature));
|
||||
if (!maybe_read_mz)
|
||||
{
|
||||
return std::move(maybe_read_mz).error();
|
||||
}
|
||||
|
||||
if (EXPECTED_MZ_HEADER != StringView{mz_signature, sizeof(mz_signature)})
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr long OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c;
|
||||
static constexpr StringLiteral PE_SIGNATURE = "PE\0\0";
|
||||
static constexpr auto PE_SIGNATURE_SIZE = static_cast<uint32_t>(PE_SIGNATURE.size());
|
||||
static constexpr StringLiteral EXPECTED_PE_SIGNATURE = "PE\0\0";
|
||||
uint32_t offset;
|
||||
{
|
||||
auto read_offset = f.try_read_all_from(OFFSET_TO_PE_SIGNATURE_OFFSET, &offset, sizeof(offset));
|
||||
|
@ -36,21 +53,16 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
char signature[PE_SIGNATURE_SIZE];
|
||||
char pe_signature[EXPECTED_PE_SIGNATURE.size()];
|
||||
{
|
||||
auto read_signature = f.try_read_all_from(offset, signature, PE_SIGNATURE_SIZE);
|
||||
auto read_signature = f.try_read_all_from(offset, pe_signature, sizeof(pe_signature));
|
||||
if (!read_signature.has_value())
|
||||
{
|
||||
return std::move(read_signature).error();
|
||||
}
|
||||
}
|
||||
|
||||
if (PE_SIGNATURE != StringView{signature, PE_SIGNATURE_SIZE})
|
||||
{
|
||||
return msg::format(msgPESignatureMismatch, msg::path = f.path());
|
||||
}
|
||||
|
||||
return Unit{};
|
||||
return EXPECTED_PE_SIGNATURE == StringView{pe_signature, sizeof(pe_signature)};
|
||||
}
|
||||
|
||||
ExpectedL<Unit> try_read_optional_header(DllMetadata& metadata, ReadFilePointer& f)
|
||||
|
@ -639,20 +651,28 @@ namespace vcpkg
|
|||
return result;
|
||||
}
|
||||
|
||||
ExpectedL<DllMetadata> try_read_dll_metadata(ReadFilePointer& f)
|
||||
ExpectedL<Optional<DllMetadata>> try_read_dll_metadata(ReadFilePointer& f)
|
||||
{
|
||||
Optional<DllMetadata> result;
|
||||
{
|
||||
auto signature = read_pe_signature_and_get_coff_header_offset(f);
|
||||
if (!signature.has_value())
|
||||
auto maybe_signature_ok = read_pe_signature_and_get_coff_header_offset(f);
|
||||
if (auto signature_ok = maybe_signature_ok.get())
|
||||
{
|
||||
return std::move(signature).error();
|
||||
if (!*signature_ok)
|
||||
{
|
||||
return nullopt;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::move(maybe_signature_ok).error();
|
||||
}
|
||||
}
|
||||
|
||||
DllMetadata result{};
|
||||
DllMetadata& target = result.emplace();
|
||||
|
||||
{
|
||||
auto read_coff = f.try_read_all(&result.coff_header, sizeof(result.coff_header));
|
||||
auto read_coff = f.try_read_all(&target.coff_header, sizeof(target.coff_header));
|
||||
if (!read_coff.has_value())
|
||||
{
|
||||
return std::move(read_coff).error();
|
||||
|
@ -660,7 +680,7 @@ namespace vcpkg
|
|||
}
|
||||
|
||||
{
|
||||
auto read_optional_header = try_read_optional_header(result, f);
|
||||
auto read_optional_header = try_read_optional_header(target, f);
|
||||
if (!read_optional_header.has_value())
|
||||
{
|
||||
return std::move(read_optional_header).error();
|
||||
|
@ -668,7 +688,7 @@ namespace vcpkg
|
|||
}
|
||||
|
||||
{
|
||||
auto read_section_headers = try_read_section_headers(result, f);
|
||||
auto read_section_headers = try_read_section_headers(target, f);
|
||||
if (!read_section_headers)
|
||||
{
|
||||
return std::move(read_section_headers).error();
|
||||
|
@ -676,7 +696,7 @@ namespace vcpkg
|
|||
}
|
||||
|
||||
{
|
||||
auto read_load_config_directory = try_read_image_config_directory(result, f);
|
||||
auto read_load_config_directory = try_read_image_config_directory(target, f);
|
||||
if (!read_load_config_directory)
|
||||
{
|
||||
return std::move(read_load_config_directory).error();
|
||||
|
@ -686,6 +706,21 @@ namespace vcpkg
|
|||
return result;
|
||||
}
|
||||
|
||||
ExpectedL<DllMetadata> try_read_dll_metadata_required(ReadFilePointer& f)
|
||||
{
|
||||
return try_read_dll_metadata(f).then([&](Optional<DllMetadata>&& maybe_metadata) -> ExpectedL<DllMetadata> {
|
||||
if (auto metadata = maybe_metadata.get())
|
||||
{
|
||||
return std::move(*metadata);
|
||||
}
|
||||
|
||||
return LocalizedString::from_raw(f.path())
|
||||
.append_raw(": ")
|
||||
.append_raw(ErrorPrefix)
|
||||
.append(msgFileIsNotExecutable);
|
||||
});
|
||||
}
|
||||
|
||||
ExpectedL<bool> try_read_if_dll_has_exports(const DllMetadata& dll, ReadFilePointer& f)
|
||||
{
|
||||
const auto export_data_directory = dll.try_get_image_data_directory(0);
|
||||
|
|
|
@ -1381,14 +1381,17 @@ namespace vcpkg
|
|||
return Unit{};
|
||||
}
|
||||
|
||||
FilePointer::~FilePointer()
|
||||
void FilePointer::close() noexcept
|
||||
{
|
||||
if (m_fs)
|
||||
{
|
||||
Checks::check_exit(VCPKG_LINE_INFO, ::fclose(m_fs) == 0);
|
||||
m_fs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FilePointer::~FilePointer() { close(); }
|
||||
|
||||
ReadFilePointer::ReadFilePointer() noexcept = default;
|
||||
|
||||
ReadFilePointer::ReadFilePointer(ReadFilePointer&&) noexcept = default;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
using namespace vcpkg;
|
||||
|
||||
|
@ -104,11 +105,22 @@ namespace
|
|||
|
||||
void resolve(const Path& binary)
|
||||
{
|
||||
msg::println(msgApplocalProcessing, msg::path = binary);
|
||||
msg::print(LocalizedString::from_raw(binary)
|
||||
.append_raw(": ")
|
||||
.append_raw(MessagePrefix)
|
||||
.append(msgApplocalProcessing)
|
||||
.append_raw('\n'));
|
||||
|
||||
auto dll_file = m_fs.open_for_read(binary, VCPKG_LINE_INFO);
|
||||
const auto dll_metadata = vcpkg::try_read_dll_metadata(dll_file).value_or_exit(VCPKG_LINE_INFO);
|
||||
const auto dll_metadata = vcpkg::try_read_dll_metadata_required(dll_file).value_or_exit(VCPKG_LINE_INFO);
|
||||
const auto imported_names =
|
||||
vcpkg::try_read_dll_imported_dll_names(dll_metadata, dll_file).value_or_exit(VCPKG_LINE_INFO);
|
||||
dll_file.close();
|
||||
resolve_explicit(binary, imported_names);
|
||||
}
|
||||
|
||||
void resolve_explicit(const Path& binary, const std::vector<std::string>& imported_names)
|
||||
{
|
||||
Debug::print("Imported DLLs of ", binary, " were ", Strings::join("\n", imported_names), "\n");
|
||||
|
||||
for (auto&& imported_name : imported_names)
|
||||
|
@ -569,7 +581,7 @@ namespace vcpkg
|
|||
nullptr,
|
||||
};
|
||||
|
||||
void command_z_applocal_and_exit(const VcpkgCmdArguments& args, const Filesystem&)
|
||||
void command_z_applocal_and_exit(const VcpkgCmdArguments& args, const Filesystem& fs)
|
||||
{
|
||||
auto parsed = args.parse_arguments(CommandZApplocalMetadata);
|
||||
const auto target_binary = parsed.settings.find(OPTION_TARGET_BINARY);
|
||||
|
@ -585,17 +597,70 @@ namespace vcpkg
|
|||
}
|
||||
|
||||
const auto target_installed_bin_dir =
|
||||
real_filesystem.almost_canonical(target_installed_bin_setting->second, VCPKG_LINE_INFO);
|
||||
const auto target_binary_path = real_filesystem.almost_canonical(target_binary->second, VCPKG_LINE_INFO);
|
||||
fs.almost_canonical(target_installed_bin_setting->second, VCPKG_LINE_INFO);
|
||||
const auto decoded = decode_from_canonical_bin_dir(target_installed_bin_dir);
|
||||
AppLocalInvocation invocation(real_filesystem,
|
||||
|
||||
// the first binary is special in that it might not be a DLL or might not exist
|
||||
const Path target_binary_path = target_binary->second;
|
||||
msg::print(LocalizedString::from_raw(target_binary_path)
|
||||
.append_raw(": ")
|
||||
.append_raw(MessagePrefix)
|
||||
.append(msgApplocalProcessing)
|
||||
.append_raw('\n'));
|
||||
|
||||
std::error_code ec;
|
||||
auto dll_file = fs.open_for_read(target_binary_path, ec);
|
||||
if (ec)
|
||||
{
|
||||
auto io_error = ec.message();
|
||||
if (ec == std::errc::no_such_file_or_directory)
|
||||
{
|
||||
msg::print(Color::warning,
|
||||
LocalizedString::from_raw(target_binary_path)
|
||||
.append_raw(": ")
|
||||
.append_raw(WarningPrefix)
|
||||
.append_raw(io_error)
|
||||
.append_raw('\n'));
|
||||
}
|
||||
else
|
||||
{
|
||||
msg::print(Color::error,
|
||||
LocalizedString::from_raw(target_binary_path)
|
||||
.append_raw(": ")
|
||||
.append_raw(ErrorPrefix)
|
||||
.append_raw(io_error)
|
||||
.append_raw('\n'));
|
||||
}
|
||||
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
auto maybe_dll_metadata = vcpkg::try_read_dll_metadata(dll_file).value_or_exit(VCPKG_LINE_INFO);
|
||||
auto dll_metadata = maybe_dll_metadata.get();
|
||||
if (!dll_metadata)
|
||||
{
|
||||
msg::print(Color::warning,
|
||||
LocalizedString::from_raw(target_binary_path)
|
||||
.append_raw(": ")
|
||||
.append_raw(WarningPrefix)
|
||||
.append(msgFileIsNotExecutable)
|
||||
.append_raw('\n'));
|
||||
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
const auto imported_names =
|
||||
vcpkg::try_read_dll_imported_dll_names(*dll_metadata, dll_file).value_or_exit(VCPKG_LINE_INFO);
|
||||
dll_file.close();
|
||||
|
||||
AppLocalInvocation invocation(fs,
|
||||
target_binary_path.parent_path(),
|
||||
target_installed_bin_dir,
|
||||
decoded.installed_root,
|
||||
decoded.is_debug,
|
||||
maybe_create_log(parsed.settings, OPTION_TLOG_FILE, real_filesystem),
|
||||
maybe_create_log(parsed.settings, OPTION_COPIED_FILES_LOG, real_filesystem));
|
||||
invocation.resolve(target_binary_path);
|
||||
maybe_create_log(parsed.settings, OPTION_TLOG_FILE, fs),
|
||||
maybe_create_log(parsed.settings, OPTION_COPIED_FILES_LOG, fs));
|
||||
invocation.resolve_explicit(target_binary_path, imported_names);
|
||||
Checks::exit_success(VCPKG_LINE_INFO);
|
||||
}
|
||||
} // namespace vcpkg
|
||||
|
|
|
@ -445,7 +445,7 @@ namespace vcpkg
|
|||
return std::move(maybe_file).error();
|
||||
}
|
||||
|
||||
auto maybe_metadata = try_read_dll_metadata(*file);
|
||||
auto maybe_metadata = try_read_dll_metadata_required(*file);
|
||||
auto metadata = maybe_metadata.get();
|
||||
if (!metadata)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче