Skip to content

Commit d9083dc

Browse files
committed
SMTChecker: Loop conditions should be analyzed as in loop context in BMC
Value of loop condition can change between iterations of the loop. Therefore, BMC should be in the "inside loop" state when analyzing loop conditions.
1 parent 880b61b commit d9083dc

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Compiler Features:
88

99

1010
Bugfixes:
11+
* SMTChecker: Do not consider loop conditions as constant-condition verification target as this could cause incorrect reports and internal compiler errors.
1112
* SMTChecker: Fix incorrect analysis when only a subset of contracts is selected with `--model-checker-contracts`.
1213
* SMTChecker: Fix internal compiler error when string literal is used to initialize user-defined type based on fixed bytes.
1314

libsolidity/formal/BMC.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,9 @@ bool BMC::visit(WhileStatement const& _node)
363363
{
364364
//after loop iterations are done, we check the loop condition last final time
365365
auto indices = copyVariableIndices();
366+
m_loopCheckpoints.emplace();
366367
_node.condition().accept(*this);
368+
m_loopCheckpoints.pop();
367369
loopCondition = expr(_node.condition());
368370
// assert that the loop is complete
369371
m_context.addAssertion(!loopCondition || broke || !loopConditionOnPreviousIterations);
@@ -391,13 +393,13 @@ bool BMC::visit(ForStatement const& _node)
391393
for (unsigned int i = 0; i < bmcLoopIterations; ++i)
392394
{
393395
auto indicesBefore = copyVariableIndices();
396+
m_loopCheckpoints.emplace();
394397
if (_node.condition())
395398
{
396399
_node.condition()->accept(*this);
397400
// values in loop condition might change during loop iteration
398401
forCondition = expr(*_node.condition());
399402
}
400-
m_loopCheckpoints.emplace();
401403
auto indicesAfterCondition = copyVariableIndices();
402404

403405
pushPathCondition(forCondition);
@@ -443,8 +445,10 @@ bool BMC::visit(ForStatement const& _node)
443445
auto indices = copyVariableIndices();
444446
if (_node.condition())
445447
{
448+
m_loopCheckpoints.emplace();
446449
_node.condition()->accept(*this);
447450
forCondition = expr(*_node.condition());
451+
m_loopCheckpoints.pop();
448452
}
449453
// assert that the loop is complete
450454
m_context.addAssertion(!forCondition || broke || !forConditionOnPreviousIterations);
@@ -932,9 +936,9 @@ void BMC::checkVerificationTarget(BMCVerificationTarget& _target)
932936
checkAssert(_target);
933937
break;
934938
case VerificationTargetType::ConstantCondition:
935-
solAssert(false, "Checks for constant condition are handled separately");
939+
smtAssert(false, "Checks for constant condition are handled separately");
936940
default:
937-
solAssert(false, "");
941+
smtAssert(false);
938942
}
939943
}
940944

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
contract Test {
2+
function loop() public pure {
3+
for (uint k = 0; (k == 0 ? true : false); k++) {
4+
}
5+
}
6+
}
7+
// ====
8+
// SMTEngine: bmc
9+
// SMTTargets: constantCondition
10+
// ----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
contract Test {
2+
function loop() public pure {
3+
uint k = 0;
4+
while (k == 0 ? true : false) {
5+
++k;
6+
}
7+
}
8+
}
9+
// ====
10+
// SMTEngine: bmc
11+
// SMTTargets: constantCondition
12+
// ----

0 commit comments

Comments
 (0)