mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Disallow unknown JSON keys in standard-json
This commit is contained in:
parent
1c8c873465
commit
8cd2ac8462
@ -8,6 +8,7 @@ Compiler Features:
|
||||
* Inline Assembly: Improve error messages around invalid function argument count.
|
||||
* Code Generator: Use codecopy for string constants more aggressively.
|
||||
* Code Generator: Use binary search for dispatch function if more efficient. The size/speed tradeoff can be tuned using ``--optimize-runs``.
|
||||
* Compiler Interface: Disallow unknown keys in standard JSON input.
|
||||
* SMTChecker: Support mathematical and cryptographic functions in an uninterpreted way.
|
||||
* Static Analyzer: Do not warn about unused variables or state mutability for functions with an empty body.
|
||||
* Type Checker: Add an additional reason to be displayed when type conversion fails.
|
||||
|
@ -27,7 +27,10 @@
|
||||
#include <libdevcore/JSON.h>
|
||||
#include <libdevcore/Keccak256.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
@ -225,6 +228,50 @@ Json::Value collectEVMObject(eth::LinkerObject const& _object, string const* _so
|
||||
return output;
|
||||
}
|
||||
|
||||
boost::optional<Json::Value> checkKeys(Json::Value const& _input, set<string> const& _keys)
|
||||
{
|
||||
for (auto const& member: _input.getMemberNames())
|
||||
if (!_keys.count(member))
|
||||
return formatFatalError("JSONError", "Unknown key \"" + member + "\"");
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
boost::optional<Json::Value> checkRootKeys(Json::Value const& _input)
|
||||
{
|
||||
static set<string> keys{"auxiliaryInput", "language", "settings", "sources"};
|
||||
return checkKeys(_input, keys);
|
||||
}
|
||||
|
||||
boost::optional<Json::Value> checkSourceKeys(Json::Value const& _input)
|
||||
{
|
||||
static set<string> keys{"content", "keccak256", "urls"};
|
||||
return checkKeys(_input, keys);
|
||||
}
|
||||
|
||||
boost::optional<Json::Value> checkAuxiliaryInputKeys(Json::Value const& _input)
|
||||
{
|
||||
static set<string> keys{"smtlib2responses"};
|
||||
return checkKeys(_input, keys);
|
||||
}
|
||||
|
||||
boost::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
|
||||
{
|
||||
static set<string> keys{"evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings"};
|
||||
return checkKeys(_input, keys);
|
||||
}
|
||||
|
||||
boost::optional<Json::Value> checkOptimizerKeys(Json::Value const& _input)
|
||||
{
|
||||
static set<string> keys{"enabled", "runs"};
|
||||
return checkKeys(_input, keys);
|
||||
}
|
||||
|
||||
boost::optional<Json::Value> checkMetadataKeys(Json::Value const& _input)
|
||||
{
|
||||
static set<string> keys{"useLiteralContent"};
|
||||
return checkKeys(_input, keys);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
||||
@ -234,6 +281,9 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
||||
if (!_input.isObject())
|
||||
return formatFatalError("JSONError", "Input is not a JSON object.");
|
||||
|
||||
if (auto result = checkRootKeys(_input))
|
||||
return *result;
|
||||
|
||||
if (_input["language"] != "Solidity")
|
||||
return formatFatalError("JSONError", "Only \"Solidity\" is supported as a language.");
|
||||
|
||||
@ -254,6 +304,9 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
||||
if (!sources[sourceName].isObject())
|
||||
return formatFatalError("JSONError", "Source input is not a JSON object.");
|
||||
|
||||
if (auto result = checkSourceKeys(sources[sourceName]))
|
||||
return *result;
|
||||
|
||||
if (sources[sourceName]["keccak256"].isString())
|
||||
hash = sources[sourceName]["keccak256"].asString();
|
||||
|
||||
@ -319,6 +372,10 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
||||
}
|
||||
|
||||
Json::Value const& auxInputs = _input["auxiliaryInput"];
|
||||
|
||||
if (auto result = checkAuxiliaryInputKeys(auxInputs))
|
||||
return *result;
|
||||
|
||||
if (!!auxInputs)
|
||||
{
|
||||
Json::Value const& smtlib2Responses = auxInputs["smtlib2responses"];
|
||||
@ -341,6 +398,9 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
||||
|
||||
Json::Value const& settings = _input.get("settings", Json::Value());
|
||||
|
||||
if (auto result = checkSettingsKeys(settings))
|
||||
return *result;
|
||||
|
||||
if (settings.isMember("evmVersion"))
|
||||
{
|
||||
if (!settings["evmVersion"].isString())
|
||||
@ -366,6 +426,10 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
||||
if (settings.isMember("optimizer"))
|
||||
{
|
||||
Json::Value optimizerSettings = settings["optimizer"];
|
||||
|
||||
if (auto result = checkOptimizerKeys(optimizerSettings))
|
||||
return *result;
|
||||
|
||||
if (optimizerSettings.isMember("enabled"))
|
||||
{
|
||||
if (!optimizerSettings["enabled"].isBool())
|
||||
@ -427,6 +491,10 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
||||
m_compilerStack.setLibraries(libraries);
|
||||
|
||||
Json::Value metadataSettings = settings.get("metadata", Json::Value());
|
||||
|
||||
if (auto result = checkMetadataKeys(metadataSettings))
|
||||
return *result;
|
||||
|
||||
m_compilerStack.useMetadataLiteralSources(metadataSettings.get("useLiteralContent", Json::Value(false)).asBool());
|
||||
|
||||
Json::Value outputSelection = settings.get("outputSelection", Json::Value());
|
||||
|
@ -113,15 +113,20 @@ printTask "Testing unknown options..."
|
||||
test_solc_behaviour() {
|
||||
local filename="${1}"
|
||||
local solc_args="${2}"
|
||||
local stdout_expected="${3}"
|
||||
local exit_code_expected="${4}"
|
||||
local stderr_expected="${5}"
|
||||
local solc_stdin="${3}"
|
||||
local stdout_expected="${4}"
|
||||
local exit_code_expected="${5}"
|
||||
local stderr_expected="${6}"
|
||||
local stdout_path=`mktemp`
|
||||
local stderr_path=`mktemp`
|
||||
if [[ "$exit_code_expected" = "" ]]; then exit_code_expected="0"; fi
|
||||
|
||||
set +e
|
||||
"$SOLC" "${filename}" ${solc_args} 1>$stdout_path 2>$stderr_path
|
||||
if [[ "$solc_stdin" = "" ]]; then
|
||||
"$SOLC" "${filename}" ${solc_args} 1>$stdout_path 2>$stderr_path
|
||||
else
|
||||
"$SOLC" "${filename}" ${solc_args} <$solc_stdin 1>$stdout_path 2>$stderr_path
|
||||
fi
|
||||
exitCode=$?
|
||||
set -e
|
||||
|
||||
@ -158,14 +163,29 @@ test_solc_behaviour() {
|
||||
}
|
||||
|
||||
printTask "Testing passing files that are not found..."
|
||||
test_solc_behaviour "file_not_found.sol" "" "" 1 "\"file_not_found.sol\" is not found."
|
||||
test_solc_behaviour "file_not_found.sol" "" "" "" 1 "\"file_not_found.sol\" is not found."
|
||||
|
||||
printTask "Testing passing files that are not files..."
|
||||
test_solc_behaviour "." "" "" 1 "\".\" is not a valid file."
|
||||
test_solc_behaviour "." "" "" "" 1 "\".\" is not a valid file."
|
||||
|
||||
printTask "Testing passing empty remappings..."
|
||||
test_solc_behaviour "${0}" "=/some/remapping/target" "" 1 "Invalid remapping: \"=/some/remapping/target\"."
|
||||
test_solc_behaviour "${0}" "ctx:=/some/remapping/target" "" 1 "Invalid remapping: \"ctx:=/some/remapping/target\"."
|
||||
test_solc_behaviour "${0}" "=/some/remapping/target" "" "" 1 "Invalid remapping: \"=/some/remapping/target\"."
|
||||
test_solc_behaviour "${0}" "ctx:=/some/remapping/target" "" "" 1 "Invalid remapping: \"ctx:=/some/remapping/target\"."
|
||||
|
||||
printTask "Running standard JSON commandline tests..."
|
||||
(
|
||||
cd "$REPO_ROOT"/test/cmdlineTests/
|
||||
for file in *.json
|
||||
do
|
||||
args="--standard-json"
|
||||
stdin="$REPO_ROOT/test/cmdlineTests/$file"
|
||||
stdout=$(cat $file.stdout 2>/dev/null || true)
|
||||
exitCode=$(cat $file.exit 2>/dev/null || true)
|
||||
err=$(cat $file.err 2>/dev/null || true)
|
||||
printTask " - $file"
|
||||
test_solc_behaviour "" "$args" "$stdin" "$stdout" "$exitCode" "$err"
|
||||
done
|
||||
)
|
||||
|
||||
printTask "Running general commandline tests..."
|
||||
(
|
||||
@ -177,7 +197,7 @@ do
|
||||
exitCode=$(cat $file.exit 2>/dev/null || true)
|
||||
err=$(cat $file.err 2>/dev/null || true)
|
||||
printTask " - $file"
|
||||
test_solc_behaviour "$file" "$args" "$stdout" "$exitCode" "$err"
|
||||
test_solc_behaviour "$file" "$args" "" "$stdout" "$exitCode" "$err"
|
||||
done
|
||||
)
|
||||
|
||||
|
10
test/cmdlineTests/standard.json
Normal file
10
test/cmdlineTests/standard.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/standard.json.exit
Normal file
1
test/cmdlineTests/standard.json.exit
Normal file
@ -0,0 +1 @@
|
||||
0
|
1
test/cmdlineTests/standard.json.stdout
Normal file
1
test/cmdlineTests/standard.json.stdout
Normal file
@ -0,0 +1 @@
|
||||
{"contracts":{"A":{"C":{"evm":{}}}},"errors":[{"component":"general","formattedMessage":"Warning: This is a pre-release compiler version, please do not use it in production.\n","message":"This is a pre-release compiler version, please do not use it in production.","severity":"warning","type":"Warning"}],"sources":{"A":{"id":0}}}
|
14
test/cmdlineTests/standard_wrong_key_auxiliary_input.json
Normal file
14
test/cmdlineTests/standard_wrong_key_auxiliary_input.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
},
|
||||
"auxiliaryInput":
|
||||
{
|
||||
"key1": "test"
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]}
|
22
test/cmdlineTests/standard_wrong_key_metadata.json
Normal file
22
test/cmdlineTests/standard_wrong_key_metadata.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
},
|
||||
"settings":
|
||||
{
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 200
|
||||
},
|
||||
"evmVersion": "byzantium",
|
||||
"metadata": {
|
||||
"key1": "test",
|
||||
"useLiteralContent": true
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/standard_wrong_key_metadata.json.exit
Normal file
1
test/cmdlineTests/standard_wrong_key_metadata.json.exit
Normal file
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]}
|
22
test/cmdlineTests/standard_wrong_key_optimizer.json
Normal file
22
test/cmdlineTests/standard_wrong_key_optimizer.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
},
|
||||
"settings":
|
||||
{
|
||||
"optimizer": {
|
||||
"key1": "test",
|
||||
"enabled": true,
|
||||
"runs": 200
|
||||
},
|
||||
"evmVersion": "byzantium",
|
||||
"metadata": {
|
||||
"useLiteralContent": true
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/standard_wrong_key_optimizer.json.exit
Normal file
1
test/cmdlineTests/standard_wrong_key_optimizer.json.exit
Normal file
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]}
|
11
test/cmdlineTests/standard_wrong_key_root.json
Normal file
11
test/cmdlineTests/standard_wrong_key_root.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"key1": "test",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/standard_wrong_key_root.json.exit
Normal file
1
test/cmdlineTests/standard_wrong_key_root.json.exit
Normal file
@ -0,0 +1 @@
|
||||
0
|
1
test/cmdlineTests/standard_wrong_key_root.json.stdout
Normal file
1
test/cmdlineTests/standard_wrong_key_root.json.stdout
Normal file
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]}
|
22
test/cmdlineTests/standard_wrong_key_settings.json
Normal file
22
test/cmdlineTests/standard_wrong_key_settings.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
},
|
||||
"settings":
|
||||
{
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 200
|
||||
},
|
||||
"evmVersion": "byzantium",
|
||||
"metadata": {
|
||||
"useLiteralContent": true
|
||||
},
|
||||
"key1": "test"
|
||||
}
|
||||
}
|
1
test/cmdlineTests/standard_wrong_key_settings.json.exit
Normal file
1
test/cmdlineTests/standard_wrong_key_settings.json.exit
Normal file
@ -0,0 +1 @@
|
||||
0
|
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]}
|
11
test/cmdlineTests/standard_wrong_key_source.json
Normal file
11
test/cmdlineTests/standard_wrong_key_source.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources":
|
||||
{
|
||||
"A":
|
||||
{
|
||||
"key1": "test",
|
||||
"content": "pragma solidity >=0.0; contract C { function f() public pure {} }"
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/standard_wrong_key_source.json.exit
Normal file
1
test/cmdlineTests/standard_wrong_key_source.json.exit
Normal file
@ -0,0 +1 @@
|
||||
0
|
1
test/cmdlineTests/standard_wrong_key_source.json.stdout
Normal file
1
test/cmdlineTests/standard_wrong_key_source.json.stdout
Normal file
@ -0,0 +1 @@
|
||||
{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]}
|
Loading…
Reference in New Issue
Block a user