Merge pull request #11234 from ethereum/fix-file-reader-compiler-stack-source-unit-name-mismatch

Use identical source unit names in FileReader and CompilerStack
This commit is contained in:
Christian Parpart 2021-04-14 13:46:14 +02:00 committed by GitHub
commit 81c7b30a6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 128 additions and 11 deletions

View File

@ -31,6 +31,7 @@ Bugfixes:
* SMTChecker: Fix internal error on public getter returning dynamic data on older EVM versions where these are not available.
* SMTChecker: Fix internal error on try-catch with function call in catch block.
* Type Checker: Fix missing error when events are used without an emit statement.
* Commandline interface: Fix internal error when printing AST and using ``--base-path`` or ``file://`` prefix in imports.
AST Changes:

View File

@ -42,7 +42,7 @@ void FileReader::setSources(StringMap _sources)
m_sourceCodes = std::move(_sources);
}
ReadCallback::Result FileReader::readFile(string const& _kind, string const& _path)
ReadCallback::Result FileReader::readFile(string const& _kind, string const& _sourceUnitName)
{
try
{
@ -51,12 +51,11 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _pa
"ReadFile callback used as callback kind " +
_kind
));
string validPath = _path;
if (validPath.find("file://") == 0)
validPath.erase(0, 7);
string strippedSourceUnitName = _sourceUnitName;
if (strippedSourceUnitName.find("file://") == 0)
strippedSourceUnitName.erase(0, 7);
auto const path = m_basePath / validPath;
auto canonicalPath = boost::filesystem::weakly_canonical(path);
auto canonicalPath = boost::filesystem::weakly_canonical(m_basePath / strippedSourceUnitName);
bool isAllowed = false;
for (auto const& allowedDir: m_allowedDirectories)
{
@ -81,7 +80,7 @@ ReadCallback::Result FileReader::readFile(string const& _kind, string const& _pa
// NOTE: we ignore the FileNotFound exception as we manually check above
auto contents = readFileAsString(canonicalPath.string());
m_sourceCodes[path.generic_string()] = contents;
m_sourceCodes[_sourceUnitName] = contents;
return ReadCallback::Result{true, contents};
}
catch (util::Exception const& _exception)

View File

@ -62,14 +62,21 @@ public:
SourceCode const& sourceCode(SourceUnitName const& _sourceUnitName) const { return m_sourceCodes.at(_sourceUnitName); }
/// Resets all sources to the given map of source unit ID to source codes.
/// Does not enforce @a allowedDirectories().
void setSources(StringMap _sources);
/// Adds the source code for a given source unit ID.
/// Does not enforce @a allowedDirectories().
void setSource(boost::filesystem::path const& _path, SourceCode _source);
/// Reads a given file at @p _path of kind @p _kind from the local filesystem and returns the result.
/// @p _kind must always be passed as "source".
frontend::ReadCallback::Result readFile(std::string const& _kind, std::string const& _path);
/// Receives a @p _sourceUnitName that refers to a source unit in compiler's virtual filesystem
/// and attempts to interpret it as a path and read the corresponding file from disk.
/// The read will only succeed if the canonical path of the file is within one of the @a allowedDirectories().
/// @param _kind must be equal to "source". Other values are not supported.
/// @return Content of the loaded file or an error message. If the operation succeeds, a copy of
/// the content is retained in @a sourceCodes() under the key of @a _sourceUnitName. If the key
/// already exists, previous content is discarded.
frontend::ReadCallback::Result readFile(std::string const& _kind, std::string const& _sourceUnitName);
frontend::ReadCallback::Callback reader()
{

View File

@ -162,7 +162,7 @@ function test_solc_behaviour()
sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1<AUXDATA REMOVED>/' "$stdout_path"
sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path"
sed -i.bak -e 's/\(Unimplemented feature error.* in \).*$/\1<FILENAME REMOVED>/' "$stderr_path"
sed -i.bak -e 's/"version": "[^"]*"/"version": "<VERSION REMOVED>"/' "$stdout_path"
sed -i.bak -e 's/"version":[ ]*"[^"]*"/"version": "<VERSION REMOVED>"/' "$stdout_path"
# Remove bytecode (but not linker references). Since non-JSON output is unstructured,
# use metadata markers for detection to have some confidence that it's actually bytecode

View File

@ -0,0 +1 @@
--ast-compact-json --base-path . --allow-paths .

View File

@ -0,0 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract C {}

View File

@ -0,0 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
import "./c.sol";

View File

@ -0,0 +1,91 @@
JSON AST (compact format):
======= ast_compact_json_with_base_path/c.sol =======
{
"absolutePath": "ast_compact_json_with_base_path/c.sol",
"exportedSymbols":
{
"C":
[
5
]
},
"id": 6,
"license": "GPL-3.0",
"nodeType": "SourceUnit",
"nodes":
[
{
"id": 4,
"literals":
[
"solidity",
">=",
"0.0"
],
"nodeType": "PragmaDirective",
"src": "36:22:0"
},
{
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"fullyImplemented": true,
"id": 5,
"linearizedBaseContracts":
[
5
],
"name": "C",
"nameLocation": "69:1:0",
"nodeType": "ContractDefinition",
"nodes": [],
"scope": 6,
"src": "60:13:0"
}
],
"src": "36:38:0"
}
======= ast_compact_json_with_base_path/input.sol =======
{
"absolutePath": "ast_compact_json_with_base_path/input.sol",
"exportedSymbols":
{
"C":
[
5
]
},
"id": 3,
"license": "GPL-3.0",
"nodeType": "SourceUnit",
"nodes":
[
{
"id": 1,
"literals":
[
"solidity",
">=",
"0.0"
],
"nodeType": "PragmaDirective",
"src": "36:22:1"
},
{
"absolutePath": "ast_compact_json_with_base_path/c.sol",
"file": "./c.sol",
"id": 2,
"nameLocation": "-1:-1:-1",
"nodeType": "ImportDirective",
"scope": 3,
"sourceUnit": 6,
"src": "60:17:1",
"symbolAliases": [],
"unitAlias": ""
}
],
"src": "36:42:1"
}

View File

@ -0,0 +1 @@
--combined-json ast --base-path . --allow-paths .

View File

@ -0,0 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
contract C {}

View File

@ -0,0 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.0;
import "./c.sol";

View File

@ -0,0 +1 @@
{"contracts":{"combined_json_with_base_path/c.sol:C":{}},"sourceList":["combined_json_with_base_path/c.sol","combined_json_with_base_path/input.sol"],"sources":{"combined_json_with_base_path/c.sol":{"AST":{"absolutePath":"combined_json_with_base_path/c.sol","exportedSymbols":{"C":[5]},"id":6,"license":"GPL-3.0","nodeType":"SourceUnit","nodes":[{"id":4,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"36:22:0"},{"abstract":false,"baseContracts":[],"contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"id":5,"linearizedBaseContracts":[5],"name":"C","nameLocation":"69:1:0","nodeType":"ContractDefinition","nodes":[],"scope":6,"src":"60:13:0"}],"src":"36:38:0"}},"combined_json_with_base_path/input.sol":{"AST":{"absolutePath":"combined_json_with_base_path/input.sol","exportedSymbols":{"C":[5]},"id":3,"license":"GPL-3.0","nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"36:22:1"},{"absolutePath":"combined_json_with_base_path/c.sol","file":"./c.sol","id":2,"nameLocation":"-1:-1:-1","nodeType":"ImportDirective","scope":3,"sourceUnit":6,"src":"60:17:1","symbolAliases":[],"unitAlias":""}],"src":"36:42:1"}}},"version": "<VERSION REMOVED>"}