Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce --no-import-callback CLI option #14610

Merged
merged 1 commit into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Language Features:


Compiler Features:
* Commandline Interface: Add ``--no-import-callback`` option that prevents the compiler from loading source files not given explicitly on the CLI or in Standard JSON input.
* Commandline Interface: Use proper severity and coloring also for error messages produced outside of the compilation pipeline.
* Parser: Remove the experimental error recovery mode (``--error-recovery`` / ``settings.parserErrorRecovery``).
* Yul Optimizer: If ``PUSH0`` is supported, favor zero literals over storing zero values in variables.
Expand Down
5 changes: 3 additions & 2 deletions docs/path-resolution.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ source unit is assigned a unique *source unit name* which is an opaque and unstr
When you use the :ref:`import statement <import>`, you specify an *import path* that references a
source unit name.

.. index:: ! import callback, ! Host Filesystem Loader
.. index:: ! import callback, ! Host Filesystem Loader, ! --no-import-callback
.. _import-callback:

Import Callback
Expand All @@ -36,8 +36,9 @@ An import callback is free to interpret source unit names in an arbitrary way, n
If there is no callback available when one is needed or if it fails to locate the source code,
compilation fails.

The command-line compiler provides the *Host Filesystem Loader* - a rudimentary callback
By default, the command-line compiler provides the *Host Filesystem Loader* - a rudimentary callback
that interprets a source unit name as a path in the local filesystem.
This callback can be disabled using the ``--no-import-callback`` command-line option.
The `JavaScript interface <https://github.com/ethereum/solc-js>`_ does not provide any by default,
but one can be provided by the user.
This mechanism can be used to obtain source code from locations other then the local filesystem
Expand Down
11 changes: 8 additions & 3 deletions libsolidity/interface/UniversalCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace solidity::frontend
class UniversalCallback
{
public:
UniversalCallback(FileReader& _fileReader, SMTSolverCommand& _solver) :
UniversalCallback(FileReader* _fileReader, SMTSolverCommand& _solver) :
m_fileReader{_fileReader},
m_solver{_solver}
{}
Expand All @@ -38,15 +38,20 @@ class UniversalCallback
{
return [this](std::string const& _kind, std::string const& _data) -> ReadCallback::Result {
if (_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile))
return m_fileReader.readFile(_kind, _data);
if (!m_fileReader)
return ReadCallback::Result{false, "No import callback."};
else
return m_fileReader->readFile(_kind, _data);
else if (_kind == ReadCallback::kindString(ReadCallback::Kind::SMTQuery))
return m_solver.solve(_kind, _data);
solAssert(false, "Unknown callback kind.");
};
}

void resetImportCallback() { m_fileReader = nullptr; }

private:
FileReader& m_fileReader;
FileReader* m_fileReader;
SMTSolverCommand& m_solver;
};

Expand Down
3 changes: 3 additions & 0 deletions solc/CommandLineInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,9 @@ void CommandLineInterface::readInputFiles()
{
solAssert(!m_standardJsonInput.has_value());

if (m_options.input.noImportCallback)
m_universalCallback.resetImportCallback();
r0qs marked this conversation as resolved.
Show resolved Hide resolved

static std::set<frontend::InputMode> const noInputFiles{
frontend::InputMode::Help,
frontend::InputMode::License,
Expand Down
2 changes: 1 addition & 1 deletion solc/CommandLineInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class CommandLineInterface
bool m_hasOutput = false;
FileReader m_fileReader;
SMTSolverCommand m_solverCommand{"eld"};
UniversalCallback m_universalCallback{m_fileReader, m_solverCommand};
UniversalCallback m_universalCallback{&m_fileReader, m_solverCommand};
std::optional<std::string> m_standardJsonInput;
std::unique_ptr<frontend::CompilerStack> m_compiler;
CommandLineOptions m_options;
Expand Down
12 changes: 12 additions & 0 deletions solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ static std::string const g_strModelCheckerTimeout = "model-checker-timeout";
static std::string const g_strModelCheckerBMCLoopIterations = "model-checker-bmc-loop-iterations";
static std::string const g_strNone = "none";
static std::string const g_strNoOptimizeYul = "no-optimize-yul";
static std::string const g_strNoImportCallback = "no-import-callback";
static std::string const g_strOptimize = "optimize";
static std::string const g_strOptimizeRuns = "optimize-runs";
static std::string const g_strOptimizeYul = "optimize-yul";
Expand Down Expand Up @@ -224,6 +225,7 @@ bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noex
input.includePaths == _other.input.includePaths &&
input.allowedDirectories == _other.input.allowedDirectories &&
input.ignoreMissingFiles == _other.input.ignoreMissingFiles &&
input.noImportCallback == _other.input.noImportCallback &&
output.dir == _other.output.dir &&
output.overwriteFiles == _other.output.overwriteFiles &&
output.evmVersion == _other.output.evmVersion &&
Expand Down Expand Up @@ -567,6 +569,11 @@ General Information)").c_str(),
g_strIgnoreMissingFiles.c_str(),
"Ignore missing files."
)
(
g_strNoImportCallback.c_str(),
"Disable the default import callback to prevent the compiler from loading any source "
"files not listed on the command line or given in the Standard JSON input."
)
;
desc.add(inputOptions);

Expand Down Expand Up @@ -1104,6 +1111,11 @@ void CommandLineParser::processArgs()
}
}

checkMutuallyExclusive({g_strNoImportCallback, g_strAllowPaths});

if (m_args.count(g_strNoImportCallback))
m_options.input.noImportCallback = true;

if (m_args.count(g_strAllowPaths))
{
std::vector<std::string> paths;
Expand Down
1 change: 1 addition & 0 deletions solc/CommandLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ struct CommandLineOptions
std::vector<boost::filesystem::path> includePaths;
FileReader::FileSystemPathSet allowedDirectories;
bool ignoreMissingFiles = false;
bool noImportCallback = false;
} input;

struct
Expand Down
1 change: 1 addition & 0 deletions test/cmdlineTests/no_import_callback/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--no-import-callback no_import_callback/contract_1.sol
4 changes: 4 additions & 0 deletions test/cmdlineTests/no_import_callback/contract_1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;

import "contract_2.sol";
Empty file.
5 changes: 5 additions & 0 deletions test/cmdlineTests/no_import_callback/err
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Error: Source "contract_2.sol" not found: No import callback.
--> no_import_callback/contract_1.sol:4:1:
|
4 | import "contract_2.sol";
| ^^^^^^^^^^^^^^^^^^^^^^^^
1 change: 1 addition & 0 deletions test/cmdlineTests/no_import_callback/exit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
2 changes: 2 additions & 0 deletions test/cmdlineTests/standard_no_import_callback/B.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
1 change: 1 addition & 0 deletions test/cmdlineTests/standard_no_import_callback/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--no-import-callback
8 changes: 8 additions & 0 deletions test/cmdlineTests/standard_no_import_callback/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"language": "Solidity",
"sources": {
"A": {
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0; import 'standard_no_import_callback/B.sol';"
}
}
}
26 changes: 26 additions & 0 deletions test/cmdlineTests/standard_no_import_callback/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"errors":
[
{
"component": "general",
"errorCode": "6275",
"formattedMessage": "ParserError: Source \"standard_no_import_callback/B.sol\" not found: No import callback.
--> A:2:24:
|
2 | pragma solidity >=0.0; import 'standard_no_import_callback/B.sol';
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

",
"message": "Source \"standard_no_import_callback/B.sol\" not found: No import callback.",
"severity": "error",
"sourceLocation":
{
"end": 102,
"file": "A",
"start": 59
},
"type": "ParserError"
}
],
"sources": {}
}
19 changes: 19 additions & 0 deletions test/solc/CommandLineInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,25 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes)
);
}

BOOST_AUTO_TEST_CASE(no_import_callback_allowed_paths)
{
array<string, 2> options = {
"--no-import-callback",
"--allow-paths"
};

string expectedMessage =
"The following options are mutually exclusive: "
"--no-import-callback, --allow-paths. "
"Select at most one.";

BOOST_CHECK_EXCEPTION(
parseCommandLineAndReadInputFiles({"solc", options[0], options[1], "."}),
CommandLineValidationError,
[&](auto const& _exception) { BOOST_TEST(_exception.what() == expectedMessage); return true; }
);
}

BOOST_AUTO_TEST_CASE(cli_input)
{
TemporaryDirectory tempDir1(TEST_CASE_NAME);
Expand Down
19 changes: 19 additions & 0 deletions test/solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,25 @@ BOOST_AUTO_TEST_CASE(no_cbor_metadata)
BOOST_TEST(assert);
}

BOOST_AUTO_TEST_CASE(no_import_callback)
{
std::vector<std::vector<std::string>> commandLinePerInputMode = {
{"solc", "--no-import-callback", "contract.sol"},
{"solc", "--standard-json", "--no-import-callback", "input.json"},
{"solc", "--assemble", "--no-import-callback", "input.yul"},
{"solc", "--strict-assembly", "--no-import-callback", "input.yul"},
{"solc", "--import-ast", "--no-import-callback", "ast.json"},
{"solc", "--link", "--no-import-callback", "input.bin"},
{"solc", "--yul", "--no-import-callback", "input.yul"},
};

for (auto const& commandLine: commandLinePerInputMode)
{
CommandLineOptions parsedOptions = parseCommandLine(commandLine);
BOOST_TEST(parsedOptions.input.noImportCallback);
}
}

BOOST_AUTO_TEST_CASE(via_ir_options)
{
BOOST_TEST(!parseCommandLine({"solc", "contract.sol"}).output.viaIR);
Expand Down