Basic support to free constants

This commit is contained in:
Leonardo Alt 2021-04-07 18:53:56 +02:00
parent 6ae82fcec2
commit 095d337140
7 changed files with 39 additions and 48 deletions

View File

@ -61,8 +61,6 @@ BMC::BMC(
void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>> _solvedTargets)
{
/// This is currently used to abort analysis of SourceUnits
/// containing file level functions or constants.
if (SMTEncoder::analyze(_source))
{
m_solvedTargets = move(_solvedTargets);
@ -70,6 +68,7 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
m_context.clear();
m_context.setAssertionAccumulation(true);
m_variableUsage.setFunctionInlining(shouldInlineFunctionCall);
createFreeConstants(sourceDependencies(_source));
_source.accept(*this);
}

View File

@ -76,17 +76,13 @@ CHC::CHC(
void CHC::analyze(SourceUnit const& _source)
{
/// This is currently used to abort analysis of SourceUnits
/// containing file level functions or constants.
if (SMTEncoder::analyze(_source))
{
resetSourceAnalysis();
set<SourceUnit const*, ASTNode::CompareByID> sources;
sources.insert(&_source);
for (auto const& source: _source.referencedSourceUnits(true))
sources.insert(source);
auto sources = sourceDependencies(_source);
collectFreeFunctions(sources);
createFreeConstants(sources);
for (auto const* source: sources)
defineInterfacesAndSummaries(*source);
for (auto const* source: sources)
@ -1422,7 +1418,8 @@ void CHC::verificationTargetEncountered(
if (!m_settings.targets.has(_type))
return;
solAssert(m_currentContract || m_currentFunction, "");
if (!(m_currentContract || m_currentFunction))
return;
bool scopeIsFunction = m_currentFunction && !m_currentFunction->isConstructor();
auto errorId = newErrorId();

View File

@ -51,27 +51,6 @@ SMTEncoder::SMTEncoder(smt::EncodingContext& _context):
bool SMTEncoder::analyze(SourceUnit const& _source)
{
set<SourceUnit const*, smt::EncodingContext::IdCompare> sources;
sources.insert(&_source);
for (auto const& source: _source.referencedSourceUnits(true))
sources.insert(source);
bool analysis = true;
for (auto source: sources)
for (auto node: source->nodes())
if (auto var = dynamic_pointer_cast<VariableDeclaration>(node))
{
m_errorReporter.warning(
8195_error,
var->location(),
"Model checker analysis was not possible because file level constants are not supported."
);
analysis = false;
}
if (!analysis)
return false;
state().prepareForSourceUnit(_source);
return true;
@ -437,14 +416,9 @@ void SMTEncoder::endVisit(TupleExpression const& _tuple)
auto values = applyMap(_tuple.components(), [this](auto const& component) -> optional<smtutil::Expression> {
if (component)
{
if (auto varDecl = identifierToVariable(*component))
return currentValue(*varDecl);
else
{
if (!m_context.knownExpression(*component))
if (!m_context.knownExpression(*component))
createExpr(*component);
return expr(*component);
}
return expr(*component);
}
return {};
});
@ -1395,6 +1369,9 @@ void SMTEncoder::endVisit(IndexAccess const& _indexAccess)
auto varDecl = identifierToVariable(*id);
solAssert(varDecl, "");
array = m_context.variable(*varDecl);
if (varDecl && varDecl->isConstant())
m_context.addAssertion(currentValue(*varDecl) == expr(*id));
}
else
{
@ -2599,6 +2576,7 @@ VariableDeclaration const* SMTEncoder::identifierToVariable(Expression const& _e
solAssert(m_context.knownVariable(*varDecl), "");
return varDecl;
}
return nullptr;
}
@ -2913,6 +2891,15 @@ set<FunctionCall const*> SMTEncoder::collectABICalls(ASTNode const* _node)
return ABIFunctions(_node).abiCalls;
}
set<SourceUnit const*, ASTNode::CompareByID> SMTEncoder::sourceDependencies(SourceUnit const& _source)
{
set<SourceUnit const*, ASTNode::CompareByID> sources;
sources.insert(&_source);
for (auto const& source: _source.referencedSourceUnits(true))
sources.insert(source);
return sources;
}
void SMTEncoder::createReturnedExpressions(FunctionCall const& _funCall, ContractDefinition const* _contextContract)
{
auto funDef = functionCallToDefinition(_funCall, currentScopeContract(), _contextContract);
@ -2978,6 +2965,14 @@ void SMTEncoder::collectFreeFunctions(set<SourceUnit const*, ASTNode::CompareByI
}
}
void SMTEncoder::createFreeConstants(set<SourceUnit const*, ASTNode::CompareByID> const& _sources)
{
for (auto source: _sources)
for (auto node: source->nodes())
if (auto var = dynamic_cast<VariableDeclaration const*>(node.get()))
createVariable(*var);
}
smt::SymbolicState& SMTEncoder::state()
{
return m_context.state();

View File

@ -112,6 +112,10 @@ public:
static std::set<FunctionCall const*> collectABICalls(ASTNode const* _node);
/// @returns all the sources that @param _source depends on,
/// including itself.
static std::set<SourceUnit const*, ASTNode::CompareByID> sourceDependencies(SourceUnit const& _source);
protected:
// TODO: Check that we do not have concurrent reads and writes to a variable,
// because the order of expression evaluation is undefined
@ -373,6 +377,8 @@ protected:
/// and internal library functions in m_freeFunctions.
void collectFreeFunctions(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources);
std::set<FunctionDefinition const*, ASTNode::CompareByID> const& allFreeFunctions() const { return m_freeFunctions; }
/// Create symbolic variables for the free constants in all @param _sources.
void createFreeConstants(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources);
/// @returns a note to be added to warnings.
std::string extraComment();

View File

@ -7,5 +7,4 @@ contract C {
// ====
// SMTEngine: all
// ----
// Warning 8195: (0-20): Model checker analysis was not possible because file level constants are not supported.
// Warning 8195: (0-20): Model checker analysis was not possible because file level constants are not supported.
// Warning 4984: (125-130): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\nx = 115792089237316195423570985008687907853269984665640564039457584007913129639894\n = 0\n\nTransaction trace:\nC.constructor()\nC.f(115792089237316195423570985008687907853269984665640564039457584007913129639894)

View File

@ -10,10 +10,4 @@ contract C {
// ====
// SMTEngine: all
// ----
// Warning 2018: (188-278): Function state mutability can be restricted to pure
// Warning 8195: (0-23): Model checker analysis was not possible because file level constants are not supported.
// Warning 8195: (79-133): Model checker analysis was not possible because file level constants are not supported.
// Warning 8195: (135-172): Model checker analysis was not possible because file level constants are not supported.
// Warning 8195: (0-23): Model checker analysis was not possible because file level constants are not supported.
// Warning 8195: (79-133): Model checker analysis was not possible because file level constants are not supported.
// Warning 8195: (135-172): Model checker analysis was not possible because file level constants are not supported.
// Warning 2018: (220-310): Function state mutability can be restricted to pure

View File

@ -12,5 +12,6 @@ function fun(uint[] calldata _x, uint[] storage _y) view returns (uint, uint[]
// ====
// SMTEngine: all
// ----
// Warning 8195: (32-52): Model checker analysis was not possible because file level constants are not supported.
// Warning 8195: (32-52): Model checker analysis was not possible because file level constants are not supported.
// Warning 4984: (222-234): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\ndata = []\nx = 1\n = 0\n = 0\na = 0\n\nTransaction trace:\nC.constructor()\nState: data = []\nC.f(1, input)\n ::fun(_x, []) -- internal call
// Warning 4984: (222-238): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\ndata = []\nx = 115792089237316195423570985008687907853269984665640564039457584007913129632175\n = 0\n = 0\na = 0\n\nTransaction trace:\nC.constructor()\nState: data = []\nC.f(115792089237316195423570985008687907853269984665640564039457584007913129632175, input)\n ::fun(_x, []) -- internal call
// Warning 6368: (347-352): CHC: Out of bounds access happens here.\nCounterexample:\ndata = []\nx = 0\ninput = [5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 14, 5, 5, 5, 5, 5, 19, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]\n = 0\n = 0\n\nTransaction trace:\nC.constructor()\nState: data = []\nC.f(0, [5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 14, 5, 5, 5, 5, 5, 19, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])\n ::fun([5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 14, 5, 5, 5, 5, 5, 19, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], []) -- internal call