aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-08-13 19:37:04 +0800
committerGitHub <noreply@github.com>2018-08-13 19:37:04 +0800
commita2c754b3fed422b3d8027a5298624bcfed3744a5 (patch)
tree9306c07b3445117a318f14dcde5efd1bd7dcaf9d
parent43db88b8363d73ee2f5ffa094ff506414261bd11 (diff)
parenta7885e0b0a8808e9daa7cc3b86781997c614b8d3 (diff)
downloaddexon-solidity-a2c754b3fed422b3d8027a5298624bcfed3744a5.tar
dexon-solidity-a2c754b3fed422b3d8027a5298624bcfed3744a5.tar.gz
dexon-solidity-a2c754b3fed422b3d8027a5298624bcfed3744a5.tar.bz2
dexon-solidity-a2c754b3fed422b3d8027a5298624bcfed3744a5.tar.lz
dexon-solidity-a2c754b3fed422b3d8027a5298624bcfed3744a5.tar.xz
dexon-solidity-a2c754b3fed422b3d8027a5298624bcfed3744a5.tar.zst
dexon-solidity-a2c754b3fed422b3d8027a5298624bcfed3744a5.zip
Merge pull request #4793 from ethereum/emptyRemappings
Disallow remappings with empty prefix.
-rw-r--r--Changelog.md1
-rw-r--r--docs/layout-of-source-files.rst11
-rw-r--r--docs/using-the-compiler.rst11
-rw-r--r--libsolidity/interface/CompilerStack.cpp37
-rw-r--r--libsolidity/interface/CompilerStack.h21
-rw-r--r--libsolidity/interface/StandardCompiler.cpp9
-rw-r--r--solc/CommandLineInterface.cpp15
-rw-r--r--solc/CommandLineInterface.h2
-rwxr-xr-xtest/cmdlineTests.sh4
-rw-r--r--test/libsolidity/Imports.cpp14
10 files changed, 82 insertions, 43 deletions
diff --git a/Changelog.md b/Changelog.md
index b2f9bf05..56e00003 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -16,6 +16,7 @@ Breaking Changes:
* Commandline interface: Remove obsolete ``--formal`` option.
* Commandline interface: Rename the ``--julia`` option to ``--yul``.
* Commandline interface: Require ``-`` if standard input is used as source.
+ * Compiler interface: Disallow remappings with empty prefix.
* Control Flow Analyzer: Turn warning about returning uninitialized storage pointers into an error.
* General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code.
* General: Disallow declaring empty structs.
diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst
index 46ef3d57..4bacd704 100644
--- a/docs/layout-of-source-files.rst
+++ b/docs/layout-of-source-files.rst
@@ -100,11 +100,10 @@ When the compiler is invoked, it is not only possible to specify how to
discover the first element of a path, but it is possible to specify path prefix
remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to
``/usr/local/dapp-bin/library`` and the compiler will read the files from there.
-If multiple remappings can be applied, the one with the longest key is tried first. This
-allows for a "fallback-remapping" with e.g. ``""`` maps to
-``"/usr/local/include/solidity"``. Furthermore, these remappings can
-depend on the context, which allows you to configure packages to
-import e.g. different versions of a library of the same name.
+If multiple remappings can be applied, the one with the longest key is tried first.
+An empty prefix is not allowed. Furthermore, these remappings can depend on the context,
+which allows you to configure packages to import e.g. different versions of a library
+of the same name.
**solc**:
@@ -148,7 +147,7 @@ Note that solc only allows you to include files from certain directories:
They have to be in the directory (or subdirectory) of one of the explicitly
specified source files or in the directory (or subdirectory) of a remapping
target. If you want to allow direct absolute includes, just add the
-remapping ``=/``.
+remapping ``/=/``.
If there are multiple remappings that lead to a valid file, the remapping
with the longest common prefix is chosen.
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index 1d7cb97b..b286e1a3 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -23,14 +23,15 @@ it is also possible to provide path redirects using ``prefix=path`` in the follo
::
- solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol
+ solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ file.sol
This essentially instructs the compiler to search for anything starting with
-``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin`` and if it does not
-find the file there, it will look at ``/usr/local/lib/fallback`` (the empty prefix
-always matches). ``solc`` will not read files from the filesystem that lie outside of
+``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin``.
+``solc`` will not read files from the filesystem that lie outside of
the remapping targets and outside of the directories where explicitly specified source
-files reside, so things like ``import "/etc/passwd";`` only work if you add ``=/`` as a remapping.
+files reside, so things like ``import "/etc/passwd";`` only work if you add ``/=/`` as a remapping.
+
+An empty remapping prefix is not allowed.
If there are multiple matches due to remappings, the one with the longest common prefix is selected.
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 836e30d2..e800b278 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -58,22 +58,31 @@ using namespace std;
using namespace dev;
using namespace dev::solidity;
-void CompilerStack::setRemappings(vector<string> const& _remappings)
+boost::optional<CompilerStack::Remapping> CompilerStack::parseRemapping(string const& _remapping)
+{
+ auto eq = find(_remapping.begin(), _remapping.end(), '=');
+ if (eq == _remapping.end())
+ return {};
+
+ auto colon = find(_remapping.begin(), eq, ':');
+
+ Remapping r;
+
+ r.context = colon == eq ? string() : string(_remapping.begin(), colon);
+ r.prefix = colon == eq ? string(_remapping.begin(), eq) : string(colon + 1, eq);
+ r.target = string(eq + 1, _remapping.end());
+
+ if (r.prefix.empty())
+ return {};
+
+ return r;
+}
+
+void CompilerStack::setRemappings(vector<Remapping> const& _remappings)
{
- vector<Remapping> remappings;
for (auto const& remapping: _remappings)
- {
- auto eq = find(remapping.begin(), remapping.end(), '=');
- if (eq == remapping.end())
- continue; // ignore
- auto colon = find(remapping.begin(), eq, ':');
- Remapping r;
- r.context = colon == eq ? string() : string(remapping.begin(), colon);
- r.prefix = colon == eq ? string(remapping.begin(), eq) : string(colon + 1, eq);
- r.target = string(eq + 1, remapping.end());
- remappings.push_back(r);
- }
- swap(m_remappings, remappings);
+ solAssert(!remapping.prefix.empty(), "");
+ m_remappings = _remappings;
}
void CompilerStack::setEVMVersion(EVMVersion _version)
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 2234a8c9..9a15fbf0 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -84,6 +84,13 @@ public:
CompilationSuccessful
};
+ struct Remapping
+ {
+ std::string context;
+ std::string prefix;
+ std::string target;
+ };
+
/// Creates a new compiler stack.
/// @param _readFile callback to used to read files for import statements. Must return
/// and must not emit exceptions.
@@ -103,8 +110,11 @@ public:
/// All settings, with the exception of remappings, are reset.
void reset(bool _keepSources = false);
- /// Sets path remappings in the format "context:prefix=target"
- void setRemappings(std::vector<std::string> const& _remappings);
+ // Parses a remapping of the format "context:prefix=target".
+ static boost::optional<Remapping> parseRemapping(std::string const& _remapping);
+
+ /// Sets path remappings.
+ void setRemappings(std::vector<Remapping> const& _remappings);
/// Sets library addresses. Addresses are cleared iff @a _libraries is missing.
/// Will not take effect before running compile.
@@ -319,13 +329,6 @@ private:
FunctionDefinition const& _function
) const;
- struct Remapping
- {
- std::string context;
- std::string prefix;
- std::string target;
- };
-
ReadCallback::Callback m_readFile;
ReadCallback::Callback m_smtQuery;
bool m_optimize = false;
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 58b84163..c1996777 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -326,9 +326,14 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
m_compilerStack.setEVMVersion(*version);
}
- vector<string> remappings;
+ vector<CompilerStack::Remapping> remappings;
for (auto const& remapping: settings.get("remappings", Json::Value()))
- remappings.push_back(remapping.asString());
+ {
+ if (auto r = CompilerStack::parseRemapping(remapping.asString()))
+ remappings.emplace_back(std::move(*r));
+ else
+ return formatFatalError("JSONError", "Invalid remapping: \"" + remapping.asString() + "\"");
+ }
m_compilerStack.setRemappings(remappings);
Json::Value optimizerSettings = settings.get("optimizer", Json::Value());
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 429bd637..f7d1c748 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -392,7 +392,18 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings()
{
auto eq = find(path.begin(), path.end(), '=');
if (eq != path.end())
- path = string(eq + 1, path.end());
+ {
+ if (auto r = CompilerStack::parseRemapping(path))
+ {
+ m_remappings.emplace_back(std::move(*r));
+ path = string(eq + 1, path.end());
+ }
+ else
+ {
+ cerr << "Invalid remapping: \"" << path << "\"." << endl;
+ return false;
+ }
+ }
else if (path == "-")
addStdin = true;
else
@@ -808,7 +819,7 @@ bool CommandLineInterface::processInput()
if (m_args.count(g_argMetadataLiteral) > 0)
m_compiler->useMetadataLiteralSources(true);
if (m_args.count(g_argInputFile))
- m_compiler->setRemappings(m_args[g_argInputFile].as<vector<string>>());
+ m_compiler->setRemappings(m_remappings);
for (auto const& sourceCode: m_sourceCodes)
m_compiler->addSource(sourceCode.first, sourceCode.second);
if (m_args.count(g_argLibraries))
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index 45ec1eb5..010dce34 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -97,6 +97,8 @@ private:
boost::program_options::variables_map m_args;
/// map of input files to source code strings
std::map<std::string, std::string> m_sourceCodes;
+ /// list of remappings
+ std::vector<dev::solidity::CompilerStack::Remapping> m_remappings;
/// list of allowed directories to read files from
std::vector<boost::filesystem::path> m_allowedDirectories;
/// map of library names to addresses
diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh
index 7256386d..a260da34 100755
--- a/test/cmdlineTests.sh
+++ b/test/cmdlineTests.sh
@@ -144,6 +144,10 @@ test_solc_file_input_failures "file_not_found.sol" "" "" "\"file_not_found.sol\"
printTask "Testing passing files that are not files..."
test_solc_file_input_failures "." "" "" "\".\" is not a valid file."
+printTask "Testing passing empty remappings..."
+test_solc_file_input_failures "${0}" "=/some/remapping/target" "" "Invalid remapping: \"=/some/remapping/target\"."
+test_solc_file_input_failures "${0}" "ctx:=/some/remapping/target" "" "Invalid remapping: \"ctx:=/some/remapping/target\"."
+
printTask "Compiling various other contracts and libraries..."
(
cd "$REPO_ROOT"/test/compilationTests/
diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp
index df31ac40..dc33d577 100644
--- a/test/libsolidity/Imports.cpp
+++ b/test/libsolidity/Imports.cpp
@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(name_clash_in_import)
BOOST_AUTO_TEST_CASE(remappings)
{
CompilerStack c;
- c.setRemappings(vector<string>{"s=s_1.4.6", "t=Tee"});
+ c.setRemappings(vector<CompilerStack::Remapping>{{"", "s", "s_1.4.6"},{"", "t", "Tee"}});
c.addSource("a", "import \"s/s.sol\"; contract A is S {} pragma solidity >=0.0;");
c.addSource("b", "import \"t/tee.sol\"; contract A is Tee {} pragma solidity >=0.0;");
c.addSource("s_1.4.6/s.sol", "contract S {} pragma solidity >=0.0;");
@@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(remappings)
BOOST_AUTO_TEST_CASE(context_dependent_remappings)
{
CompilerStack c;
- c.setRemappings(vector<string>{"a:s=s_1.4.6", "b:s=s_1.4.7"});
+ c.setRemappings(vector<CompilerStack::Remapping>{{"a", "s", "s_1.4.6"}, {"b", "s", "s_1.4.7"}});
c.addSource("a/a.sol", "import \"s/s.sol\"; contract A is SSix {} pragma solidity >=0.0;");
c.addSource("b/b.sol", "import \"s/s.sol\"; contract B is SSeven {} pragma solidity >=0.0;");
c.addSource("s_1.4.6/s.sol", "contract SSix {} pragma solidity >=0.0;");
@@ -200,7 +200,11 @@ BOOST_AUTO_TEST_CASE(filename_with_period)
BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_preserved)
{
CompilerStack c;
- c.setRemappings(vector<string>{"foo=vendor/foo_2.0.0", "vendor/bar:foo=vendor/foo_1.0.0", "bar=vendor/bar"});
+ c.setRemappings(vector<CompilerStack::Remapping>{
+ {"", "foo", "vendor/foo_2.0.0"},
+ {"vendor/bar", "foo", "vendor/foo_1.0.0"},
+ {"", "bar", "vendor/bar"}
+ });
c.addSource("main.sol", "import \"foo/foo.sol\"; import {Bar} from \"bar/bar.sol\"; contract Main is Foo2, Bar {} pragma solidity >=0.0;");
c.addSource("vendor/bar/bar.sol", "import \"foo/foo.sol\"; contract Bar {Foo1 foo;} pragma solidity >=0.0;");
c.addSource("vendor/foo_1.0.0/foo.sol", "contract Foo1 {} pragma solidity >=0.0;");
@@ -212,7 +216,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_pres
BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent)
{
CompilerStack c;
- c.setRemappings(vector<string>{"a:x/y/z=d", "a/b:x=e"});
+ c.setRemappings(vector<CompilerStack::Remapping>{{"a", "x/y/z", "d"}, {"a/b", "x", "e"}});
c.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;");
c.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;");
c.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;");
@@ -220,7 +224,7 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent)
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
CompilerStack d;
- d.setRemappings(vector<string>{"a/b:x=e", "a:x/y/z=d"});
+ d.setRemappings(vector<CompilerStack::Remapping>{{"a/b", "x", "e"}, {"a", "x/y/z", "d"}});
d.addSource("a/main.sol", "import \"x/y/z/z.sol\"; contract Main is D {} pragma solidity >=0.0;");
d.addSource("a/b/main.sol", "import \"x/y/z/z.sol\"; contract Main is E {} pragma solidity >=0.0;");
d.addSource("d/z.sol", "contract D {} pragma solidity >=0.0;");