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

Verify supplied hash in JSON I/O #2159

Merged
merged 1 commit into from Apr 24, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 45 additions & 4 deletions libsolidity/interface/StandardCompiler.cpp
Expand Up @@ -25,6 +25,7 @@
#include <libsolidity/ast/ASTJsonConverter.h>
#include <libevmasm/Instruction.h>
#include <libdevcore/JSON.h>
#include <libdevcore/SHA3.h>

using namespace std;
using namespace dev;
Expand Down Expand Up @@ -91,6 +92,19 @@ Json::Value formatErrorWithException(
return formatError(_warning, _type, _component, message, formattedMessage, location);
}

/// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content.
bool hashMatchesContent(string const& _hash, string const& _content)
{
try
{
return dev::h256(_hash) == dev::keccak256(_content);
}
catch (dev::BadHexCharacter)
{
return false;
}
}

StringMap createSourceList(Json::Value const& _input)
{
StringMap sources;
Expand Down Expand Up @@ -165,8 +179,24 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
Json::Value errors = Json::arrayValue;

for (auto const& sourceName: sources.getMemberNames())
{
string hash;
if (sources[sourceName]["keccak256"].isString())
hash = sources[sourceName]["keccak256"].asString();

if (sources[sourceName]["content"].isString())
m_compilerStack.addSource(sourceName, sources[sourceName]["content"].asString());
{
string content = sources[sourceName]["content"].asString();
if (!hash.empty() && !hashMatchesContent(hash, content))
errors.append(formatError(
false,
"IOError",
"general",
"Mismatch between content and supplied hash for \"" + sourceName + "\""
));
else
m_compilerStack.addSource(sourceName, content);
}
else if (sources[sourceName]["urls"].isArray())
{
if (!m_readFile)
Expand All @@ -180,9 +210,19 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
ReadFile::Result result = m_readFile(url.asString());
if (result.success)
{
m_compilerStack.addSource(sourceName, result.contentsOrErrorMessage);
found = true;
break;
if (!hash.empty() && !hashMatchesContent(hash, result.contentsOrErrorMessage))
errors.append(formatError(
false,
"IOError",
"general",
"Mismatch between content and supplied hash for \"" + sourceName + "\" at \"" + url.asString() + "\""
));
else
{
m_compilerStack.addSource(sourceName, result.contentsOrErrorMessage);
found = true;
break;
}
}
else
failures.push_back("Cannot import url (\"" + url.asString() + "\"): " + result.contentsOrErrorMessage);
Expand All @@ -201,6 +241,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
}
else
return formatFatalError("JSONError", "Invalid input source specified.");
}

Json::Value const& settings = _input.get("settings", Json::Value());

Expand Down