[SMTChecker] Basic support for inline assembly using over-approximating analysis

This commit is contained in:
Martin Blicha
2021-01-26 16:20:50 +01:00
committed by Martin Blicha
parent 2f2d2224b1
commit 484e67815a
14 changed files with 261 additions and 5 deletions
+54 -1
View File
@@ -24,6 +24,9 @@
#include <libsolidity/analysis/ConstantEvaluator.h>
#include <libyul/AST.h>
#include <libyul/optimiser/Semantics.h>
#include <libsmtutil/SMTPortfolio.h>
#include <libsmtutil/Helpers.h>
@@ -304,10 +307,46 @@ void SMTEncoder::endVisit(Block const& _block)
bool SMTEncoder::visit(InlineAssembly const& _inlineAsm)
{
/// This is very similar to `yul::Assignments`, except I need to collect `Identifier`s and not just names as `YulString`s.
struct AssignedExternalsCollector: public yul::ASTWalker
{
AssignedExternalsCollector(InlineAssembly const& _inlineAsm): externalReferences(_inlineAsm.annotation().externalReferences)
{
this->operator()(_inlineAsm.operations());
}
map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> const& externalReferences;
set<VariableDeclaration const*> assignedVars;
using yul::ASTWalker::operator();
void operator()(yul::Assignment const& _assignment)
{
auto const& vars = _assignment.variableNames;
for (auto const& identifier: vars)
if (auto externalInfo = valueOrNullptr(externalReferences, &identifier))
if (auto varDecl = dynamic_cast<VariableDeclaration const*>(externalInfo->declaration))
assignedVars.insert(varDecl);
}
};
yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.dialect(), _inlineAsm.operations());
if (sideEffectsCollector.invalidatesMemory())
resetMemoryVariables();
if (sideEffectsCollector.invalidatesStorage())
resetStorageVariables();
auto assignedVars = AssignedExternalsCollector(_inlineAsm).assignedVars;
for (auto const* var: assignedVars)
{
solAssert(var, "");
solAssert(var->isLocalVariable(), "Non-local variable assigned in inlined assembly");
m_context.resetVariable(*var);
}
m_errorReporter.warning(
7737_error,
_inlineAsm.location(),
"Assertion checker does not support inline assembly."
"Inline assembly may cause SMTChecker to produce spurious warnings (false positives)."
);
return false;
}
@@ -2256,6 +2295,20 @@ void SMTEncoder::resetStateVariables()
m_context.resetVariables([&](VariableDeclaration const& _variable) { return _variable.isStateVariable(); });
}
void SMTEncoder::resetMemoryVariables()
{
m_context.resetVariables([&](VariableDeclaration const& _variable) {
return _variable.referenceLocation() == VariableDeclaration::Location::Memory;
});
}
void SMTEncoder::resetStorageVariables()
{
m_context.resetVariables([&](VariableDeclaration const& _variable) {
return _variable.referenceLocation() == VariableDeclaration::Location::Storage || _variable.isStateVariable();
});
}
void SMTEncoder::resetReferences(VariableDeclaration const& _varDecl)
{
m_context.resetVariables([&](VariableDeclaration const& _var) {
+2
View File
@@ -260,6 +260,8 @@ protected:
void initializeLocalVariables(FunctionDefinition const& _function);
void initializeFunctionCallParameters(CallableDeclaration const& _function, std::vector<smtutil::Expression> const& _callArgs);
void resetStateVariables();
void resetStorageVariables();
void resetMemoryVariables();
/// Resets all references/pointers that have the same type or have
/// a subexpression of the same type as _varDecl.
void resetReferences(VariableDeclaration const& _varDecl);