aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-12-19 02:39:46 +0800
committerGitHub <noreply@github.com>2018-12-19 02:39:46 +0800
commit20189c3f3bb553096b0eb8a783d80d04ba6d49e9 (patch)
treefdcdc267b6767b49aea66a0dbd5cd3c7d5b3fa4d /libsolidity
parente33545292ac2a5a40e03f3d3b6a43773b7f04333 (diff)
parentc43d96f2bf5614136bfbcaf45d0850c914bf81ee (diff)
downloaddexon-solidity-20189c3f3bb553096b0eb8a783d80d04ba6d49e9.tar.gz
dexon-solidity-20189c3f3bb553096b0eb8a783d80d04ba6d49e9.tar.zst
dexon-solidity-20189c3f3bb553096b0eb8a783d80d04ba6d49e9.zip
Merge pull request #5637 from ethereum/better-json-error-reporting
Json: Provide better error message when 'settings' is not an object
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/interface/StandardCompiler.cpp90
1 files changed, 77 insertions, 13 deletions
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 5be267e9..e99b1324 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -228,48 +228,97 @@ 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)
+boost::optional<Json::Value> checkKeys(Json::Value const& _input, set<string> const& _keys, string const& _name)
{
+ if (!!_input && !_input.isObject())
+ return formatFatalError("JSONError", "\"" + _name + "\" must be an object");
+
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);
+ return checkKeys(_input, keys, "root");
}
-boost::optional<Json::Value> checkSourceKeys(Json::Value const& _input)
+boost::optional<Json::Value> checkSourceKeys(Json::Value const& _input, string const& _name)
{
static set<string> keys{"content", "keccak256", "urls"};
- return checkKeys(_input, keys);
+ return checkKeys(_input, keys, "sources." + _name);
}
boost::optional<Json::Value> checkAuxiliaryInputKeys(Json::Value const& _input)
{
static set<string> keys{"smtlib2responses"};
- return checkKeys(_input, keys);
+ return checkKeys(_input, keys, "auxiliaryInput");
}
boost::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
{
static set<string> keys{"evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings"};
- return checkKeys(_input, keys);
+ return checkKeys(_input, keys, "settings");
}
boost::optional<Json::Value> checkOptimizerKeys(Json::Value const& _input)
{
static set<string> keys{"enabled", "runs"};
- return checkKeys(_input, keys);
+ return checkKeys(_input, keys, "settings.optimizer");
}
boost::optional<Json::Value> checkMetadataKeys(Json::Value const& _input)
{
static set<string> keys{"useLiteralContent"};
- return checkKeys(_input, keys);
+ return checkKeys(_input, keys, "settings.metadata");
+}
+
+boost::optional<Json::Value> checkOutputSelection(Json::Value const& _outputSelection)
+{
+ if (!!_outputSelection && !_outputSelection.isObject())
+ return formatFatalError("JSONError", "\"settings.outputSelection\" must be an object");
+
+ for (auto const& sourceName: _outputSelection.getMemberNames())
+ {
+ auto const& sourceVal = _outputSelection[sourceName];
+
+ if (!sourceVal.isObject())
+ return formatFatalError(
+ "JSONError",
+ "\"settings.outputSelection." + sourceName + "\" must be an object"
+ );
+
+ for (auto const& contractName: sourceVal.getMemberNames())
+ {
+ auto const& contractVal = sourceVal[contractName];
+
+ if (!contractVal.isArray())
+ return formatFatalError(
+ "JSONError",
+ "\"settings.outputSelection." +
+ sourceName +
+ "." +
+ contractName +
+ "\" must be a string array"
+ );
+
+ for (auto const& output: contractVal)
+ if (!output.isString())
+ return formatFatalError(
+ "JSONError",
+ "\"settings.outputSelection." +
+ sourceName +
+ "." +
+ contractName +
+ "\" must be a string array"
+ );
+ }
+ }
+
+ return boost::none;
}
}
@@ -301,10 +350,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
{
string hash;
- if (!sources[sourceName].isObject())
- return formatFatalError("JSONError", "Source input is not a JSON object.");
-
- if (auto result = checkSourceKeys(sources[sourceName]))
+ if (auto result = checkSourceKeys(sources[sourceName], sourceName))
return *result;
if (sources[sourceName]["keccak256"].isString())
@@ -380,6 +426,10 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
{
Json::Value const& smtlib2Responses = auxInputs["smtlib2responses"];
if (!!smtlib2Responses)
+ {
+ if (!smtlib2Responses.isObject())
+ return formatFatalError("JSONError", "\"auxiliaryInput.smtlib2responses\" must be an object.");
+
for (auto const& hashString: smtlib2Responses.getMemberNames())
{
h256 hash;
@@ -392,8 +442,15 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
return formatFatalError("JSONError", "Invalid hex encoding of SMTLib2 auxiliary input.");
}
+ if (!smtlib2Responses[hashString].isString())
+ return formatFatalError(
+ "JSONError",
+ "\"smtlib2Responses." + hashString + "\" must be a string."
+ );
+
m_compilerStack.addSMTLib2Response(hash, smtlib2Responses[hashString].asString());
}
+ }
}
Json::Value const& settings = _input.get("settings", Json::Value());
@@ -411,11 +468,14 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
m_compilerStack.setEVMVersion(*version);
}
+ if (settings.isMember("remappings") && !settings["remappings"].isArray())
+ return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings.");
+
vector<CompilerStack::Remapping> remappings;
for (auto const& remapping: settings.get("remappings", Json::Value()))
{
if (!remapping.isString())
- return formatFatalError("JSONError", "Remapping entry must be a string.");
+ return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings");
if (auto r = CompilerStack::parseRemapping(remapping.asString()))
remappings.emplace_back(std::move(*r));
else
@@ -498,6 +558,10 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
m_compilerStack.useMetadataLiteralSources(metadataSettings.get("useLiteralContent", Json::Value(false)).asBool());
Json::Value outputSelection = settings.get("outputSelection", Json::Value());
+
+ if (auto jsonError = checkOutputSelection(outputSelection))
+ return *jsonError;
+
m_compilerStack.setRequestedContractNames(requestedContractNames(outputSelection));
try