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:
@@ -836,7 +836,7 @@ void BMC::checkCondition(
|
||||
"\nNote that some information is erased after the execution of loops.\n"
|
||||
"You can re-introduce information using require().";
|
||||
if (m_externalFunctionCallHappened)
|
||||
extraComment+=
|
||||
extraComment +=
|
||||
"\nNote that external function calls are not inlined,"
|
||||
" even if the source code of the function is available."
|
||||
" This is due to the possibility that the actual called contract"
|
||||
@@ -854,7 +854,7 @@ void BMC::checkCondition(
|
||||
if (_callStack.size())
|
||||
{
|
||||
std::ostringstream modelMessage;
|
||||
modelMessage << "\nCounterexample:\n";
|
||||
modelMessage << "Counterexample:\n";
|
||||
solAssert(values.size() == expressionNames.size(), "");
|
||||
map<string, string> sortedModel;
|
||||
for (size_t i = 0; i < values.size(); ++i)
|
||||
@@ -863,6 +863,7 @@ void BMC::checkCondition(
|
||||
|
||||
for (auto const& eval: sortedModel)
|
||||
modelMessage << " " << eval.first << " = " << eval.second << "\n";
|
||||
|
||||
m_errorReporter.warning(
|
||||
_errorHappens,
|
||||
_location,
|
||||
|
||||
@@ -1298,7 +1298,7 @@ void CHC::checkAndReportTarget(
|
||||
_errorReporterId,
|
||||
_scope->location(),
|
||||
"CHC: " + _satMsg,
|
||||
SecondarySourceLocation().append("\nCounterexample:\n" + *cex, SourceLocation{})
|
||||
SecondarySourceLocation().append("Counterexample:\n" + *cex, SourceLocation{})
|
||||
);
|
||||
else
|
||||
m_outerErrorReporter.warning(
|
||||
@@ -1402,9 +1402,13 @@ optional<string> CHC::generateCounterexample(CHCSolverInterface::CexGraph const&
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto modelMsg = formatVariableModel(*stateVars, stateValues, ", ");
|
||||
/// We report the state after every tx in the trace except for the last, which is reported
|
||||
/// 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);
|
||||
path.emplace_back(txCex);
|
||||
|
||||
@@ -27,9 +27,11 @@ using namespace solidity::frontend;
|
||||
ModelChecker::ModelChecker(
|
||||
ErrorReporter& _errorReporter,
|
||||
map<h256, string> const& _smtlib2Responses,
|
||||
ModelCheckerEngine _engine,
|
||||
ReadCallback::Callback const& _smtCallback,
|
||||
smtutil::SMTSolverChoice _enabledSolvers
|
||||
):
|
||||
m_engine(_engine),
|
||||
m_context(),
|
||||
m_bmc(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))
|
||||
return;
|
||||
|
||||
m_chc.analyze(_source);
|
||||
if (m_engine.chc)
|
||||
m_chc.analyze(_source);
|
||||
|
||||
auto solvedTargets = m_chc.safeTargets();
|
||||
for (auto const& target: m_chc.unsafeTargets())
|
||||
solvedTargets[target.first] += target.second;
|
||||
|
||||
m_bmc.analyze(_source, solvedTargets);
|
||||
if (m_engine.bmc)
|
||||
m_bmc.analyze(_source, solvedTargets);
|
||||
}
|
||||
|
||||
vector<string> ModelChecker::unhandledQueries()
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <libsmtutil/SolverInterface.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace solidity::langutil
|
||||
{
|
||||
class ErrorReporter;
|
||||
@@ -41,6 +43,34 @@ struct SourceLocation;
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -49,6 +79,7 @@ public:
|
||||
ModelChecker(
|
||||
langutil::ErrorReporter& _errorReporter,
|
||||
std::map<solidity::util::h256, std::string> const& _smtlib2Responses,
|
||||
ModelCheckerEngine _engine = ModelCheckerEngine::All(),
|
||||
ReadCallback::Callback const& _smtCallback = ReadCallback::Callback(),
|
||||
smtutil::SMTSolverChoice _enabledSolvers = smtutil::SMTSolverChoice::All()
|
||||
);
|
||||
@@ -64,6 +95,8 @@ public:
|
||||
static smtutil::SMTSolverChoice availableSolvers();
|
||||
|
||||
private:
|
||||
ModelCheckerEngine m_engine;
|
||||
|
||||
/// Stores the context of the encoding.
|
||||
smt::EncodingContext m_context;
|
||||
|
||||
|
||||
@@ -2114,7 +2114,7 @@ SecondarySourceLocation SMTEncoder::callStackMessage(vector<CallStackEntry> cons
|
||||
{
|
||||
SecondarySourceLocation callStackLocation;
|
||||
solAssert(!_callStack.empty(), "");
|
||||
callStackLocation.append("Callstack: ", SourceLocation());
|
||||
callStackLocation.append("Callstack:", SourceLocation());
|
||||
for (auto const& call: _callStack | boost::adaptors::reversed)
|
||||
if (call.second)
|
||||
callStackLocation.append("", call.second->location());
|
||||
|
||||
Reference in New Issue
Block a user