mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11688 from ethereum/fix-and-document-allow-paths
Fix and document `--allow-paths`
This commit is contained in:
@@ -160,6 +160,7 @@ set(solcli_sources
|
||||
solc/Common.cpp
|
||||
solc/Common.h
|
||||
solc/CommandLineInterface.cpp
|
||||
solc/CommandLineInterfaceAllowPaths.cpp
|
||||
solc/CommandLineParser.cpp
|
||||
)
|
||||
detect_stray_source_files("${solcli_sources}" "solc/")
|
||||
|
||||
@@ -53,13 +53,17 @@ void solidity::test::createFileWithContent(boost::filesystem::path const& _path,
|
||||
}
|
||||
|
||||
bool solidity::test::createSymlinkIfSupportedByFilesystem(
|
||||
boost::filesystem::path const& _targetPath,
|
||||
boost::filesystem::path _targetPath,
|
||||
boost::filesystem::path const& _linkName,
|
||||
bool _directorySymlink
|
||||
)
|
||||
{
|
||||
boost::system::error_code symlinkCreationError;
|
||||
|
||||
// NOTE: On Windows / works as a separator in a symlink target only if the target is absolute.
|
||||
// Convert path separators to native ones to avoid this problem.
|
||||
_targetPath.make_preferred();
|
||||
|
||||
if (_directorySymlink)
|
||||
boost::filesystem::create_directory_symlink(_targetPath, _linkName, symlinkCreationError);
|
||||
else
|
||||
|
||||
@@ -46,7 +46,7 @@ void createFileWithContent(boost::filesystem::path const& _path, std::string con
|
||||
/// support symlinks.
|
||||
/// Throws an exception of the operation fails for a different reason.
|
||||
bool createSymlinkIfSupportedByFilesystem(
|
||||
boost::filesystem::path const& _targetPath,
|
||||
boost::filesystem::path _targetPath,
|
||||
boost::filesystem::path const& _linkName,
|
||||
bool _directorySymlink
|
||||
);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
-
|
||||
@@ -1,11 +0,0 @@
|
||||
Error: Source "too_long_line/input.sol" not found: File outside of allowed directories.
|
||||
--> <stdin>:4:1:
|
||||
|
|
||||
4 | import "../too_long_line/input.sol";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Error: Source "error_codes/input.sol" not found: File outside of allowed directories.
|
||||
--> stdin_allowed_paths/input.sol:4:1:
|
||||
|
|
||||
4 | import "../error_codes/input.sol";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1,4 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0;
|
||||
|
||||
import "../error_codes/input.sol";
|
||||
@@ -1,4 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0;
|
||||
|
||||
import "../too_long_line/input.sol";
|
||||
@@ -36,31 +36,39 @@ using namespace solidity::test;
|
||||
namespace solidity::frontend::test
|
||||
{
|
||||
|
||||
using SymlinkResolution = FileReader::SymlinkResolution;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(FileReaderTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_absolute_path)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/"), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./"), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./."), "/");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/.", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./.", resolveSymlinks), "/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a"), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/"), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/."), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./a"), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./a/"), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./a/."), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b"), "/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a", resolveSymlinks), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/", resolveSymlinks), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/.", resolveSymlinks), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./a", resolveSymlinks), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./a/", resolveSymlinks), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/./a/.", resolveSymlinks), "/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b", resolveSymlinks), "/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/", resolveSymlinks), "/a/b/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/./b/"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/../a/b/"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/.."), "/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/../"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/..", resolveSymlinks), "/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/../", resolveSymlinks), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/./b/", resolveSymlinks), "/a/b/");
|
||||
#if !defined(_WIN32) || BOOST_VERSION > 107600
|
||||
// This throws on Windows due to a bug in Boost: https://github.com/boostorg/filesystem/issues/201
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/../a/b/", resolveSymlinks), "/a/b/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/../../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/../../../"), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/../../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b/c/../../../", resolveSymlinks), "/");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_relative_path)
|
||||
@@ -75,54 +83,64 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_relative_path)
|
||||
expectedPrefix = "/" / expectedPrefix.relative_path();
|
||||
soltestAssert(expectedPrefix.is_absolute() || expectedPrefix.root_path() == "/", "");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("."), expectedPrefix / "x/y/z/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./"), expectedPrefix / "x/y/z/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(".//"), expectedPrefix / "x/y/z/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(".."), expectedPrefix / "x/y");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../"), expectedPrefix / "x/y/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("..//"), expectedPrefix / "x/y/");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(".", resolveSymlinks), expectedPrefix / "x/y/z/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./", resolveSymlinks), expectedPrefix / "x/y/z/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(".//", resolveSymlinks), expectedPrefix / "x/y/z/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("..", resolveSymlinks), expectedPrefix / "x/y");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../", resolveSymlinks), expectedPrefix / "x/y/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("..//", resolveSymlinks), expectedPrefix / "x/y/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a"), expectedPrefix / "x/y/z/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/"), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/."), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a"), expectedPrefix / "x/y/z/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/"), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/."), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/./"), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/.//"), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/./."), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/././"), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/././/"), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b"), expectedPrefix / "x/y/z/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/"), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a", resolveSymlinks), expectedPrefix / "x/y/z/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/.", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a", resolveSymlinks), expectedPrefix / "x/y/z/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/.", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/./", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/.//", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/./.", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/././", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/././/", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b", resolveSymlinks), expectedPrefix / "x/y/z/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/", resolveSymlinks), expectedPrefix / "x/y/z/a/b/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a/b"), expectedPrefix / "x/y/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/b"), expectedPrefix / "x/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/b"), expectedPrefix / "x/y/z/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("././a/b"), expectedPrefix / "x/y/z/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a/b", resolveSymlinks), expectedPrefix / "x/y/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/b", resolveSymlinks), expectedPrefix / "x/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("./a/b", resolveSymlinks), expectedPrefix / "x/y/z/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("././a/b", resolveSymlinks), expectedPrefix / "x/y/z/a/b");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/./b/"), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/../a/b/"), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/.."), expectedPrefix / "x/y/z/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../"), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/..//"), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../.."), expectedPrefix / "x/y/z/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../../"), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../..//"), expectedPrefix / "x/y/z/a/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/.././../p/../q/../a/b"), expectedPrefix / "a/b");
|
||||
#if !defined(_WIN32) || BOOST_VERSION > 107600
|
||||
// This throws on Windows due to a bug in Boost: https://github.com/boostorg/filesystem/issues/201
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/.././../p/../q/../a/b", resolveSymlinks), expectedPrefix / "a/b");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/../a/b/", resolveSymlinks), expectedPrefix / "x/y/z/a/b/");
|
||||
#endif
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/./b/", resolveSymlinks), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/..", resolveSymlinks), expectedPrefix / "x/y/z/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../", resolveSymlinks), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/..//", resolveSymlinks), expectedPrefix / "x/y/z/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../..", resolveSymlinks), expectedPrefix / "x/y/z/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../../", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/b/c/../..//", resolveSymlinks), expectedPrefix / "x/y/z/a/");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_redundant_slashes)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("///"), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("////"), "/");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("///", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("////", resolveSymlinks), "/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("////a/b/"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a//b/"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a////b/"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b//"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b////"), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("////a/b/", resolveSymlinks), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a//b/", resolveSymlinks), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a////b/", resolveSymlinks), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b//", resolveSymlinks), "/a/b/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/b////", resolveSymlinks), "/a/b/");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_unc_path)
|
||||
@@ -134,23 +152,26 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_unc_path)
|
||||
boost::filesystem::path expectedWorkDir = "/" / boost::filesystem::current_path().relative_path();
|
||||
soltestAssert(expectedWorkDir.is_absolute() || expectedWorkDir.root_path() == "/", "");
|
||||
|
||||
// UNC paths start with // or \\ followed by a name. They are used for network shares on Windows.
|
||||
// On UNIX systems they are not supported but still treated in a special way.
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/"), "//host/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b"), "//host/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b/"), "//host/a/b/");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
// UNC paths start with // or \\ followed by a name. They are used for network shares on Windows.
|
||||
// On UNIX systems they are not supported but still treated in a special way.
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/", resolveSymlinks), "//host/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b", resolveSymlinks), "//host/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host/a/b/", resolveSymlinks), "//host/a/b/");
|
||||
|
||||
#if defined(_WIN32)
|
||||
// On Windows an UNC path can also start with \\ instead of //
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/"), "//host/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b"), "//host/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b/"), "//host/a/b/");
|
||||
// On Windows an UNC path can also start with \\ instead of //
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/", resolveSymlinks), "//host/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b", resolveSymlinks), "//host/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b/", resolveSymlinks), "//host/a/b/");
|
||||
#else
|
||||
// On UNIX systems it's just a fancy relative path instead
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/"), expectedWorkDir / "\\\\host/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b"), expectedWorkDir / "\\\\host/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b/"), expectedWorkDir / "\\\\host/a/b/");
|
||||
// On UNIX systems it's just a fancy relative path instead
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/", resolveSymlinks), expectedWorkDir / "\\\\host/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b", resolveSymlinks), expectedWorkDir / "\\\\host/a/b");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("\\\\host/a/b/", resolveSymlinks), expectedWorkDir / "\\\\host/a/b/");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_root_name_only)
|
||||
@@ -167,20 +188,23 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_root_name_only)
|
||||
// C:\ represents the root directory of drive C: but C: on its own refers to the current working
|
||||
// directory.
|
||||
|
||||
// UNC paths
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//"), "//" / expectedWorkDir);
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host"), "//host" / expectedWorkDir);
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
// UNC paths
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//", resolveSymlinks), "//" / expectedWorkDir);
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("//host", resolveSymlinks), "//host" / expectedWorkDir);
|
||||
|
||||
// On UNIX systems root name is empty.
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(""), expectedWorkDir);
|
||||
// On UNIX systems root name is empty.
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("", resolveSymlinks), expectedWorkDir);
|
||||
|
||||
#if defined(_WIN32)
|
||||
boost::filesystem::path driveLetter = boost::filesystem::current_path().root_name();
|
||||
solAssert(!driveLetter.empty(), "");
|
||||
solAssert(driveLetter.is_relative(), "");
|
||||
boost::filesystem::path driveLetter = boost::filesystem::current_path().root_name();
|
||||
solAssert(!driveLetter.empty(), "");
|
||||
solAssert(driveLetter.is_relative(), "");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(driveLetter), expectedWorkDir);
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(driveLetter, resolveSymlinks), expectedWorkDir);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_stripping_root_name)
|
||||
@@ -193,41 +217,55 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_stripping_root_name)
|
||||
soltestAssert(!boost::filesystem::current_path().root_name().empty(), "");
|
||||
#endif
|
||||
|
||||
boost::filesystem::path normalizedPath = FileReader::normalizeCLIPathForVFS(boost::filesystem::current_path());
|
||||
BOOST_CHECK_EQUAL(normalizedPath, "/" / boost::filesystem::current_path().relative_path());
|
||||
BOOST_TEST(normalizedPath.root_name().empty());
|
||||
BOOST_CHECK_EQUAL(normalizedPath.root_directory(), "/");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
boost::filesystem::path normalizedPath = FileReader::normalizeCLIPathForVFS(
|
||||
boost::filesystem::current_path(),
|
||||
resolveSymlinks
|
||||
);
|
||||
BOOST_CHECK_EQUAL(normalizedPath, "/" / boost::filesystem::current_path().relative_path());
|
||||
BOOST_TEST(normalizedPath.root_name().empty());
|
||||
BOOST_CHECK_EQUAL(normalizedPath.root_directory(), "/");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_path_beyond_root)
|
||||
{
|
||||
TemporaryWorkingDirectory tempWorkDir("/");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../"), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../a"), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../a/.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../a/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../../a"), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../../a/.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../../a/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/../../b/../.."), "/");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../.", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../a", resolveSymlinks), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../../a", resolveSymlinks), "/a");
|
||||
#if !defined(_WIN32) || BOOST_VERSION > 107600
|
||||
// This throws on Windows due to a bug in Boost: https://github.com/boostorg/filesystem/issues/201
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../a/..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../a/../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../../a/..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/../../a/../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("/a/../../b/../..", resolveSymlinks), "/");
|
||||
#endif
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(".."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../"), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a"), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a/.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a"), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/../../b/../.."), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../.", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a", resolveSymlinks), "/a");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a", resolveSymlinks), "/a");
|
||||
#if !defined(_WIN32) || BOOST_VERSION > 107600
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a/..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../a/../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("../../a/../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/../..", resolveSymlinks), "/");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("a/../../b/../..", resolveSymlinks), "/");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_case_sensitivity)
|
||||
@@ -235,22 +273,31 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_case_sensitivity)
|
||||
TemporaryDirectory tempDir(TEST_CASE_NAME);
|
||||
TemporaryWorkingDirectory tempWorkDir(tempDir);
|
||||
|
||||
boost::filesystem::path expectedPrefix = "/" / tempDir.path().relative_path();
|
||||
soltestAssert(expectedPrefix.is_absolute() || expectedPrefix.root_path() == "/", "");
|
||||
boost::filesystem::path workDirNoSymlinks = boost::filesystem::weakly_canonical(tempDir);
|
||||
boost::filesystem::path expectedPrefix = "/" / workDirNoSymlinks.relative_path();
|
||||
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc") == expectedPrefix / "abc");
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc") != expectedPrefix / "ABC");
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(tempDir.path() / "ABC") != expectedPrefix / "abc");
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(tempDir.path() / "ABC") == expectedPrefix / "ABC");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(workDirNoSymlinks / "abc", resolveSymlinks) == expectedPrefix / "abc");
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(workDirNoSymlinks / "abc", resolveSymlinks) != expectedPrefix / "ABC");
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(workDirNoSymlinks / "ABC", resolveSymlinks) != expectedPrefix / "abc");
|
||||
BOOST_TEST(FileReader::normalizeCLIPathForVFS(workDirNoSymlinks / "ABC", resolveSymlinks) == expectedPrefix / "ABC");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_path_separators)
|
||||
{
|
||||
// Even on Windows we want / as a separator.
|
||||
BOOST_TEST((FileReader::normalizeCLIPathForVFS("/a/b/c").native() == boost::filesystem::path("/a/b/c").native()));
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
// Even on Windows we want / as a separator.
|
||||
BOOST_TEST((
|
||||
FileReader::normalizeCLIPathForVFS("/a/b/c", resolveSymlinks).native() ==
|
||||
boost::filesystem::path("/a/b/c").native()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_should_not_resolve_symlinks)
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_should_not_resolve_symlinks_unless_requested)
|
||||
{
|
||||
TemporaryDirectory tempDir({"abc/"}, TEST_CASE_NAME);
|
||||
soltestAssert(tempDir.path().is_absolute(), "");
|
||||
@@ -258,11 +305,26 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_should_not_resolve_symlinks)
|
||||
if (!createSymlinkIfSupportedByFilesystem(tempDir.path() / "abc", tempDir.path() / "sym", true))
|
||||
return;
|
||||
|
||||
boost::filesystem::path expectedPrefix = "/" / tempDir.path().relative_path();
|
||||
soltestAssert(expectedPrefix.is_absolute() || expectedPrefix.root_path() == "/", "");
|
||||
boost::filesystem::path expectedPrefixWithSymlinks = "/" / tempDir.path().relative_path();
|
||||
boost::filesystem::path expectedPrefixWithoutSymlinks = "/" / boost::filesystem::weakly_canonical(tempDir).relative_path();
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol"), expectedPrefix / "sym/contract.sol");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc/contract.sol"), expectedPrefix / "abc/contract.sol");
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol", SymlinkResolution::Disabled),
|
||||
expectedPrefixWithSymlinks / "sym/contract.sol"
|
||||
);
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc/contract.sol", SymlinkResolution::Disabled),
|
||||
expectedPrefixWithSymlinks / "abc/contract.sol"
|
||||
);
|
||||
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol", SymlinkResolution::Enabled),
|
||||
expectedPrefixWithoutSymlinks / "abc/contract.sol"
|
||||
);
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc/contract.sol", SymlinkResolution::Enabled),
|
||||
expectedPrefixWithoutSymlinks / "abc/contract.sol"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_should_resolve_symlinks_in_workdir_when_path_is_relative)
|
||||
@@ -280,9 +342,31 @@ BOOST_AUTO_TEST_CASE(normalizeCLIPathForVFS_should_resolve_symlinks_in_workdir_w
|
||||
boost::filesystem::path expectedPrefix = "/" / tempDir.path().relative_path();
|
||||
soltestAssert(expectedPrefix.is_absolute() || expectedPrefix.root_path() == "/", "");
|
||||
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS("contract.sol"), expectedWorkDir / "contract.sol");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol"), expectedPrefix / "sym/contract.sol");
|
||||
BOOST_CHECK_EQUAL(FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc/contract.sol"), expectedPrefix / "abc/contract.sol");
|
||||
for (SymlinkResolution resolveSymlinks: {SymlinkResolution::Enabled, SymlinkResolution::Disabled})
|
||||
{
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS("contract.sol", resolveSymlinks),
|
||||
expectedWorkDir / "contract.sol"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol", SymlinkResolution::Disabled),
|
||||
expectedPrefix / "sym/contract.sol"
|
||||
);
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc/contract.sol", SymlinkResolution::Disabled),
|
||||
expectedPrefix / "abc/contract.sol"
|
||||
);
|
||||
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "sym/contract.sol", SymlinkResolution::Enabled),
|
||||
expectedWorkDir / "contract.sol"
|
||||
);
|
||||
BOOST_CHECK_EQUAL(
|
||||
FileReader::normalizeCLIPathForVFS(tempDir.path() / "abc/contract.sol", SymlinkResolution::Enabled),
|
||||
expectedWorkDir / "contract.sol"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(isPathPrefix_file_prefix)
|
||||
|
||||
@@ -786,12 +786,7 @@ BOOST_AUTO_TEST_CASE(cli_paths_to_source_unit_names_symlinks)
|
||||
TemporaryWorkingDirectory tempWorkDir(tempDir.path() / "r");
|
||||
|
||||
if (
|
||||
#if !defined(_WIN32)
|
||||
!createSymlinkIfSupportedByFilesystem("../x/y", tempDir.path() / "r/sym", true) ||
|
||||
#else
|
||||
// NOTE: On Windows / works as a separator in a symlink target only if the target is absolute
|
||||
!createSymlinkIfSupportedByFilesystem("..\\x\\y", tempDir.path() / "r/sym", true) ||
|
||||
#endif
|
||||
!createSymlinkIfSupportedByFilesystem("contract.sol", tempDir.path() / "x/y/z/contract_symlink.sol", false)
|
||||
)
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,539 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
/// Unit tests for solc/CommandLineInterface.h
|
||||
|
||||
#include <solc/CommandLineInterface.h>
|
||||
|
||||
#include <test/solc/Common.h>
|
||||
|
||||
#include <test/Common.h>
|
||||
#include <test/FilesystemUtils.h>
|
||||
#include <test/TemporaryDirectory.h>
|
||||
#include <test/libsolidity/util/SoltestErrors.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::test;
|
||||
|
||||
#define TEST_CASE_NAME (boost::unit_test::framework::current_test_case().p_name)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct ImportCheck
|
||||
{
|
||||
enum class Result
|
||||
{
|
||||
Unknown, ///< Status is unknown due to a failure of the status check.
|
||||
OK, ///< Passed compilation without errors.
|
||||
FileNotFound, ///< Error was reported: file not found.
|
||||
PathDisallowed, ///< Error was reported: file not allowed paths.
|
||||
};
|
||||
|
||||
bool operator==(ImportCheck const& _other) const { return result == _other.result && message == _other.message; }
|
||||
bool operator!=(ImportCheck const& _other) const { return !(*this == _other); }
|
||||
|
||||
operator bool() const { return this->result == Result::OK; }
|
||||
|
||||
static ImportCheck const OK() { return {Result::OK, ""}; }
|
||||
static ImportCheck const FileNotFound() { return {Result::FileNotFound, ""}; }
|
||||
static ImportCheck const PathDisallowed() { return {Result::PathDisallowed, ""}; }
|
||||
static ImportCheck const Unknown(const string& _message) { return {Result::Unknown, _message}; }
|
||||
|
||||
Result result;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
ImportCheck checkImport(
|
||||
string const& _import,
|
||||
vector<string> const& _cliOptions
|
||||
)
|
||||
{
|
||||
soltestAssert(regex_match(_import, regex{R"(import '[^']*')"}), "");
|
||||
for (string const& option: _cliOptions)
|
||||
soltestAssert(
|
||||
boost::starts_with(option, "--base-path") ||
|
||||
boost::starts_with(option, "--allow-paths") ||
|
||||
!boost::starts_with(option, "--"),
|
||||
""
|
||||
);
|
||||
|
||||
vector<string> commandLine = {
|
||||
"solc",
|
||||
"-",
|
||||
"--no-color",
|
||||
"--error-codes",
|
||||
};
|
||||
commandLine += _cliOptions;
|
||||
|
||||
string standardInputContent =
|
||||
"// SPDX-License-Identifier: GPL-3.0\n"
|
||||
"pragma solidity >=0.0;\n" +
|
||||
_import + ";";
|
||||
|
||||
test::OptionsReaderAndMessages cliResult = test::parseCommandLineAndReadInputFiles(
|
||||
commandLine,
|
||||
standardInputContent,
|
||||
true /* processInput */
|
||||
);
|
||||
if (cliResult.success)
|
||||
return ImportCheck::OK();
|
||||
|
||||
static regex const sourceNotFoundErrorRegex{
|
||||
R"(^Error \(6275\): Source ".+" not found: (.*)\.\n)"
|
||||
R"(\s*--> .*<stdin>:\d+:\d+:\n)"
|
||||
R"(\s*\|\n)"
|
||||
R"(\d+\s*\| import '.+';\n)"
|
||||
R"(\s*\| \^+\n\s*$)"
|
||||
};
|
||||
|
||||
smatch submatches;
|
||||
if (!regex_match(cliResult.stderrContent, submatches, sourceNotFoundErrorRegex))
|
||||
return ImportCheck::Unknown("Unexpected stderr content: '" + cliResult.stderrContent + "'");
|
||||
if (submatches[1] != "File not found" && submatches[1] != "File outside of allowed directories")
|
||||
return ImportCheck::Unknown("Unexpected error message: '" + cliResult.stderrContent + "'");
|
||||
|
||||
if (submatches[1] == "File not found")
|
||||
return ImportCheck::FileNotFound();
|
||||
else if (submatches[1] == "File outside of allowed directories")
|
||||
return ImportCheck::PathDisallowed();
|
||||
else
|
||||
return ImportCheck::Unknown("Unexpected error message '" + submatches[1].str() + "'");
|
||||
}
|
||||
|
||||
class AllowPathsFixture
|
||||
{
|
||||
protected:
|
||||
AllowPathsFixture():
|
||||
m_tempDir({"code/", "work/"}, TEST_CASE_NAME),
|
||||
m_tempWorkDir(m_tempDir.path() / "work"),
|
||||
m_codeDir(m_tempDir.path() / "code"),
|
||||
m_workDir(m_tempDir.path() / "work"),
|
||||
m_portablePrefix(("/" / boost::filesystem::canonical(m_codeDir).relative_path()).generic_string())
|
||||
{
|
||||
createFilesWithParentDirs(
|
||||
{
|
||||
m_codeDir / "a/b/c/d.sol",
|
||||
m_codeDir / "a/b/c.sol",
|
||||
m_codeDir / "a/b/X.sol",
|
||||
m_codeDir / "a/X/c.sol",
|
||||
m_codeDir / "X/b/c.sol",
|
||||
|
||||
m_codeDir / "a/bc/d.sol",
|
||||
m_codeDir / "X/bc/d.sol",
|
||||
|
||||
m_codeDir / "x/y/z.sol",
|
||||
m_codeDir / "contract.sol",
|
||||
|
||||
m_workDir / "a/b/c/d.sol",
|
||||
m_workDir / "a/b/c.sol",
|
||||
m_workDir / "a/b/X.sol",
|
||||
m_workDir / "a/X/c.sol",
|
||||
m_workDir / "X/b/c.sol",
|
||||
|
||||
m_workDir / "contract.sol",
|
||||
},
|
||||
"// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;"
|
||||
);
|
||||
|
||||
if (
|
||||
!createSymlinkIfSupportedByFilesystem("b", m_codeDir / "a/b_sym", true) ||
|
||||
!createSymlinkIfSupportedByFilesystem("../x/y", m_codeDir / "a/y_sym", true) ||
|
||||
!createSymlinkIfSupportedByFilesystem("../../a/b/c.sol", m_codeDir / "a/b/c_sym.sol", false) ||
|
||||
!createSymlinkIfSupportedByFilesystem("../../x/y/z.sol", m_codeDir / "a/b/z_sym.sol", false)
|
||||
)
|
||||
return;
|
||||
|
||||
m_caseSensitiveFilesystem = boost::filesystem::create_directories(m_codeDir / "A/B/C");
|
||||
soltestAssert(boost::filesystem::equivalent(m_codeDir / "a/b/c", m_codeDir / "A/B/C") != m_caseSensitiveFilesystem, "");
|
||||
}
|
||||
|
||||
TemporaryDirectory m_tempDir;
|
||||
TemporaryWorkingDirectory m_tempWorkDir;
|
||||
boost::filesystem::path const m_codeDir;
|
||||
boost::filesystem::path const m_workDir;
|
||||
string m_portablePrefix;
|
||||
bool m_caseSensitiveFilesystem = true;
|
||||
};
|
||||
|
||||
ostream& operator<<(ostream& _out, ImportCheck const& _value)
|
||||
{
|
||||
switch (_value.result)
|
||||
{
|
||||
case ImportCheck::Result::Unknown: _out << "Unknown"; break;
|
||||
case ImportCheck::Result::OK: _out << "OK"; break;
|
||||
case ImportCheck::Result::FileNotFound: _out << "FileNotFound"; break;
|
||||
case ImportCheck::Result::PathDisallowed: _out << "PathDisallowed"; break;
|
||||
}
|
||||
if (_value.message != "")
|
||||
_out << "(" << _value.message << ")";
|
||||
return _out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace boost::test_tools::tt_detail
|
||||
{
|
||||
|
||||
// Boost won't find the << operator unless we put it in the std namespace which is illegal.
|
||||
// The recommended solution is to overload print_log_value<> struct and make it use our operator.
|
||||
|
||||
template<>
|
||||
struct print_log_value<ImportCheck>
|
||||
{
|
||||
void operator()(std::ostream& _out, ImportCheck const& _value) { ::operator<<(_out, _value); }
|
||||
};
|
||||
|
||||
} // namespace boost::test_tools::tt_detail
|
||||
|
||||
namespace solidity::frontend::test
|
||||
{
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(CommandLineInterfaceAllowPathsTest)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_multiple_paths, AllowPathsFixture)
|
||||
{
|
||||
string allowedPaths =
|
||||
m_codeDir.generic_string() + "/a/b/X.sol," +
|
||||
m_codeDir.generic_string() + "/X/," +
|
||||
m_codeDir.generic_string() + "/z," +
|
||||
m_codeDir.generic_string() + "/a/b";
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths", allowedPaths}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"--allow-paths", allowedPaths}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"--allow-paths", allowedPaths}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"--allow-paths", allowedPaths}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_should_work_with_various_path_forms, AllowPathsFixture)
|
||||
{
|
||||
string import = "import '" + m_portablePrefix + "/a/b/c.sol'";
|
||||
|
||||
// Without --allow-path
|
||||
BOOST_TEST(checkImport(import, {}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Absolute paths allowed
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", m_codeDir.string()}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", m_codeDir.string() + "/a"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", m_codeDir.string() + "/a/"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", m_codeDir.string() + "/a/b"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", m_codeDir.string() + "/a/b/c.sol"}));
|
||||
|
||||
// Relative paths allowed
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=../code/a"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=../code/a/"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=../code/a/b"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=../code/a/b/c.sol"}));
|
||||
|
||||
// Non-normalized paths allowed
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/."}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/./"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a/.."}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a/../"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a/b"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a/./b"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a/../a/b"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a///b"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a/b//"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", "./../code/a/b///"}));
|
||||
|
||||
// Root path allowed
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=/"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=///"}));
|
||||
|
||||
// UNC paths should be treated differently from normal paths
|
||||
soltestAssert(FileReader::isUNCPath("/" + m_portablePrefix), "");
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=//"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=/" + m_portablePrefix}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Paths going beyond root allowed
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=/../../"}));
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=/../.."}));
|
||||
#if !defined(_WIN32) || BOOST_VERSION > 107600
|
||||
// This throws on Windows due to a bug in Boost: https://github.com/boostorg/filesystem/issues/201
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=/../../a/../"}));
|
||||
#endif
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths=/../../" + m_portablePrefix}));
|
||||
|
||||
// File named like a directory
|
||||
BOOST_TEST(checkImport(import, {"--allow-paths", m_codeDir.string() + "/a/b/c.sol/"}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_should_handle_empty_paths, AllowPathsFixture)
|
||||
{
|
||||
// Work dir is base path
|
||||
BOOST_TEST(checkImport("import 'a/../../work/a/b/c.sol'", {"--allow-paths", ""}));
|
||||
BOOST_TEST(checkImport("import 'a/../../work/a/b/c.sol'", {"--allow-paths", "x,,y"}));
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/b/c.sol'", {"--allow-paths", ""}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/b/c.sol'", {"--allow-paths", "x,,y"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Work dir is not base path
|
||||
BOOST_TEST(checkImport("import 'a/../../work/a/b/c.sol'", {"--allow-paths", "", "--base-path=../code/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import 'a/../../work/a/b/c.sol'", {"--allow-paths", "x,,y", "--base-path=../code/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/b/c.sol'", {"--allow-paths", "", "--base-path=../code/"}));
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/b/c.sol'", {"--allow-paths", "x,,y", "--base-path=../code/"}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_case_sensitive, AllowPathsFixture)
|
||||
{
|
||||
// Allowed paths are case-sensitive even on case-insensitive filesystems
|
||||
BOOST_TEST(
|
||||
checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths", m_codeDir.string() + "/A/B/"}) ==
|
||||
ImportCheck::PathDisallowed()
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_should_work_with_various_import_forms, AllowPathsFixture)
|
||||
{
|
||||
// Absolute import paths
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths", "../code/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"--allow-paths", "../code/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"--allow-paths", "../code/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"--allow-paths", "../code/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths", "../code/a/b/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"--allow-paths", "../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"--allow-paths", "../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"--allow-paths", "../code/a/b/"}));
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths", "../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"--allow-paths", "../code/a/b"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"--allow-paths", "../code/a/b"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"--allow-paths", "../code/a/b"}));
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths", "../code/a"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"--allow-paths", "../code/a"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"--allow-paths", "../code/a"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"--allow-paths", "../code/a"}));
|
||||
|
||||
// Relative import paths
|
||||
// NOTE: Base path is whitelisted by default so we need the 'a/../../code/' part to get
|
||||
// outside of it. And it can't be just '../code/' because that would not be a direct import.
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/b/c.sol'", {"--allow-paths", "../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import 'a/../../code/X/b/c.sol'", {"--allow-paths", "../code/a/b"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/X/c.sol'", {"--allow-paths", "../code/a/b"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/b/X.sol'", {"--allow-paths", "../code/a/b"}));
|
||||
|
||||
// Non-normalized relative import paths
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/./b/c.sol'", {"--allow-paths", "../code/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a/../a/b/c.sol'", {"--allow-paths", "../code/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import 'a/../../code/a///b/c.sol'", {"--allow-paths", "../code/a/b/c.sol"}));
|
||||
|
||||
// UNC paths in imports
|
||||
string uncImportPath = "/" + m_portablePrefix + "/a/b/c.sol";
|
||||
soltestAssert(FileReader::isUNCPath(uncImportPath), "");
|
||||
BOOST_TEST(checkImport("import '" + uncImportPath + "'", {"--allow-paths", "../code/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_automatic_whitelisting_input_files, AllowPathsFixture)
|
||||
{
|
||||
// By default none of the files is whitelisted
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c/d.sol'", {}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Compiling a file whitelists its directory and subdirectories
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {m_codeDir.string() + "/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c/d.sol'", {m_codeDir.string() + "/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {m_codeDir.string() + "/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {m_codeDir.string() + "/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {m_codeDir.string() + "/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {m_codeDir.string() + "/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// If only file name is specified, its parent dir path is empty. This should be equivalent to
|
||||
// whitelisting the work dir.
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/contract.sol'", {"contract.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import 'contract.sol'", {"contract.sol"}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_automatic_whitelisting_remappings, AllowPathsFixture)
|
||||
{
|
||||
// Adding a remapping whitelists target's parent directory and subdirectories
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../code/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c/d.sol'", {"x=../code/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"x=../code/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"x=../code/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../code/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {"x=../code/a/b/c.sol"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=/contract.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=/contract.sol/"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {m_portablePrefix + "/a/b=../code/X/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {m_portablePrefix + "/a/b/=../code/X/b/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {m_portablePrefix + "/a/b=../code/X/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {m_portablePrefix + "/a/b/=../code/X/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {m_portablePrefix + "/a/b:y/z=x/w"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {m_portablePrefix + "/a/b:y/z=x/w"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Adding a remapping whitelists the target and subdirectories when the target is a directory
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../code/a/b/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c/d.sol'", {"x=../code/a/b/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"x=../code/a/b/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"x=../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {"x=../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {"x=../code/a/c/"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Adding a remapping whitelists target's parent directory and subdirectories when the target
|
||||
// is a directory but does not have a trailing slash
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c/d.sol'", {"x=../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/X.sol'", {"x=../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"x=../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../code/a/b"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {"x=../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/bc/d.sol'", {"x=../code/a/c"}));
|
||||
|
||||
// Adding a remapping to a relative target at VFS root whitelists the work dir
|
||||
BOOST_TEST(checkImport("import '/../../x/y/z.sol'", {"x=contract.sol", "--base-path=../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '/../../../work/a/b/c.sol'", {"x=contract.sol", "--base-path=../code/a/b/"}));
|
||||
|
||||
BOOST_TEST(checkImport("import '/../../x/y/z.sol'", {"x=contract.sol/", "--base-path=../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '/../../../work/a/b/c.sol'", {"x=contract.sol/", "--base-path=../code/a/b/"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Adding a remapping with an empty target does not whitelist anything
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {m_portablePrefix + "="}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"../code/="}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '/../work/a/b/c.sol'", {"../code/=", "--base-path", m_portablePrefix}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Adding a remapping that includes .. or . segments whitelists the parent dir and subdirectories
|
||||
// of the resolved target
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=."}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=."}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=./"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=./"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=.."}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=.."}));
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../"}));
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../code/a/b/./.."}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"x=../code/a/b/./.."}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../code/a/b/./.."}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../code/a/b/./../"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"x=../code/a/b/./../"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../code/a/b/./../"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../code/a/b/./../b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"x=../code/a/b/./../b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../code/a/b/./../b"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"x=../code/a/b/./../b/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/X/c.sol'", {"x=../code/a/b/./../b/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/X/b/c.sol'", {"x=../code/a/b/./../b/"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// If the target is just a file name, its parent dir path is empty. This should be equivalent to
|
||||
// whitelisting the work dir.
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/contract.sol'", {"x=contract.sol"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import 'contract.sol'", {"x=contract.sol"}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_automatic_whitelisting_base_path, AllowPathsFixture)
|
||||
{
|
||||
// Relative base path whitelists its content
|
||||
BOOST_TEST(checkImport("import 'b/c.sol'", {"--base-path=../code/a"}));
|
||||
BOOST_TEST(checkImport("import 'b/c/d.sol'", {"--base-path=../code/a"}));
|
||||
BOOST_TEST(checkImport("import 'b/X.sol'", {"--base-path=../code/a"}));
|
||||
BOOST_TEST(checkImport("import 'X/c.sol'", {"--base-path=../code/a"}));
|
||||
|
||||
BOOST_TEST(checkImport("import 'b/c.sol'", {"--base-path=../code/a/"}));
|
||||
BOOST_TEST(checkImport("import 'b/c/d.sol'", {"--base-path=../code/a/"}));
|
||||
BOOST_TEST(checkImport("import 'b/X.sol'", {"--base-path=../code/a/"}));
|
||||
BOOST_TEST(checkImport("import 'X/c.sol'", {"--base-path=../code/a/"}));
|
||||
|
||||
BOOST_TEST(checkImport("import 'a/b/c.sol'", {"--base-path=../code/."}));
|
||||
BOOST_TEST(checkImport("import 'a/b/c.sol'", {"--base-path=../code/./"}));
|
||||
BOOST_TEST(checkImport("import 'code/a/b/c.sol'", {"--base-path=.."}));
|
||||
BOOST_TEST(checkImport("import 'code/a/b/c.sol'", {"--base-path=../"}));
|
||||
|
||||
// Absolute base path whitelists its content
|
||||
BOOST_TEST(checkImport("import 'b/c.sol'", {"--base-path", m_codeDir.string() + "/a"}));
|
||||
BOOST_TEST(checkImport("import 'b/c/d.sol'", {"--base-path", m_codeDir.string() + "/a"}));
|
||||
BOOST_TEST(checkImport("import 'b/X.sol'", {"--base-path", m_codeDir.string() + "/a"}));
|
||||
BOOST_TEST(checkImport("import 'X/c.sol'", {"--base-path", m_codeDir.string() + "/a"}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_automatic_whitelisting_work_dir, AllowPathsFixture)
|
||||
{
|
||||
// Work dir is only automatically whitelisted if it matches base path
|
||||
BOOST_TEST(checkImport("import 'b/../../../work/a/b/c.sol'", {"--base-path=../code/a/"}) == ImportCheck::PathDisallowed());
|
||||
|
||||
// Compiling a file in the work dir whitelists it even if it's not in base path
|
||||
BOOST_TEST(checkImport("import 'b/../../../work/a/b/c.sol'", {"--base-path", "../code/a/", "a/b/c.sol"}));
|
||||
|
||||
// Work dir can also be whitelisted manually
|
||||
BOOST_TEST(checkImport("import 'b/../../../work/a/b/c.sol'", {"--base-path", "../code/a/", "--allow-paths=."}));
|
||||
|
||||
// Not setting base path whitelists the working directory
|
||||
BOOST_TEST(checkImport("import 'a/b/c.sol'", {}));
|
||||
BOOST_TEST(checkImport("import 'a/b/c/d.sol'", {}));
|
||||
BOOST_TEST(checkImport("import 'a/b/X.sol'", {}));
|
||||
BOOST_TEST(checkImport("import 'a/X/c.sol'", {}));
|
||||
|
||||
// Setting base path to an empty value whitelists the working directory
|
||||
BOOST_TEST(checkImport("import 'a/b/c.sol'", {"--base-path", ""}));
|
||||
BOOST_TEST(checkImport("import 'a/b/c/d.sol'", {"--base-path", ""}));
|
||||
BOOST_TEST(checkImport("import 'a/b/X.sol'", {"--base-path", ""}));
|
||||
BOOST_TEST(checkImport("import 'a/X/c.sol'", {"--base-path", ""}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_symlinks_within_whitelisted_dir, AllowPathsFixture)
|
||||
{
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b_sym/c.sol'", {"--allow-paths=../code/a/b/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths=../code/a/b_sym/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b_sym/c.sol'", {"--allow-paths=../code/a/b_sym/"}));
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b_sym/c.sol'", {"--allow-paths=../code/a/b"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths=../code/a/b_sym"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b_sym/c.sol'", {"--allow-paths=../code/a/b_sym"}));
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c_sym.sol'", {"--allow-paths=../code/a/b/c.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c.sol'", {"--allow-paths=../code/a/b/c_sym.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/c_sym.sol'", {"--allow-paths=../code/a/b/c_sym.sol"}));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(allow_path_symlinks_outside_whitelisted_dir, AllowPathsFixture)
|
||||
{
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/y_sym/z.sol'", {"--allow-paths=../code/a/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/y_sym/z.sol'", {"--allow-paths=../code/x/"}));
|
||||
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/z_sym.sol'", {"--allow-paths=../code/a/"}) == ImportCheck::PathDisallowed());
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/z_sym.sol'", {"--allow-paths=../code/x/"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/z_sym.sol'", {"--allow-paths=../code/a/b/z_sym.sol"}));
|
||||
BOOST_TEST(checkImport("import '" + m_portablePrefix + "/a/b/z_sym.sol'", {"--allow-paths=../code/x/y/z.sol"}));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace solidity::frontend::test
|
||||
@@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(cli_mode_options)
|
||||
|
||||
expectedOptions.input.addStdin = true;
|
||||
expectedOptions.input.basePath = "/home/user/";
|
||||
expectedOptions.input.allowedDirectories = {"/tmp", "/home", "project", "../contracts", "", "c", "/usr/lib"};
|
||||
expectedOptions.input.allowedDirectories = {"/tmp", "/home", "project", "../contracts", "c", "/usr/lib"};
|
||||
expectedOptions.input.ignoreMissingFiles = true;
|
||||
expectedOptions.input.errorRecovery = (inputMode == InputMode::Compiler);
|
||||
expectedOptions.output.dir = "/tmp/out";
|
||||
@@ -307,7 +307,7 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
|
||||
};
|
||||
expectedOptions.input.addStdin = true;
|
||||
expectedOptions.input.basePath = "/home/user/";
|
||||
expectedOptions.input.allowedDirectories = {"/tmp", "/home", "project", "../contracts", "", "c", "/usr/lib"};
|
||||
expectedOptions.input.allowedDirectories = {"/tmp", "/home", "project", "../contracts", "c", "/usr/lib"};
|
||||
expectedOptions.input.ignoreMissingFiles = true;
|
||||
expectedOptions.output.overwriteFiles = true;
|
||||
expectedOptions.output.evmVersion = EVMVersion::spuriousDragon();
|
||||
|
||||
+18
-1
@@ -54,5 +54,22 @@ test::OptionsReaderAndMessages test::parseCommandLineAndReadInputFiles(
|
||||
if (success && _processInput)
|
||||
success = cli.processInput();
|
||||
|
||||
return {success, cli.options(), cli.fileReader(), cli.standardJsonInput(), sout.str(), serr.str()};
|
||||
return {
|
||||
success,
|
||||
cli.options(),
|
||||
cli.fileReader(),
|
||||
cli.standardJsonInput(),
|
||||
sout.str(),
|
||||
stripPreReleaseWarning(serr.str()),
|
||||
};
|
||||
}
|
||||
|
||||
string test::stripPreReleaseWarning(string const& _stderrContent)
|
||||
{
|
||||
static regex const preReleaseWarningRegex{
|
||||
R"(Warning( \(3805\))?: This is a pre-release compiler version, please do not use it in production\.\n)"
|
||||
R"((\n)?)"
|
||||
};
|
||||
|
||||
return regex_replace(_stderrContent, preReleaseWarningRegex, "");
|
||||
}
|
||||
|
||||
@@ -50,4 +50,6 @@ OptionsReaderAndMessages parseCommandLineAndReadInputFiles(
|
||||
bool _processInput = false
|
||||
);
|
||||
|
||||
std::string stripPreReleaseWarning(std::string const& _stderrContent);
|
||||
|
||||
} // namespace solidity::frontend::test
|
||||
|
||||
Reference in New Issue
Block a user