Treat ambiguous imports as errors

This commit is contained in:
Kamil Śliwak
2021-09-27 13:14:23 +02:00
parent 9975b5e26b
commit f909555022
4 changed files with 82 additions and 10 deletions
+24 -9
View File
@@ -21,8 +21,10 @@
#include <libsolutil/CommonIO.h>
#include <libsolutil/Exceptions.h>
#include <libsolutil/StringUtils.h>
#include <boost/algorithm/string/predicate.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/range/conversion.hpp>
@@ -32,6 +34,7 @@ using solidity::frontend::ReadCallback;
using solidity::langutil::InternalCompilerError;
using solidity::util::errinfo_comment;
using solidity::util::readFileAsString;
using solidity::util::joinHumanReadable;
using std::map;
using std::reference_wrapper;
using std::string;
@@ -109,24 +112,38 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
if (strippedSourceUnitName.find("file://") == 0)
strippedSourceUnitName.erase(0, 7);
vector<boost::filesystem::path> candidates;
vector<reference_wrapper<boost::filesystem::path>> prefixes = {m_basePath};
prefixes += (m_includePaths | ranges::to<vector<reference_wrapper<boost::filesystem::path>>>);
boost::filesystem::path canonicalPath;
for (auto const& prefix: prefixes)
{
canonicalPath = normalizeCLIPathForVFS(prefix / strippedSourceUnitName, SymlinkResolution::Enabled);
boost::filesystem::path canonicalPath = normalizeCLIPathForVFS(prefix / strippedSourceUnitName, SymlinkResolution::Enabled);
if (boost::filesystem::exists(canonicalPath))
break;
candidates.push_back(std::move(canonicalPath));
}
auto pathToQuotedString = [](boost::filesystem::path const& _path){ return "\"" + _path.string() + "\""; };
if (candidates.empty())
return ReadCallback::Result{false, "File not found."};
if (candidates.size() >= 2)
return ReadCallback::Result{
false,
"Ambiguous import. "
"Multiple matching files found inside base path and/or include paths: " +
joinHumanReadable(candidates | ranges::views::transform(pathToQuotedString), ", ") +
"."
};
FileSystemPathSet extraAllowedPaths = {m_basePath.empty() ? "." : m_basePath};
extraAllowedPaths += m_includePaths;
bool isAllowed = false;
for (boost::filesystem::path const& allowedDir: m_allowedDirectories + extraAllowedPaths)
if (isPathPrefix(normalizeCLIPathForVFS(allowedDir, SymlinkResolution::Enabled), canonicalPath))
if (isPathPrefix(normalizeCLIPathForVFS(allowedDir, SymlinkResolution::Enabled), candidates[0]))
{
isAllowed = true;
break;
@@ -135,14 +152,12 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _so
if (!isAllowed)
return ReadCallback::Result{false, "File outside of allowed directories."};
if (!boost::filesystem::exists(canonicalPath))
return ReadCallback::Result{false, "File not found."};
if (!boost::filesystem::is_regular_file(canonicalPath))
if (!boost::filesystem::is_regular_file(candidates[0]))
return ReadCallback::Result{false, "Not a valid file."};
// NOTE: we ignore the FileNotFound exception as we manually check above
auto contents = readFileAsString(canonicalPath);
auto contents = readFileAsString(candidates[0]);
solAssert(m_sourceCodes.count(_sourceUnitName) == 0, "");
m_sourceCodes[_sourceUnitName] = contents;
return ReadCallback::Result{true, contents};
}