From 8cd2ac84622185a59ee61439289d1defe58dec99 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Tue, 11 Dec 2018 15:47:19 +0100 Subject: Disallow unknown JSON keys in standard-json --- Changelog.md | 1 + libsolidity/interface/StandardCompiler.cpp | 68 ++++++++++++++++++++++ test/cmdlineTests.sh | 38 +++++++++--- test/cmdlineTests/standard.json | 10 ++++ test/cmdlineTests/standard.json.exit | 1 + test/cmdlineTests/standard.json.stdout | 1 + .../standard_wrong_key_auxiliary_input.json | 14 +++++ .../standard_wrong_key_auxiliary_input.json.exit | 1 + .../standard_wrong_key_auxiliary_input.json.stdout | 1 + test/cmdlineTests/standard_wrong_key_metadata.json | 22 +++++++ .../standard_wrong_key_metadata.json.exit | 1 + .../standard_wrong_key_metadata.json.stdout | 1 + .../cmdlineTests/standard_wrong_key_optimizer.json | 22 +++++++ .../standard_wrong_key_optimizer.json.exit | 1 + .../standard_wrong_key_optimizer.json.stdout | 1 + test/cmdlineTests/standard_wrong_key_root.json | 11 ++++ .../cmdlineTests/standard_wrong_key_root.json.exit | 1 + .../standard_wrong_key_root.json.stdout | 1 + test/cmdlineTests/standard_wrong_key_settings.json | 22 +++++++ .../standard_wrong_key_settings.json.exit | 1 + .../standard_wrong_key_settings.json.stdout | 1 + test/cmdlineTests/standard_wrong_key_source.json | 11 ++++ .../standard_wrong_key_source.json.exit | 1 + .../standard_wrong_key_source.json.stdout | 1 + 24 files changed, 224 insertions(+), 9 deletions(-) create mode 100644 test/cmdlineTests/standard.json create mode 100644 test/cmdlineTests/standard.json.exit create mode 100644 test/cmdlineTests/standard.json.stdout create mode 100644 test/cmdlineTests/standard_wrong_key_auxiliary_input.json create mode 100644 test/cmdlineTests/standard_wrong_key_auxiliary_input.json.exit create mode 100644 test/cmdlineTests/standard_wrong_key_auxiliary_input.json.stdout create mode 100644 test/cmdlineTests/standard_wrong_key_metadata.json create mode 100644 test/cmdlineTests/standard_wrong_key_metadata.json.exit create mode 100644 test/cmdlineTests/standard_wrong_key_metadata.json.stdout create mode 100644 test/cmdlineTests/standard_wrong_key_optimizer.json create mode 100644 test/cmdlineTests/standard_wrong_key_optimizer.json.exit create mode 100644 test/cmdlineTests/standard_wrong_key_optimizer.json.stdout create mode 100644 test/cmdlineTests/standard_wrong_key_root.json create mode 100644 test/cmdlineTests/standard_wrong_key_root.json.exit create mode 100644 test/cmdlineTests/standard_wrong_key_root.json.stdout create mode 100644 test/cmdlineTests/standard_wrong_key_settings.json create mode 100644 test/cmdlineTests/standard_wrong_key_settings.json.exit create mode 100644 test/cmdlineTests/standard_wrong_key_settings.json.stdout create mode 100644 test/cmdlineTests/standard_wrong_key_source.json create mode 100644 test/cmdlineTests/standard_wrong_key_source.json.exit create mode 100644 test/cmdlineTests/standard_wrong_key_source.json.stdout diff --git a/Changelog.md b/Changelog.md index 838fd8be..4dfd7471 100644 --- a/Changelog.md +++ b/Changelog.md @@ -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. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 862b6633..21d213e7 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -27,7 +27,10 @@ #include #include +#include + #include +#include using namespace std; using namespace dev; @@ -225,6 +228,50 @@ Json::Value collectEVMObject(eth::LinkerObject const& _object, string const* _so return output; } +boost::optional checkKeys(Json::Value const& _input, set const& _keys) +{ + for (auto const& member: _input.getMemberNames()) + if (!_keys.count(member)) + return formatFatalError("JSONError", "Unknown key \"" + member + "\""); + return boost::none; +} + +boost::optional checkRootKeys(Json::Value const& _input) +{ + static set keys{"auxiliaryInput", "language", "settings", "sources"}; + return checkKeys(_input, keys); +} + +boost::optional checkSourceKeys(Json::Value const& _input) +{ + static set keys{"content", "keccak256", "urls"}; + return checkKeys(_input, keys); +} + +boost::optional checkAuxiliaryInputKeys(Json::Value const& _input) +{ + static set keys{"smtlib2responses"}; + return checkKeys(_input, keys); +} + +boost::optional checkSettingsKeys(Json::Value const& _input) +{ + static set keys{"evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings"}; + return checkKeys(_input, keys); +} + +boost::optional checkOptimizerKeys(Json::Value const& _input) +{ + static set keys{"enabled", "runs"}; + return checkKeys(_input, keys); +} + +boost::optional checkMetadataKeys(Json::Value const& _input) +{ + static set 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()); diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 7b2b528b..95176814 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -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 ) diff --git a/test/cmdlineTests/standard.json b/test/cmdlineTests/standard.json new file mode 100644 index 00000000..826253b8 --- /dev/null +++ b/test/cmdlineTests/standard.json @@ -0,0 +1,10 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + } +} diff --git a/test/cmdlineTests/standard.json.exit b/test/cmdlineTests/standard.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard.json.stdout b/test/cmdlineTests/standard.json.stdout new file mode 100644 index 00000000..ba4099e5 --- /dev/null +++ b/test/cmdlineTests/standard.json.stdout @@ -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}}} diff --git a/test/cmdlineTests/standard_wrong_key_auxiliary_input.json b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json new file mode 100644 index 00000000..51dbce41 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json @@ -0,0 +1,14 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "auxiliaryInput": + { + "key1": "test" + } +} diff --git a/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.exit b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.stdout b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_metadata.json b/test/cmdlineTests/standard_wrong_key_metadata.json new file mode 100644 index 00000000..490e489a --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_metadata.json @@ -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 + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_metadata.json.exit b/test/cmdlineTests/standard_wrong_key_metadata.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_metadata.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_metadata.json.stdout b/test/cmdlineTests/standard_wrong_key_metadata.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_metadata.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_optimizer.json b/test/cmdlineTests/standard_wrong_key_optimizer.json new file mode 100644 index 00000000..c28c3a92 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_optimizer.json @@ -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 + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_optimizer.json.exit b/test/cmdlineTests/standard_wrong_key_optimizer.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_optimizer.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_optimizer.json.stdout b/test/cmdlineTests/standard_wrong_key_optimizer.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_optimizer.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_root.json b/test/cmdlineTests/standard_wrong_key_root.json new file mode 100644 index 00000000..4689c50c --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_root.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "key1": "test", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_root.json.exit b/test/cmdlineTests/standard_wrong_key_root.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_root.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_root.json.stdout b/test/cmdlineTests/standard_wrong_key_root.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_root.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_settings.json b/test/cmdlineTests/standard_wrong_key_settings.json new file mode 100644 index 00000000..d7809b1c --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_settings.json @@ -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" + } +} diff --git a/test/cmdlineTests/standard_wrong_key_settings.json.exit b/test/cmdlineTests/standard_wrong_key_settings.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_settings.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_settings.json.stdout b/test/cmdlineTests/standard_wrong_key_settings.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_settings.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_source.json b/test/cmdlineTests/standard_wrong_key_source.json new file mode 100644 index 00000000..d8a8aa16 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_source.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "key1": "test", + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_source.json.exit b/test/cmdlineTests/standard_wrong_key_source.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_source.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_source.json.stdout b/test/cmdlineTests/standard_wrong_key_source.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_source.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} -- cgit