mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add CLI option to choose model checker engine
This commit is contained in:
parent
23314fc96c
commit
4e49135318
@ -12,6 +12,8 @@ Compiler Features:
|
|||||||
* SMTChecker: Support inline arrays.
|
* SMTChecker: Support inline arrays.
|
||||||
* SMTChecker: Support variables ``block``, ``msg`` and ``tx`` in the CHC engine.
|
* SMTChecker: Support variables ``block``, ``msg`` and ``tx`` in the CHC engine.
|
||||||
* Control Flow Graph: Print warning for non-empty functions with unnamed return parameters that are not assigned a value in all code paths.
|
* Control Flow Graph: Print warning for non-empty functions with unnamed return parameters that are not assigned a value in all code paths.
|
||||||
|
* Command Line Interface: New option ``model-checker-engine`` allows to choose a specific SMTChecker engine. Options are ``all`` (default), ``bmc``, ``chc`` and ``none``.
|
||||||
|
* Standard JSON: New option ``settings.modelCheckerEngine`` allows to choose a specific SMTChecker engine. Options are ``all`` (default), ``bmc``, ``chc`` and ``none``.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -341,7 +341,9 @@ Input Description
|
|||||||
"def": {
|
"def": {
|
||||||
"MyContract": [ "abi", "evm.bytecode.opcodes" ]
|
"MyContract": [ "abi", "evm.bytecode.opcodes" ]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
// Choose which model checker engine to use: all (default), bmc, chc, none.
|
||||||
|
"modelCheckerEngine": "chc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ void SourceReferenceFormatterHuman::printExceptionInformation(SourceReferenceExt
|
|||||||
for (auto const& secondary: _msg.secondary)
|
for (auto const& secondary: _msg.secondary)
|
||||||
{
|
{
|
||||||
secondaryColored() << "Note";
|
secondaryColored() << "Note";
|
||||||
messageColored() << ": " << secondary.message << '\n';
|
messageColored() << ":" << (secondary.message.empty() ? "" : (" " + secondary.message)) << '\n';
|
||||||
printSourceLocation(secondary);
|
printSourceLocation(secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,7 +836,7 @@ void BMC::checkCondition(
|
|||||||
"\nNote that some information is erased after the execution of loops.\n"
|
"\nNote that some information is erased after the execution of loops.\n"
|
||||||
"You can re-introduce information using require().";
|
"You can re-introduce information using require().";
|
||||||
if (m_externalFunctionCallHappened)
|
if (m_externalFunctionCallHappened)
|
||||||
extraComment+=
|
extraComment +=
|
||||||
"\nNote that external function calls are not inlined,"
|
"\nNote that external function calls are not inlined,"
|
||||||
" even if the source code of the function is available."
|
" even if the source code of the function is available."
|
||||||
" This is due to the possibility that the actual called contract"
|
" This is due to the possibility that the actual called contract"
|
||||||
@ -854,7 +854,7 @@ void BMC::checkCondition(
|
|||||||
if (_callStack.size())
|
if (_callStack.size())
|
||||||
{
|
{
|
||||||
std::ostringstream modelMessage;
|
std::ostringstream modelMessage;
|
||||||
modelMessage << "\nCounterexample:\n";
|
modelMessage << "Counterexample:\n";
|
||||||
solAssert(values.size() == expressionNames.size(), "");
|
solAssert(values.size() == expressionNames.size(), "");
|
||||||
map<string, string> sortedModel;
|
map<string, string> sortedModel;
|
||||||
for (size_t i = 0; i < values.size(); ++i)
|
for (size_t i = 0; i < values.size(); ++i)
|
||||||
@ -863,6 +863,7 @@ void BMC::checkCondition(
|
|||||||
|
|
||||||
for (auto const& eval: sortedModel)
|
for (auto const& eval: sortedModel)
|
||||||
modelMessage << " " << eval.first << " = " << eval.second << "\n";
|
modelMessage << " " << eval.first << " = " << eval.second << "\n";
|
||||||
|
|
||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
_errorHappens,
|
_errorHappens,
|
||||||
_location,
|
_location,
|
||||||
|
@ -1298,7 +1298,7 @@ void CHC::checkAndReportTarget(
|
|||||||
_errorReporterId,
|
_errorReporterId,
|
||||||
_scope->location(),
|
_scope->location(),
|
||||||
"CHC: " + _satMsg,
|
"CHC: " + _satMsg,
|
||||||
SecondarySourceLocation().append("\nCounterexample:\n" + *cex, SourceLocation{})
|
SecondarySourceLocation().append("Counterexample:\n" + *cex, SourceLocation{})
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
m_outerErrorReporter.warning(
|
m_outerErrorReporter.warning(
|
||||||
@ -1402,9 +1402,13 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
auto modelMsg = formatVariableModel(*stateVars, stateValues, ", ");
|
||||||
/// We report the state after every tx in the trace except for the last, which is reported
|
/// We report the state after every tx in the trace except for the last, which is reported
|
||||||
/// first in the code above.
|
/// first in the code above.
|
||||||
path.emplace_back("State: " + formatVariableModel(*stateVars, stateValues, ", "));
|
if (!modelMsg.empty())
|
||||||
|
path.emplace_back("State: " + modelMsg);
|
||||||
|
}
|
||||||
|
|
||||||
string txCex = summaryPredicate->formatSummaryCall(summaryArgs);
|
string txCex = summaryPredicate->formatSummaryCall(summaryArgs);
|
||||||
path.emplace_back(txCex);
|
path.emplace_back(txCex);
|
||||||
|
@ -27,9 +27,11 @@ using namespace solidity::frontend;
|
|||||||
ModelChecker::ModelChecker(
|
ModelChecker::ModelChecker(
|
||||||
ErrorReporter& _errorReporter,
|
ErrorReporter& _errorReporter,
|
||||||
map<h256, string> const& _smtlib2Responses,
|
map<h256, string> const& _smtlib2Responses,
|
||||||
|
ModelCheckerEngine _engine,
|
||||||
ReadCallback::Callback const& _smtCallback,
|
ReadCallback::Callback const& _smtCallback,
|
||||||
smtutil::SMTSolverChoice _enabledSolvers
|
smtutil::SMTSolverChoice _enabledSolvers
|
||||||
):
|
):
|
||||||
|
m_engine(_engine),
|
||||||
m_context(),
|
m_context(),
|
||||||
m_bmc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, _enabledSolvers),
|
m_bmc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, _enabledSolvers),
|
||||||
m_chc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, _enabledSolvers)
|
m_chc(m_context, _errorReporter, _smtlib2Responses, _smtCallback, _enabledSolvers)
|
||||||
@ -41,13 +43,15 @@ void ModelChecker::analyze(SourceUnit const& _source)
|
|||||||
if (!_source.annotation().experimentalFeatures.count(ExperimentalFeature::SMTChecker))
|
if (!_source.annotation().experimentalFeatures.count(ExperimentalFeature::SMTChecker))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_chc.analyze(_source);
|
if (m_engine.chc)
|
||||||
|
m_chc.analyze(_source);
|
||||||
|
|
||||||
auto solvedTargets = m_chc.safeTargets();
|
auto solvedTargets = m_chc.safeTargets();
|
||||||
for (auto const& target: m_chc.unsafeTargets())
|
for (auto const& target: m_chc.unsafeTargets())
|
||||||
solvedTargets[target.first] += target.second;
|
solvedTargets[target.first] += target.second;
|
||||||
|
|
||||||
m_bmc.analyze(_source, solvedTargets);
|
if (m_engine.bmc)
|
||||||
|
m_bmc.analyze(_source, solvedTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> ModelChecker::unhandledQueries()
|
vector<string> ModelChecker::unhandledQueries()
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include <libsmtutil/SolverInterface.h>
|
#include <libsmtutil/SolverInterface.h>
|
||||||
#include <liblangutil/ErrorReporter.h>
|
#include <liblangutil/ErrorReporter.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace solidity::langutil
|
namespace solidity::langutil
|
||||||
{
|
{
|
||||||
class ErrorReporter;
|
class ErrorReporter;
|
||||||
@ -41,6 +43,34 @@ struct SourceLocation;
|
|||||||
namespace solidity::frontend
|
namespace solidity::frontend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct ModelCheckerEngine
|
||||||
|
{
|
||||||
|
bool bmc = false;
|
||||||
|
bool chc = false;
|
||||||
|
|
||||||
|
static constexpr ModelCheckerEngine All() { return {true, true}; }
|
||||||
|
static constexpr ModelCheckerEngine BMC() { return {true, false}; }
|
||||||
|
static constexpr ModelCheckerEngine CHC() { return {false, true}; }
|
||||||
|
static constexpr ModelCheckerEngine None() { return {false, false}; }
|
||||||
|
|
||||||
|
bool none() const { return !any(); }
|
||||||
|
bool any() const { return bmc || chc; }
|
||||||
|
bool all() const { return bmc && chc; }
|
||||||
|
|
||||||
|
static std::optional<ModelCheckerEngine> fromString(std::string const& _engine)
|
||||||
|
{
|
||||||
|
static std::map<std::string, ModelCheckerEngine> engineMap{
|
||||||
|
{"all", All()},
|
||||||
|
{"bmc", BMC()},
|
||||||
|
{"chc", CHC()},
|
||||||
|
{"none", None()}
|
||||||
|
};
|
||||||
|
if (engineMap.count(_engine))
|
||||||
|
return engineMap.at(_engine);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ModelChecker
|
class ModelChecker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -49,6 +79,7 @@ public:
|
|||||||
ModelChecker(
|
ModelChecker(
|
||||||
langutil::ErrorReporter& _errorReporter,
|
langutil::ErrorReporter& _errorReporter,
|
||||||
std::map<solidity::util::h256, std::string> const& _smtlib2Responses,
|
std::map<solidity::util::h256, std::string> const& _smtlib2Responses,
|
||||||
|
ModelCheckerEngine _engine = ModelCheckerEngine::All(),
|
||||||
ReadCallback::Callback const& _smtCallback = ReadCallback::Callback(),
|
ReadCallback::Callback const& _smtCallback = ReadCallback::Callback(),
|
||||||
smtutil::SMTSolverChoice _enabledSolvers = smtutil::SMTSolverChoice::All()
|
smtutil::SMTSolverChoice _enabledSolvers = smtutil::SMTSolverChoice::All()
|
||||||
);
|
);
|
||||||
@ -64,6 +95,8 @@ public:
|
|||||||
static smtutil::SMTSolverChoice availableSolvers();
|
static smtutil::SMTSolverChoice availableSolvers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ModelCheckerEngine m_engine;
|
||||||
|
|
||||||
/// Stores the context of the encoding.
|
/// Stores the context of the encoding.
|
||||||
smt::EncodingContext m_context;
|
smt::EncodingContext m_context;
|
||||||
|
|
||||||
|
@ -2114,7 +2114,7 @@ SecondarySourceLocation SMTEncoder::callStackMessage(vector<CallStackEntry> cons
|
|||||||
{
|
{
|
||||||
SecondarySourceLocation callStackLocation;
|
SecondarySourceLocation callStackLocation;
|
||||||
solAssert(!_callStack.empty(), "");
|
solAssert(!_callStack.empty(), "");
|
||||||
callStackLocation.append("Callstack: ", SourceLocation());
|
callStackLocation.append("Callstack:", SourceLocation());
|
||||||
for (auto const& call: _callStack | boost::adaptors::reversed)
|
for (auto const& call: _callStack | boost::adaptors::reversed)
|
||||||
if (call.second)
|
if (call.second)
|
||||||
callStackLocation.append("", call.second->location());
|
callStackLocation.append("", call.second->location());
|
||||||
|
@ -87,6 +87,7 @@ static int g_compilerStackCounts = 0;
|
|||||||
|
|
||||||
CompilerStack::CompilerStack(ReadCallback::Callback _readFile):
|
CompilerStack::CompilerStack(ReadCallback::Callback _readFile):
|
||||||
m_readFile{std::move(_readFile)},
|
m_readFile{std::move(_readFile)},
|
||||||
|
m_modelCheckerEngine{ModelCheckerEngine::All()},
|
||||||
m_enabledSMTSolvers{smtutil::SMTSolverChoice::All()},
|
m_enabledSMTSolvers{smtutil::SMTSolverChoice::All()},
|
||||||
m_errorReporter{m_errorList}
|
m_errorReporter{m_errorList}
|
||||||
{
|
{
|
||||||
@ -138,6 +139,13 @@ void CompilerStack::setEVMVersion(langutil::EVMVersion _version)
|
|||||||
m_evmVersion = _version;
|
m_evmVersion = _version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompilerStack::setModelCheckerEngine(ModelCheckerEngine _engine)
|
||||||
|
{
|
||||||
|
if (m_stackState >= ParsedAndImported)
|
||||||
|
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Must set enabled model checking engines before parsing."));
|
||||||
|
m_modelCheckerEngine = _engine;
|
||||||
|
}
|
||||||
|
|
||||||
void CompilerStack::setSMTSolverChoice(smtutil::SMTSolverChoice _enabledSMTSolvers)
|
void CompilerStack::setSMTSolverChoice(smtutil::SMTSolverChoice _enabledSMTSolvers)
|
||||||
{
|
{
|
||||||
if (m_stackState >= ParsedAndImported)
|
if (m_stackState >= ParsedAndImported)
|
||||||
@ -207,6 +215,7 @@ void CompilerStack::reset(bool _keepSettings)
|
|||||||
m_remappings.clear();
|
m_remappings.clear();
|
||||||
m_libraries.clear();
|
m_libraries.clear();
|
||||||
m_evmVersion = langutil::EVMVersion();
|
m_evmVersion = langutil::EVMVersion();
|
||||||
|
m_modelCheckerEngine = ModelCheckerEngine::All();
|
||||||
m_enabledSMTSolvers = smtutil::SMTSolverChoice::All();
|
m_enabledSMTSolvers = smtutil::SMTSolverChoice::All();
|
||||||
m_generateIR = false;
|
m_generateIR = false;
|
||||||
m_generateEwasm = false;
|
m_generateEwasm = false;
|
||||||
@ -443,7 +452,7 @@ bool CompilerStack::analyze()
|
|||||||
|
|
||||||
if (noErrors)
|
if (noErrors)
|
||||||
{
|
{
|
||||||
ModelChecker modelChecker(m_errorReporter, m_smtlib2Responses, m_readFile, m_enabledSMTSolvers);
|
ModelChecker modelChecker(m_errorReporter, m_smtlib2Responses, m_modelCheckerEngine, m_readFile, m_enabledSMTSolvers);
|
||||||
for (Source const* source: m_sourceOrder)
|
for (Source const* source: m_sourceOrder)
|
||||||
if (source->ast)
|
if (source->ast)
|
||||||
modelChecker.analyze(*source->ast);
|
modelChecker.analyze(*source->ast);
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#include <libsolidity/interface/Version.h>
|
#include <libsolidity/interface/Version.h>
|
||||||
#include <libsolidity/interface/DebugSettings.h>
|
#include <libsolidity/interface/DebugSettings.h>
|
||||||
|
|
||||||
|
#include <libsolidity/formal/ModelChecker.h>
|
||||||
|
|
||||||
#include <libsmtutil/SolverInterface.h>
|
#include <libsmtutil/SolverInterface.h>
|
||||||
|
|
||||||
#include <liblangutil/ErrorReporter.h>
|
#include <liblangutil/ErrorReporter.h>
|
||||||
@ -165,6 +167,8 @@ public:
|
|||||||
/// Must be set before parsing.
|
/// Must be set before parsing.
|
||||||
void setEVMVersion(langutil::EVMVersion _version = langutil::EVMVersion{});
|
void setEVMVersion(langutil::EVMVersion _version = langutil::EVMVersion{});
|
||||||
|
|
||||||
|
/// Set which model checking engines should be used.
|
||||||
|
void setModelCheckerEngine(ModelCheckerEngine _engine);
|
||||||
/// Set which SMT solvers should be enabled.
|
/// Set which SMT solvers should be enabled.
|
||||||
void setSMTSolverChoice(smtutil::SMTSolverChoice _enabledSolvers);
|
void setSMTSolverChoice(smtutil::SMTSolverChoice _enabledSolvers);
|
||||||
|
|
||||||
@ -452,6 +456,7 @@ private:
|
|||||||
RevertStrings m_revertStrings = RevertStrings::Default;
|
RevertStrings m_revertStrings = RevertStrings::Default;
|
||||||
State m_stopAfter = State::CompilationSuccessful;
|
State m_stopAfter = State::CompilationSuccessful;
|
||||||
langutil::EVMVersion m_evmVersion;
|
langutil::EVMVersion m_evmVersion;
|
||||||
|
ModelCheckerEngine m_modelCheckerEngine;
|
||||||
smtutil::SMTSolverChoice m_enabledSMTSolvers;
|
smtutil::SMTSolverChoice m_enabledSMTSolvers;
|
||||||
std::map<std::string, std::set<std::string>> m_requestedContractNames;
|
std::map<std::string, std::set<std::string>> m_requestedContractNames;
|
||||||
bool m_generateEvmBytecode = true;
|
bool m_generateEvmBytecode = true;
|
||||||
|
@ -414,7 +414,7 @@ std::optional<Json::Value> checkAuxiliaryInputKeys(Json::Value const& _input)
|
|||||||
|
|
||||||
std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
|
std::optional<Json::Value> checkSettingsKeys(Json::Value const& _input)
|
||||||
{
|
{
|
||||||
static set<string> keys{"parserErrorRecovery", "debug", "evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings", "stopAfter"};
|
static set<string> keys{"parserErrorRecovery", "debug", "evmVersion", "libraries", "metadata", "optimizer", "outputSelection", "remappings", "stopAfter", "modelCheckerEngine"};
|
||||||
return checkKeys(_input, keys, "settings");
|
return checkKeys(_input, keys, "settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,6 +527,7 @@ std::optional<Json::Value> checkOutputSelection(Json::Value const& _outputSelect
|
|||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates the optimizer settings and returns them in a parsed object.
|
/// Validates the optimizer settings and returns them in a parsed object.
|
||||||
/// On error returns the json-formatted error message.
|
/// On error returns the json-formatted error message.
|
||||||
std::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value const& _jsonInput)
|
std::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value const& _jsonInput)
|
||||||
@ -866,6 +867,16 @@ std::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler:
|
|||||||
"Requested output selection conflicts with \"settings.stopAfter\"."
|
"Requested output selection conflicts with \"settings.stopAfter\"."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (settings.isMember("modelCheckerEngine"))
|
||||||
|
{
|
||||||
|
if (!settings["modelCheckerEngine"].isString())
|
||||||
|
return formatFatalError("JSONError", "modelCheckerEngine must be a string.");
|
||||||
|
std::optional<ModelCheckerEngine> engine = ModelCheckerEngine::fromString(settings["modelCheckerEngine"].asString());
|
||||||
|
if (!engine)
|
||||||
|
return formatFatalError("JSONError", "Invalid model checker engine requested.");
|
||||||
|
ret.modelCheckerEngine = *engine;
|
||||||
|
}
|
||||||
|
|
||||||
return { std::move(ret) };
|
return { std::move(ret) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -886,6 +897,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
|
|||||||
compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources);
|
compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources);
|
||||||
compilerStack.setMetadataHash(_inputsAndSettings.metadataHash);
|
compilerStack.setMetadataHash(_inputsAndSettings.metadataHash);
|
||||||
compilerStack.setRequestedContractNames(requestedContractNames(_inputsAndSettings.outputSelection));
|
compilerStack.setRequestedContractNames(requestedContractNames(_inputsAndSettings.outputSelection));
|
||||||
|
compilerStack.setModelCheckerEngine(_inputsAndSettings.modelCheckerEngine);
|
||||||
|
|
||||||
compilerStack.enableEvmBytecodeGeneration(isEvmBytecodeRequested(_inputsAndSettings.outputSelection));
|
compilerStack.enableEvmBytecodeGeneration(isEvmBytecodeRequested(_inputsAndSettings.outputSelection));
|
||||||
compilerStack.enableIRGeneration(isIRRequested(_inputsAndSettings.outputSelection));
|
compilerStack.enableIRGeneration(isIRRequested(_inputsAndSettings.outputSelection));
|
||||||
|
@ -71,6 +71,7 @@ private:
|
|||||||
bool metadataLiteralSources = false;
|
bool metadataLiteralSources = false;
|
||||||
CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS;
|
CompilerStack::MetadataHash metadataHash = CompilerStack::MetadataHash::IPFS;
|
||||||
Json::Value outputSelection;
|
Json::Value outputSelection;
|
||||||
|
ModelCheckerEngine modelCheckerEngine = ModelCheckerEngine::All();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses the input json (and potentially invokes the read callback) and either returns
|
/// Parses the input json (and potentially invokes the read callback) and either returns
|
||||||
|
@ -146,6 +146,7 @@ static string const g_strMachine = "machine";
|
|||||||
static string const g_strMetadata = "metadata";
|
static string const g_strMetadata = "metadata";
|
||||||
static string const g_strMetadataHash = "metadata-hash";
|
static string const g_strMetadataHash = "metadata-hash";
|
||||||
static string const g_strMetadataLiteral = "metadata-literal";
|
static string const g_strMetadataLiteral = "metadata-literal";
|
||||||
|
static string const g_strModelCheckerEngine = "model-checker-engine";
|
||||||
static string const g_strNatspecDev = "devdoc";
|
static string const g_strNatspecDev = "devdoc";
|
||||||
static string const g_strNatspecUser = "userdoc";
|
static string const g_strNatspecUser = "userdoc";
|
||||||
static string const g_strNone = "none";
|
static string const g_strNone = "none";
|
||||||
@ -215,6 +216,7 @@ static string const g_argMachine = g_strMachine;
|
|||||||
static string const g_argMetadata = g_strMetadata;
|
static string const g_argMetadata = g_strMetadata;
|
||||||
static string const g_argMetadataHash = g_strMetadataHash;
|
static string const g_argMetadataHash = g_strMetadataHash;
|
||||||
static string const g_argMetadataLiteral = g_strMetadataLiteral;
|
static string const g_argMetadataLiteral = g_strMetadataLiteral;
|
||||||
|
static string const g_argModelCheckerEngine = g_strModelCheckerEngine;
|
||||||
static string const g_argNatspecDev = g_strNatspecDev;
|
static string const g_argNatspecDev = g_strNatspecDev;
|
||||||
static string const g_argNatspecUser = g_strNatspecUser;
|
static string const g_argNatspecUser = g_strNatspecUser;
|
||||||
static string const g_argOpcodes = g_strOpcodes;
|
static string const g_argOpcodes = g_strOpcodes;
|
||||||
@ -993,6 +995,16 @@ General Information)").c_str(),
|
|||||||
;
|
;
|
||||||
desc.add(optimizerOptions);
|
desc.add(optimizerOptions);
|
||||||
|
|
||||||
|
po::options_description smtCheckerOptions("Model Checker Options");
|
||||||
|
smtCheckerOptions.add_options()
|
||||||
|
(
|
||||||
|
g_strModelCheckerEngine.c_str(),
|
||||||
|
po::value<string>()->value_name("all,bmc,chc,none")->default_value("all"),
|
||||||
|
"Select model checker engine."
|
||||||
|
)
|
||||||
|
;
|
||||||
|
desc.add(smtCheckerOptions);
|
||||||
|
|
||||||
po::options_description allOptions = desc;
|
po::options_description allOptions = desc;
|
||||||
allOptions.add_options()(g_argInputFile.c_str(), po::value<vector<string>>(), "input file");
|
allOptions.add_options()(g_argInputFile.c_str(), po::value<vector<string>>(), "input file");
|
||||||
|
|
||||||
@ -1379,6 +1391,18 @@ bool CommandLineInterface::processInput()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_args.count(g_argModelCheckerEngine))
|
||||||
|
{
|
||||||
|
string engineStr = m_args[g_argModelCheckerEngine].as<string>();
|
||||||
|
optional<ModelCheckerEngine> engine = ModelCheckerEngine::fromString(engineStr);
|
||||||
|
if (!engine)
|
||||||
|
{
|
||||||
|
serr() << "Invalid option for --" << g_argModelCheckerEngine << ": " << engineStr << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_modelCheckerEngine = *engine;
|
||||||
|
}
|
||||||
|
|
||||||
m_compiler = make_unique<CompilerStack>(fileReader);
|
m_compiler = make_unique<CompilerStack>(fileReader);
|
||||||
|
|
||||||
unique_ptr<SourceReferenceFormatter> formatter;
|
unique_ptr<SourceReferenceFormatter> formatter;
|
||||||
@ -1393,6 +1417,8 @@ bool CommandLineInterface::processInput()
|
|||||||
m_compiler->useMetadataLiteralSources(true);
|
m_compiler->useMetadataLiteralSources(true);
|
||||||
if (m_args.count(g_argMetadataHash))
|
if (m_args.count(g_argMetadataHash))
|
||||||
m_compiler->setMetadataHash(m_metadataHash);
|
m_compiler->setMetadataHash(m_metadataHash);
|
||||||
|
if (m_args.count(g_argModelCheckerEngine))
|
||||||
|
m_compiler->setModelCheckerEngine(m_modelCheckerEngine);
|
||||||
if (m_args.count(g_argInputFile))
|
if (m_args.count(g_argInputFile))
|
||||||
m_compiler->setRemappings(m_remappings);
|
m_compiler->setRemappings(m_remappings);
|
||||||
|
|
||||||
|
@ -79,7 +79,6 @@ private:
|
|||||||
void handleABI(std::string const& _contract);
|
void handleABI(std::string const& _contract);
|
||||||
void handleNatspec(bool _natspecDev, std::string const& _contract);
|
void handleNatspec(bool _natspecDev, std::string const& _contract);
|
||||||
void handleGasEstimation(std::string const& _contract);
|
void handleGasEstimation(std::string const& _contract);
|
||||||
void handleFormal();
|
|
||||||
void handleStorageLayout(std::string const& _contract);
|
void handleStorageLayout(std::string const& _contract);
|
||||||
|
|
||||||
/// Fills @a m_sourceCodes initially and @a m_redirects.
|
/// Fills @a m_sourceCodes initially and @a m_redirects.
|
||||||
@ -134,6 +133,8 @@ private:
|
|||||||
RevertStrings m_revertStrings = RevertStrings::Default;
|
RevertStrings m_revertStrings = RevertStrings::Default;
|
||||||
/// Chosen hash method for the bytecode metadata.
|
/// Chosen hash method for the bytecode metadata.
|
||||||
CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS;
|
CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS;
|
||||||
|
/// Chosen model checker engine.
|
||||||
|
ModelCheckerEngine m_modelCheckerEngine = ModelCheckerEngine::All();
|
||||||
/// Whether or not to colorize diagnostics output.
|
/// Whether or not to colorize diagnostics output.
|
||||||
bool m_coloredOutput = true;
|
bool m_coloredOutput = true;
|
||||||
/// Whether or not to output error IDs.
|
/// Whether or not to output error IDs.
|
||||||
|
1
test/cmdlineTests/model_checker_engine_all/args
Normal file
1
test/cmdlineTests/model_checker_engine_all/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--model-checker-engine all
|
13
test/cmdlineTests/model_checker_engine_all/err
Normal file
13
test/cmdlineTests/model_checker_engine_all/err
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Warning: CHC: Assertion violation happens here.
|
||||||
|
--> model_checker_engine_all/input.sol:6:3:
|
||||||
|
|
|
||||||
|
6 | assert(x > 0);
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
Note: Counterexample:
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
|
||||||
|
Transaction trace:
|
||||||
|
constructor()
|
||||||
|
f(0)
|
8
test/cmdlineTests/model_checker_engine_all/input.sol
Normal file
8
test/cmdlineTests/model_checker_engine_all/input.sol
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract test {
|
||||||
|
function f(uint x) public pure {
|
||||||
|
assert(x > 0);
|
||||||
|
}
|
||||||
|
}
|
1
test/cmdlineTests/model_checker_engine_bmc/args
Normal file
1
test/cmdlineTests/model_checker_engine_bmc/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--model-checker-engine bmc
|
10
test/cmdlineTests/model_checker_engine_bmc/err
Normal file
10
test/cmdlineTests/model_checker_engine_bmc/err
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Warning: BMC: Assertion violation happens here.
|
||||||
|
--> model_checker_engine_bmc/input.sol:6:3:
|
||||||
|
|
|
||||||
|
6 | assert(x > 0);
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
Note: Counterexample:
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
Note: Callstack:
|
||||||
|
Note:
|
8
test/cmdlineTests/model_checker_engine_bmc/input.sol
Normal file
8
test/cmdlineTests/model_checker_engine_bmc/input.sol
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract test {
|
||||||
|
function f(uint x) public pure {
|
||||||
|
assert(x > 0);
|
||||||
|
}
|
||||||
|
}
|
1
test/cmdlineTests/model_checker_engine_chc/args
Normal file
1
test/cmdlineTests/model_checker_engine_chc/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--model-checker-engine chc
|
13
test/cmdlineTests/model_checker_engine_chc/err
Normal file
13
test/cmdlineTests/model_checker_engine_chc/err
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Warning: CHC: Assertion violation happens here.
|
||||||
|
--> model_checker_engine_chc/input.sol:6:3:
|
||||||
|
|
|
||||||
|
6 | assert(x > 0);
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
Note: Counterexample:
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
|
||||||
|
Transaction trace:
|
||||||
|
constructor()
|
||||||
|
f(0)
|
8
test/cmdlineTests/model_checker_engine_chc/input.sol
Normal file
8
test/cmdlineTests/model_checker_engine_chc/input.sol
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract test {
|
||||||
|
function f(uint x) public pure {
|
||||||
|
assert(x > 0);
|
||||||
|
}
|
||||||
|
}
|
1
test/cmdlineTests/model_checker_engine_none/args
Normal file
1
test/cmdlineTests/model_checker_engine_none/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--model-checker-engine none
|
5
test/cmdlineTests/model_checker_engine_none/err
Normal file
5
test/cmdlineTests/model_checker_engine_none/err
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
|
||||||
|
--> model_checker_engine_none/input.sol
|
||||||
|
|
||||||
|
Warning: Source file does not specify required compiler version!
|
||||||
|
--> model_checker_engine_none/input.sol
|
9
test/cmdlineTests/model_checker_engine_none/input.sol
Normal file
9
test/cmdlineTests/model_checker_engine_none/input.sol
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Removed to yield a warning, otherwise CI test fails with the expectation
|
||||||
|
// "no output requested"
|
||||||
|
//pragma solidity >=0.0;
|
||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract test {
|
||||||
|
function f(uint x) public pure {
|
||||||
|
assert(x > 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources":
|
||||||
|
{
|
||||||
|
"A":
|
||||||
|
{
|
||||||
|
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\npragma experimental SMTChecker;\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings":
|
||||||
|
{
|
||||||
|
"modelCheckerEngine": "all"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"A:4:47: Warning: CHC: Assertion violation happens here.
|
||||||
|
contract C { function f(uint x) public pure { assert(x > 0); } }
|
||||||
|
^-----------^
|
||||||
|
Counterexample:
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
|
||||||
|
Transaction trace:
|
||||||
|
constructor()
|
||||||
|
f(0)
|
||||||
|
","message":"CHC: Assertion violation happens here.","secondarySourceLocations":[{"message":"Counterexample:
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
|
||||||
|
Transaction trace:
|
||||||
|
constructor()
|
||||||
|
f(0)"}],"severity":"warning","sourceLocation":{"end":150,"file":"A","start":137},"type":"Warning"}],"sources":{"A":{"id":0}}}
|
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources":
|
||||||
|
{
|
||||||
|
"A":
|
||||||
|
{
|
||||||
|
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\npragma experimental SMTChecker;\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings":
|
||||||
|
{
|
||||||
|
"modelCheckerEngine": "bmc"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
{"auxiliaryInputRequested":{"smtlib2queries":{"0x4ca2adc24a17cd524cf3113f3b2cddff216f428f804e884cf76d27dd3e72cd68":"(set-option :produce-models true)
|
||||||
|
(set-logic ALL)
|
||||||
|
(declare-fun |error_0| () Int)
|
||||||
|
(declare-fun |this_0| () Int)
|
||||||
|
(declare-datatypes ((|state_type| 0)) (((|state_type| (|balances| (Array Int Int))))))
|
||||||
|
(declare-fun |state_0| () |state_type|)
|
||||||
|
(declare-datatypes ((|bytes_tuple| 0)) (((|bytes_tuple| (|bytes_tuple_accessor_array| (Array Int Int)) (|bytes_tuple_accessor_length| Int)))))
|
||||||
|
(declare-datatypes ((|tx_type| 0)) (((|tx_type| (|block.coinbase| Int) (|block.difficulty| Int) (|block.gaslimit| Int) (|block.number| Int) (|block.timestamp| Int) (|blockhash| (Array Int Int)) (|msg.data| |bytes_tuple|) (|msg.sender| Int) (|msg.sig| Int) (|msg.value| Int) (|tx.gasprice| Int) (|tx.origin| Int)))))
|
||||||
|
(declare-fun |tx_0| () |tx_type|)
|
||||||
|
(declare-fun |x_4_0| () Int)
|
||||||
|
(declare-fun |expr_8_0| () Int)
|
||||||
|
(declare-fun |expr_9_0| () Int)
|
||||||
|
(declare-fun |expr_10_1| () Bool)
|
||||||
|
|
||||||
|
(assert (and (and true (and (= expr_10_1 (> expr_8_0 expr_9_0)) (and (= expr_9_0 0) (and (= expr_8_0 x_4_0) (and (and (>= x_4_0 0) (<= x_4_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) true))))) (not expr_10_1)))
|
||||||
|
(declare-const |EVALEXPR_0| Int)
|
||||||
|
(assert (= |EVALEXPR_0| x_4_0))
|
||||||
|
(check-sat)
|
||||||
|
(get-value (|EVALEXPR_0| ))
|
||||||
|
"}},"errors":[{"component":"general","errorCode":"4661","formattedMessage":"A:4:47: Warning: BMC: Assertion violation happens here.
|
||||||
|
contract C { function f(uint x) public pure { assert(x > 0); } }
|
||||||
|
^-----------^
|
||||||
|
Counterexample:
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
Callstack:
|
||||||
|
|
||||||
|
","message":"BMC: Assertion violation happens here.","secondarySourceLocations":[{"message":"Counterexample:
|
||||||
|
x = 0
|
||||||
|
"},{"message":"Callstack:"},{"message":""}],"severity":"warning","sourceLocation":{"end":150,"file":"A","start":137},"type":"Warning"}],"sources":{"A":{"id":0}}}
|
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources":
|
||||||
|
{
|
||||||
|
"A":
|
||||||
|
{
|
||||||
|
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\npragma experimental SMTChecker;\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings":
|
||||||
|
{
|
||||||
|
"modelCheckerEngine": "chc"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
{"errors":[{"component":"general","errorCode":"6328","formattedMessage":"A:4:47: Warning: CHC: Assertion violation happens here.
|
||||||
|
contract C { function f(uint x) public pure { assert(x > 0); } }
|
||||||
|
^-----------^
|
||||||
|
Counterexample:
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
|
||||||
|
Transaction trace:
|
||||||
|
constructor()
|
||||||
|
f(0)
|
||||||
|
","message":"CHC: Assertion violation happens here.","secondarySourceLocations":[{"message":"Counterexample:
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
|
||||||
|
Transaction trace:
|
||||||
|
constructor()
|
||||||
|
f(0)"}],"severity":"warning","sourceLocation":{"end":150,"file":"A","start":137},"type":"Warning"}],"sources":{"A":{"id":0}}}
|
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"language": "Solidity",
|
||||||
|
"sources":
|
||||||
|
{
|
||||||
|
"A":
|
||||||
|
{
|
||||||
|
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.0;\npragma experimental SMTChecker;\ncontract C { function f(uint x) public pure { assert(x > 0); } }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings":
|
||||||
|
{
|
||||||
|
"modelCheckerEngine": "none"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
{"sources":{"A":{"id":0}}}
|
Loading…
Reference in New Issue
Block a user