[post build lint] Check for absolute paths (#172)

This commit is contained in:
autoantwort 2023-01-20 21:58:27 +01:00 коммит произвёл GitHub
Родитель 7fbe87b0d3
Коммит fcfbfa4a21
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 425 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,3 @@
#!/bin/bash
test="${CURRENT_INSTALLED_DIR}"

Просмотреть файл

@ -0,0 +1,36 @@
set(VCPKG_POLICY_EMPTY_INCLUDE_FOLDER enabled)
if("usage" IN_LIST FEATURES)
file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/usage" "Set TEST=${CURRENT_INSTALLED_DIR} to use the port\n")
endif()
if("header" IN_LIST FEATURES)
configure_file("${CURRENT_PORT_DIR}/source.h.in" "${CURRENT_PACKAGES_DIR}/include/test.h")
endif()
if("header-comment" IN_LIST FEATURES)
configure_file("${CURRENT_PORT_DIR}/source-comment.h.in" "${CURRENT_PACKAGES_DIR}/include/test.h")
endif()
if("python" IN_LIST FEATURES)
file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/test.py" "test = \"${CURRENT_INSTALLED_DIR}\"\n")
message(STATUS "Wtite to ${CURRENT_PACKAGES_DIR}/share/${PORT}/test.py")
endif()
if("python-comment" IN_LIST FEATURES)
file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/test.py" "# test = \"${CURRENT_INSTALLED_DIR}\"\n")
endif()
if("hash" IN_LIST FEATURES)
configure_file("${CURRENT_PORT_DIR}/hash.in" "${CURRENT_PACKAGES_DIR}/share/${PORT}/test")
endif()
if("new-policy" IN_LIST FEATURES)
set(VCPKG_POLICY_SKIP_ABSOLUTE_PATHS_CHECK enabled)
endif()
if("packages" IN_LIST FEATURES)
file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/test.py" "${CURRENT_PACKAGES_DIR}")
endif()
if("buildtrees" IN_LIST FEATURES)
file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/test.py" "${CURRENT_BUILDTREES_DIR}")
endif()
if("native" IN_LIST FEATURES)
cmake_path(NATIVE_PATH CURRENT_INSTALLED_DIR CURRENT_INSTALLED_DIR_NATIVE)
file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/test.py" "${CURRENT_INSTALLED_DIR_NATIVE}")
endif()
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/../../../../LICENSE.txt" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

Просмотреть файл

@ -0,0 +1,6 @@
// char * test = "${CURRENT_INSTALLED_DIR}"
/*
${CURRENT_INSTALLED_DIR}
*/

Просмотреть файл

@ -0,0 +1,5 @@
char * test2 = R"--(/*
// ${CURRENT_INSTALLED_DIR} */
)--";

Просмотреть файл

@ -0,0 +1,37 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
"name": "absolute-paths",
"version": "1.0.0",
"features": {
"usage": {
"description": ""
},
"header": {
"description": ""
},
"header-comment": {
"description": ""
},
"python": {
"description": ""
},
"python-comment": {
"description": ""
},
"hash": {
"description": ""
},
"new-policy": {
"description": ""
},
"packages": {
"description": ""
},
"buildtrees": {
"description": ""
},
"native": {
"description": ""
}
}
}

Просмотреть файл

@ -0,0 +1,41 @@
. $PSScriptRoot/../end-to-end-tests-prelude.ps1
$CurrentTest = "No absolute paths"
$commonArgs += @("--enforce-port-checks", "--binarysource=clear")
Run-Vcpkg @commonArgs install "absolute-paths[hash]"
Throw-IfNotFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[python]"
Throw-IfNotFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[python-comment]"
Throw-IfFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[header]"
Throw-IfNotFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[header-comment]"
Throw-IfFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[usage]"
Throw-IfNotFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[usage, new-policy]"
Throw-IfFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[packages]"
Throw-IfNotFailed
Remove-Item -Recurse -Force $installRoot
Run-Vcpkg @commonArgs install "absolute-paths[native]"
Throw-IfNotFailed
Remove-Item -Recurse -Force $installRoot

Просмотреть файл

@ -1338,6 +1338,13 @@ namespace vcpkg
"One or more {vendor} credential providers failed to authenticate. See '{url}' for more details "
"on how to provide credentials.");
DECLARE_MESSAGE(FeedbackAppreciated, (), "", "Thank you for your feedback!");
DECLARE_MESSAGE(
FilesContainAbsolutePath1,
(),
"This message is printed before a list of found absolute paths, followed by FilesContainAbsolutePath2, "
"followed by a list of found files.",
"There should be no absolute paths, such as the following, in an installed package:");
DECLARE_MESSAGE(FilesContainAbsolutePath2, (), "", "Absolute paths were found in the following files:");
DECLARE_MESSAGE(FetchingBaselineInfo,
(msg::package_name),
"",

Просмотреть файл

@ -12,6 +12,8 @@
#include <algorithm>
#include <vector>
#include "vcpkg/base/fwd/span.h"
namespace vcpkg::Strings::details
{
// first looks up to_string on `T` using ADL; then, if that isn't found,
@ -218,6 +220,12 @@ namespace vcpkg::Strings
Optional<StringView> find_at_most_one_enclosed(StringView input, StringView left_tag, StringView right_tag);
bool contains_any_ignoring_c_comments(const std::string& source, View<StringView> to_find);
bool contains_any_ignoring_hash_comments(StringView source, View<StringView> to_find);
bool contains_any(StringView source, View<StringView> to_find);
bool equals(StringView a, StringView b);
template<class T>

Просмотреть файл

@ -266,6 +266,13 @@ namespace vcpkg::Util
return std::find(begin(cont), end(cont), v);
}
template<class Range, class T>
bool contains(const Range& r, const T& el)
{
using std::end;
return Util::find(r, el) != end(r);
}
template<class Container, class Pred>
auto find_if(Container&& cont, Pred pred)
{

Просмотреть файл

@ -106,6 +106,7 @@ namespace vcpkg
SKIP_DUMPBIN_CHECKS,
SKIP_ARCHITECTURE_CHECK,
CMAKE_HELPER_PORT,
SKIP_ABSOLUTE_PATHS_CHECK,
// Must be last
COUNT,
};

Просмотреть файл

@ -540,6 +540,9 @@
"FileSeekFailed": "Failed to seek to position {byte_offset} in {path}.",
"_FileSeekFailed.comment": "An example of {path} is /foo/bar. An example of {byte_offset} is 42.",
"FileSystemOperationFailed": "Filesystem operation failed:",
"FilesContainAbsolutePath1": "There should be no absolute paths, such as the following, in an installed package:",
"_FilesContainAbsolutePath1.comment": "This message is printed before a list of found absolute paths, followed by FilesContainAbsolutePath2, followed by a list of found files.",
"FilesContainAbsolutePath2": "Absolute paths were found in the following files:",
"FilesExported": "Files exported at: {path}",
"_FilesExported.comment": "An example of {path} is /foo/bar.",
"FishCompletion": "vcpkg fish completion is already added at \"{path}\".",

Просмотреть файл

@ -2,6 +2,7 @@
#include <vcpkg/base/api-stable-format.h>
#include <vcpkg/base/expected.h>
#include <vcpkg/base/span.h>
#include <vcpkg/base/strings.h>
#include <stdint.h>
@ -55,6 +56,75 @@ TEST_CASE ("find_first_of", "[strings]")
REQUIRE(find_first_of("abcdefg", "gb") == std::string("bcdefg"));
}
TEST_CASE ("contains_any_ignoring_c_comments", "[strings]")
{
using vcpkg::Strings::contains_any_ignoring_c_comments;
vcpkg::StringView to_find[] = {"abc", "wer"};
REQUIRE(contains_any_ignoring_c_comments(R"(abc)", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"("abc")", to_find));
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"("" //abc)", to_find));
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"(/*abc*/ "")", to_find));
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"(/**abc*/ "")", to_find));
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"(/**abc**/ "")", to_find));
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"(/*abc)", to_find));
// note that the line end is escaped making the single line comment include the abc
REQUIRE_FALSE(contains_any_ignoring_c_comments("// test \\\nabc", to_find));
// note that the comment start is in a string literal so it isn't a comment
REQUIRE(contains_any_ignoring_c_comments("\"//\" test abc", to_find));
// note that the comment is in a raw string literal so it isn't a comment
REQUIRE(contains_any_ignoring_c_comments(R"-(R"( // abc )")-", to_find));
// found after the raw string literal
REQUIRE(contains_any_ignoring_c_comments(R"-(R"( // )" abc)-", to_find));
// comment after the raw string literal
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R"( // )" // abc)-", to_find));
// the above, but with a d_char_sequence for the raw literal
REQUIRE(contains_any_ignoring_c_comments(R"-(R"hello( // abc )hello")-", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"-(R"hello( // )hello" abc)-", to_find));
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R"hello( // )hello" // abc)-", to_find));
// the above, but with a d_char_sequence that is a needle
REQUIRE(contains_any_ignoring_c_comments(R"-(R"abc( // abc )abc")-", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"-(R"abc( // )abc" abc)-", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"-(R"abc( // )abc" // abc)-", to_find));
// raw literal termination edge cases
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R")-", to_find)); // ends input
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R"h)-", to_find)); // ends input d_char
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R"()-", to_find)); // ends input paren
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R"h()-", to_find)); // ends input paren d_char
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R"())-", to_find)); // ends input close paren
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"-(R"()")-", to_find)); // ends input exactly
// raw literal termination edge cases (success)
REQUIRE(contains_any_ignoring_c_comments(R"-(abcR")-", to_find)); // ends input
REQUIRE(contains_any_ignoring_c_comments(R"-(abcR"h)-", to_find)); // ends input d_char
REQUIRE(contains_any_ignoring_c_comments(R"-(abcR"()-", to_find)); // ends input paren
REQUIRE(contains_any_ignoring_c_comments(R"-(abcR"h()-", to_find)); // ends input paren d_char
REQUIRE(contains_any_ignoring_c_comments(R"-(abcR"())-", to_find)); // ends input close paren
REQUIRE(contains_any_ignoring_c_comments(R"-(abcR"()")-", to_find)); // ends input exactly
REQUIRE(contains_any_ignoring_c_comments(R"-(R"()"abc)-", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"-(R"hello( hello" // abc )")-", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"(R"-( // abc )-")", to_find));
REQUIRE_FALSE(contains_any_ignoring_c_comments(R"(R"-( // hello )-" // abc)", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"(R"-( /* abc */ )-")", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"(R"-()- /* abc */ )-")", to_find));
REQUIRE(contains_any_ignoring_c_comments(R"(qwer )", to_find));
REQUIRE(contains_any_ignoring_c_comments("\"a\" \"g\" // er \n abc)", to_find));
}
TEST_CASE ("contains_any_ignoring_hash_comments", "[strings]")
{
using vcpkg::Strings::contains_any_ignoring_hash_comments;
vcpkg::StringView to_find[] = {"abc", "wer"};
REQUIRE(contains_any_ignoring_hash_comments("abc", to_find));
REQUIRE(contains_any_ignoring_hash_comments("wer", to_find));
REQUIRE(contains_any_ignoring_hash_comments("wer # test", to_find));
REQUIRE(contains_any_ignoring_hash_comments("\n wer # \n test", to_find));
REQUIRE_FALSE(contains_any_ignoring_hash_comments("# wer", to_find));
REQUIRE_FALSE(contains_any_ignoring_hash_comments("\n# wer", to_find));
REQUIRE_FALSE(contains_any_ignoring_hash_comments("\n # wer\n", to_find));
REQUIRE_FALSE(contains_any_ignoring_hash_comments("\n test # wer", to_find));
}
TEST_CASE ("edit distance", "[strings]")
{
using vcpkg::Strings::byte_edit_distance;

Просмотреть файл

@ -659,13 +659,15 @@ namespace vcpkg
REGISTER_MESSAGE(FeedbackAppreciated);
REGISTER_MESSAGE(FetchingBaselineInfo);
REGISTER_MESSAGE(FetchingRegistryInfo);
REGISTER_MESSAGE(FishCompletion);
REGISTER_MESSAGE(FloatingPointConstTooBig);
REGISTER_MESSAGE(FileNotFound);
REGISTER_MESSAGE(FileReadFailed);
REGISTER_MESSAGE(FileSeekFailed);
REGISTER_MESSAGE(FilesExported);
REGISTER_MESSAGE(FileSystemOperationFailed);
REGISTER_MESSAGE(FishCompletion);
REGISTER_MESSAGE(FilesContainAbsolutePath1);
REGISTER_MESSAGE(FilesContainAbsolutePath2);
REGISTER_MESSAGE(FollowingPackagesMissingControl);
REGISTER_MESSAGE(FollowingPackagesNotInstalled);
REGISTER_MESSAGE(FollowingPackagesUpgraded);

Просмотреть файл

@ -382,6 +382,102 @@ Optional<StringView> Strings::find_at_most_one_enclosed(StringView input, String
return result.front();
}
bool vcpkg::Strings::contains_any_ignoring_c_comments(const std::string& source, View<StringView> to_find)
{
std::string::size_type offset = 0;
std::string::size_type no_comment_offset = 0;
while (offset != std::string::npos)
{
no_comment_offset = std::max(offset, no_comment_offset);
auto start = source.find_first_of("/\"", no_comment_offset);
if (start == std::string::npos || start + 1 == source.size() || no_comment_offset == std::string::npos)
{
return Strings::contains_any(StringView(source).substr(offset), to_find);
}
if (source[start] == '/')
{
if (source[start + 1] == '/' || source[start + 1] == '*')
{
if (Strings::contains_any(StringView(source).substr(offset, start - offset), to_find))
{
return true;
}
if (source[start + 1] == '/')
{
offset = source.find_first_of('\n', start);
while (offset != std::string::npos && source[offset - 1] == '\\')
offset = source.find_first_of('\n', offset + 1);
if (offset != std::string::npos) ++offset;
continue;
}
offset = source.find_first_of('/', start + 1);
while (offset != std::string::npos && source[offset - 1] != '*')
offset = source.find_first_of('/', offset + 1);
if (offset != std::string::npos) ++offset;
continue;
}
}
else if (source[start] == '\"')
{
if (start > 0 && source[start - 1] == 'R') // raw string literals
{
auto end = source.find_first_of('(', start);
if (end == std::string::npos)
{
// invalid c++, but allowed: auto test = 'R"'
no_comment_offset = start + 1;
continue;
}
auto d_char_sequence = ')' + source.substr(start + 1, end - start - 1);
d_char_sequence.push_back('\"');
no_comment_offset = source.find(d_char_sequence, end);
if (no_comment_offset != std::string::npos) no_comment_offset += d_char_sequence.size();
continue;
}
no_comment_offset = source.find_first_of('"', start + 1);
while (no_comment_offset != std::string::npos && source[no_comment_offset - 1] == '\\')
no_comment_offset = source.find_first_of('"', no_comment_offset + 1);
if (no_comment_offset != std::string::npos) ++no_comment_offset;
continue;
}
no_comment_offset = start + 1;
}
return false;
}
bool Strings::contains_any_ignoring_hash_comments(StringView source, View<StringView> to_find)
{
auto first = source.data();
auto block_start = first;
const auto last = first + source.size();
for (; first != last; ++first)
{
if (*first == '#')
{
if (Strings::contains_any(StringView{block_start, first}, to_find))
{
return true;
}
first = std::find(first, last, '\n'); // skip comment
if (first == last)
{
return false;
}
block_start = first;
}
}
return Strings::contains_any(StringView{block_start, last}, to_find);
}
bool Strings::contains_any(StringView source, View<StringView> to_find)
{
return Util::any_of(to_find, [=](StringView s) { return Strings::contains(source, s); });
}
bool Strings::equals(StringView a, StringView b)
{
if (a.size() != b.size()) return false;

Просмотреть файл

@ -219,6 +219,7 @@ namespace vcpkg
static const std::string NAME_SKIP_DUMPBIN_CHECKS = "PolicySkipDumpbinChecks";
static const std::string NAME_SKIP_ARCHITECTURE_CHECK = "PolicySkipArchitectureCheck";
static const std::string NAME_CMAKE_HELPER_PORT = "PolicyCmakeHelperPort";
static const std::string NAME_SKIP_ABSOLUTE_PATHS_CHECK = "PolicySkipAbsolutePathsCheck";
static std::remove_const_t<decltype(ALL_POLICIES)> generate_all_policies()
{
@ -249,6 +250,7 @@ namespace vcpkg
case BuildPolicy::SKIP_DUMPBIN_CHECKS: return NAME_SKIP_DUMPBIN_CHECKS;
case BuildPolicy::SKIP_ARCHITECTURE_CHECK: return NAME_SKIP_ARCHITECTURE_CHECK;
case BuildPolicy::CMAKE_HELPER_PORT: return NAME_CMAKE_HELPER_PORT;
case BuildPolicy::SKIP_ABSOLUTE_PATHS_CHECK: return NAME_SKIP_ABSOLUTE_PATHS_CHECK;
default: Checks::unreachable(VCPKG_LINE_INFO);
}
}
@ -269,6 +271,7 @@ namespace vcpkg
case BuildPolicy::SKIP_DUMPBIN_CHECKS: return "VCPKG_POLICY_SKIP_DUMPBIN_CHECKS";
case BuildPolicy::SKIP_ARCHITECTURE_CHECK: return "VCPKG_POLICY_SKIP_ARCHITECTURE_CHECK";
case BuildPolicy::CMAKE_HELPER_PORT: return "VCPKG_POLICY_CMAKE_HELPER_PORT";
case BuildPolicy::SKIP_ABSOLUTE_PATHS_CHECK: return "VCPKG_POLICY_SKIP_ABSOLUTE_PATHS_CHECK";
default: Checks::unreachable(VCPKG_LINE_INFO);
}
}

Просмотреть файл

@ -1,10 +1,12 @@
#include <vcpkg/base/cofffilereader.h>
#include <vcpkg/base/files.h>
#include <vcpkg/base/messages.h>
#include <vcpkg/base/system.print.h>
#include <vcpkg/base/system.process.h>
#include <vcpkg/base/util.h>
#include <vcpkg/build.h>
#include <vcpkg/installedpaths.h>
#include <vcpkg/packagespec.h>
#include <vcpkg/postbuildlint.buildtype.h>
#include <vcpkg/postbuildlint.h>
@ -972,6 +974,98 @@ namespace vcpkg::PostBuildLint
return LintStatus::SUCCESS;
}
static bool file_contains_absolute_paths(const Filesystem& fs,
const Path& file,
const std::vector<StringView> stringview_paths)
{
const auto extension = file.extension();
if (extension == ".h" || extension == ".hpp" || extension == ".hxx")
{
return Strings::contains_any_ignoring_c_comments(fs.read_contents(file, IgnoreErrors{}), stringview_paths);
}
if (extension == ".cfg" || extension == ".ini" || file.filename() == "usage")
{
const auto contents = fs.read_contents(file, IgnoreErrors{});
return Strings::contains_any(contents, stringview_paths);
}
if (extension == ".py" || extension == ".sh" || extension == ".cmake" || extension == ".pc" ||
extension == ".conf")
{
const auto contents = fs.read_contents(file, IgnoreErrors{});
return Strings::contains_any_ignoring_hash_comments(contents, stringview_paths);
}
if (extension.empty())
{
std::error_code ec;
ReadFilePointer read_file(file, ec);
if (ec) return false;
char buffer[5];
if (read_file.read(buffer, 1, sizeof(buffer)) < sizeof(buffer)) return false;
if (Strings::starts_with(StringView(buffer, sizeof(buffer)), "#!") ||
Strings::starts_with(StringView(buffer, sizeof(buffer)), "\xEF\xBB\xBF#!") /* ignore byte-order mark */)
{
const auto contents = fs.read_contents(file, IgnoreErrors{});
return Strings::contains_any_ignoring_hash_comments(contents, stringview_paths);
}
return false;
}
return false;
}
static LintStatus check_no_absolute_paths_in(const Filesystem& fs, const Path& dir, Span<Path> absolute_paths)
{
std::vector<std::string> string_paths;
for (const auto& path : absolute_paths)
{
#if defined(_WIN32)
// As supplied, all /s, and all \s
string_paths.push_back(path.native());
auto path_preferred = path;
path_preferred.make_preferred();
string_paths.push_back(path_preferred.native());
string_paths.push_back(path.generic_u8string());
#else
string_paths.push_back(path.native());
#endif
}
Util::sort_unique_erase(string_paths);
const auto stringview_paths = Util::fmap(string_paths, [](std::string& s) { return StringView(s); });
std::vector<Path> failing_files;
for (auto&& file : fs.get_regular_files_recursive(dir, IgnoreErrors{}))
{
if (file_contains_absolute_paths(fs, file, stringview_paths))
{
failing_files.push_back(file);
}
}
if (failing_files.empty())
{
return LintStatus::SUCCESS;
}
auto error_message = msg::format(msgFilesContainAbsolutePath1);
for (auto&& absolute_path : absolute_paths)
{
error_message.append_raw('\n').append_indent().append_raw(absolute_path);
}
error_message.append_raw('\n').append(msgFilesContainAbsolutePath2);
for (auto&& failure : failing_files)
{
error_message.append_raw('\n').append_indent().append_raw(failure);
}
msg::println_warning(error_message);
return LintStatus::PROBLEM_DETECTED;
}
static void operator+=(size_t& left, const LintStatus& right) { left += static_cast<size_t>(right); }
static size_t perform_all_checks_and_return_error_count(const PackageSpec& spec,
@ -1100,6 +1194,11 @@ namespace vcpkg::PostBuildLint
error_count += check_no_files_in_dir(fs, package_dir);
error_count += check_no_files_in_dir(fs, package_dir / "debug");
error_count += check_pkgconfig_dir_only_in_lib_dir(fs, package_dir);
if (!build_info.policies.is_enabled(BuildPolicy::SKIP_ABSOLUTE_PATHS_CHECK))
{
error_count += check_no_absolute_paths_in(
fs, package_dir, std::vector<Path>{package_dir, paths.installed().root(), paths.build_dir(spec)});
}
return error_count;
}