Abstract function smtchecker natspec

This commit is contained in:
Leonardo Alt
2021-05-11 15:30:19 +02:00
committed by Leo Alt
parent eb99177506
commit 4b2ccf2f37
4 changed files with 82 additions and 11 deletions
+57 -7
View File
@@ -219,9 +219,20 @@ bool CHC::visit(FunctionDefinition const& _function)
if (!m_currentContract)
return false;
if (!_function.isImplemented())
if (
!_function.isImplemented() ||
abstractAsNondet(_function)
)
{
addRule(summary(_function), "summary_function_" + to_string(_function.id()));
smtutil::Expression conj(true);
if (
_function.stateMutability() == StateMutability::Pure ||
_function.stateMutability() == StateMutability::View
)
conj = conj && currentEqualInitialVarsConstraints(stateVariablesIncludingInheritedAndPrivate(_function));
conj = conj && errorFlag().currentValue() == 0;
addRule(smtutil::Expression::implies(conj, summary(_function)), "summary_function_" + to_string(_function.id()));
return false;
}
@@ -262,7 +273,10 @@ void CHC::endVisit(FunctionDefinition const& _function)
if (!m_currentContract)
return;
if (!_function.isImplemented())
if (
!_function.isImplemented() ||
abstractAsNondet(_function)
)
return;
solAssert(m_currentFunction && m_currentContract, "");
@@ -1001,6 +1015,37 @@ set<unsigned> CHC::transactionVerificationTargetsIds(ASTNode const* _txRoot)
return verificationTargetsIds;
}
optional<CHC::CHCNatspecOption> CHC::natspecOptionFromString(string const& _option)
{
static map<string, CHCNatspecOption> options{
{"abstract-function-nondet", CHCNatspecOption::AbstractFunctionNondet}
};
if (options.count(_option))
return options.at(_option);
return {};
}
set<CHC::CHCNatspecOption> CHC::smtNatspecTags(FunctionDefinition const& _function)
{
set<CHC::CHCNatspecOption> options;
string smtStr = "custom:smtchecker";
for (auto const& [tag, value]: _function.annotation().docTags)
if (tag == smtStr)
{
string const& content = value.content;
if (auto option = natspecOptionFromString(content))
options.insert(*option);
else
m_errorReporter.warning(3130_error, _function.location(), "Unknown option for \"" + smtStr + "\": \"" + content + "\"");
}
return options;
}
bool CHC::abstractAsNondet(FunctionDefinition const& _function)
{
return smtNatspecTags(_function).count(CHCNatspecOption::AbstractFunctionNondet);
}
SortPointer CHC::sort(FunctionDefinition const& _function)
{
return functionBodySort(_function, m_currentContract, state());
@@ -1213,13 +1258,11 @@ smtutil::Expression CHC::initialConstraints(ContractDefinition const& _contract,
{
smtutil::Expression conj = state().state() == state().state(0);
conj = conj && errorFlag().currentValue() == 0;
for (auto var: stateVariablesIncludingInheritedAndPrivate(_contract))
conj = conj && m_context.variable(*var)->valueAtIndex(0) == currentValue(*var);
conj = conj && currentEqualInitialVarsConstraints(stateVariablesIncludingInheritedAndPrivate(_contract));
FunctionDefinition const* function = _function ? _function : _contract.constructor();
if (function)
for (auto var: function->parameters())
conj = conj && m_context.variable(*var)->valueAtIndex(0) == currentValue(*var);
conj = conj && currentEqualInitialVarsConstraints(applyMap(function->parameters(), [](auto&& _var) -> VariableDeclaration const* { return _var.get(); }));
return conj;
}
@@ -1254,6 +1297,13 @@ vector<smtutil::Expression> CHC::currentStateVariables(ContractDefinition const&
return applyMap(SMTEncoder::stateVariablesIncludingInheritedAndPrivate(_contract), [this](auto _var) { return currentValue(*_var); });
}
smtutil::Expression CHC::currentEqualInitialVarsConstraints(vector<VariableDeclaration const*> const& _vars) const
{
return fold(_vars, smtutil::Expression(true), [this](auto&& _conj, auto _var) {
return move(_conj) && currentValue(*_var) == m_context.variable(*_var)->valueAtIndex(0);
});
}
string CHC::predicateName(ASTNode const* _node, ContractDefinition const* _contract)
{
string prefix;