Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 78d55e6

Browse files
author
Leonardo Alt
committed
[SMTChecker] Support check/unchecked
1 parent eb05826 commit 78d55e6

File tree

74 files changed

+460
-309
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+460
-309
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Language Features:
66
Compiler Features:
77
* Parser: Report meaningful error if parsing a version pragma failed.
88
* SMTChecker: Support ABI functions as uninterpreted functions.
9+
* SMTChecker: Use checked arithmetic by default and support ``unchecked`` blocks.
910

1011
Bugfixes:
1112
* Code Generator: Fix length check when decoding malformed error data in catch clause.

libsolidity/formal/BMC.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,7 @@ void BMC::endVisit(ContractDefinition const& _contract)
137137
inlineConstructorHierarchy(_contract);
138138
popCallStack();
139139
/// Check targets created by state variable initialization.
140-
smtutil::Expression constraints = m_context.assertions();
141-
checkVerificationTargets(constraints);
140+
checkVerificationTargets();
142141
m_verificationTargets.clear();
143142
}
144143

@@ -175,8 +174,7 @@ void BMC::endVisit(FunctionDefinition const& _function)
175174
{
176175
if (isRootFunction())
177176
{
178-
smtutil::Expression constraints = m_context.assertions();
179-
checkVerificationTargets(constraints);
177+
checkVerificationTargets();
180178
m_verificationTargets.clear();
181179
m_pathConditions.clear();
182180
}
@@ -534,6 +532,7 @@ pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation(
534532
Expression const& _expression
535533
)
536534
{
535+
// Unchecked does not disable div by 0 checks.
537536
if (_op == Token::Div || _op == Token::Mod)
538537
addVerificationTarget(
539538
VerificationTarget::Type::DivByZero,
@@ -543,6 +542,9 @@ pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation(
543542

544543
auto values = SMTEncoder::arithmeticOperation(_op, _left, _right, _commonType, _expression);
545544

545+
if (!m_checked)
546+
return values;
547+
546548
auto const* intType = dynamic_cast<IntegerType const*>(_commonType);
547549
if (!intType)
548550
intType = TypeProvider::uint256();
@@ -625,28 +627,28 @@ pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions()
625627

626628
/// Verification targets.
627629

628-
void BMC::checkVerificationTargets(smtutil::Expression const& _constraints)
630+
void BMC::checkVerificationTargets()
629631
{
630632
for (auto& target: m_verificationTargets)
631-
checkVerificationTarget(target, _constraints);
633+
checkVerificationTarget(target);
632634
}
633635

634-
void BMC::checkVerificationTarget(BMCVerificationTarget& _target, smtutil::Expression const& _constraints)
636+
void BMC::checkVerificationTarget(BMCVerificationTarget& _target)
635637
{
636638
switch (_target.type)
637639
{
638640
case VerificationTarget::Type::ConstantCondition:
639641
checkConstantCondition(_target);
640642
break;
641643
case VerificationTarget::Type::Underflow:
642-
checkUnderflow(_target, _constraints);
644+
checkUnderflow(_target);
643645
break;
644646
case VerificationTarget::Type::Overflow:
645-
checkOverflow(_target, _constraints);
647+
checkOverflow(_target);
646648
break;
647649
case VerificationTarget::Type::UnderOverflow:
648-
checkUnderflow(_target, _constraints);
649-
checkOverflow(_target, _constraints);
650+
checkUnderflow(_target);
651+
checkOverflow(_target);
650652
break;
651653
case VerificationTarget::Type::DivByZero:
652654
checkDivByZero(_target);
@@ -672,7 +674,7 @@ void BMC::checkConstantCondition(BMCVerificationTarget& _target)
672674
);
673675
}
674676

675-
void BMC::checkUnderflow(BMCVerificationTarget& _target, smtutil::Expression const& _constraints)
677+
void BMC::checkUnderflow(BMCVerificationTarget& _target)
676678
{
677679
solAssert(
678680
_target.type == VerificationTarget::Type::Underflow ||
@@ -693,7 +695,7 @@ void BMC::checkUnderflow(BMCVerificationTarget& _target, smtutil::Expression con
693695
intType = TypeProvider::uint256();
694696

695697
checkCondition(
696-
_target.constraints && _constraints && _target.value < smt::minValue(*intType),
698+
_target.constraints && _target.value < smt::minValue(*intType),
697699
_target.callStack,
698700
_target.modelExpressions,
699701
_target.expression->location(),
@@ -705,7 +707,7 @@ void BMC::checkUnderflow(BMCVerificationTarget& _target, smtutil::Expression con
705707
);
706708
}
707709

708-
void BMC::checkOverflow(BMCVerificationTarget& _target, smtutil::Expression const& _constraints)
710+
void BMC::checkOverflow(BMCVerificationTarget& _target)
709711
{
710712
solAssert(
711713
_target.type == VerificationTarget::Type::Overflow ||
@@ -726,7 +728,7 @@ void BMC::checkOverflow(BMCVerificationTarget& _target, smtutil::Expression cons
726728
intType = TypeProvider::uint256();
727729

728730
checkCondition(
729-
_target.constraints && _constraints && _target.value > smt::maxValue(*intType),
731+
_target.constraints && _target.value > smt::maxValue(*intType),
730732
_target.callStack,
731733
_target.modelExpressions,
732734
_target.expression->location(),

libsolidity/formal/BMC.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ class BMC: public SMTEncoder
130130
std::pair<std::vector<smtutil::Expression>, std::vector<std::string>> modelExpressions;
131131
};
132132

133-
void checkVerificationTargets(smtutil::Expression const& _constraints);
134-
void checkVerificationTarget(BMCVerificationTarget& _target, smtutil::Expression const& _constraints = smtutil::Expression(true));
133+
void checkVerificationTargets();
134+
void checkVerificationTarget(BMCVerificationTarget& _target);
135135
void checkConstantCondition(BMCVerificationTarget& _target);
136-
void checkUnderflow(BMCVerificationTarget& _target, smtutil::Expression const& _constraints);
137-
void checkOverflow(BMCVerificationTarget& _target, smtutil::Expression const& _constraints);
136+
void checkUnderflow(BMCVerificationTarget& _target);
137+
void checkOverflow(BMCVerificationTarget& _target);
138138
void checkDivByZero(BMCVerificationTarget& _target);
139139
void checkBalance(BMCVerificationTarget& _target);
140140
void checkAssert(BMCVerificationTarget& _target);

libsolidity/formal/CHC.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,11 +732,15 @@ pair<smtutil::Expression, smtutil::Expression> CHC::arithmeticOperation(
732732
frontend::Expression const& _expression
733733
)
734734
{
735+
// Unchecked does not disable div by 0 checks.
735736
if (_op == Token::Mod || _op == Token::Div)
736737
verificationTargetEncountered(&_expression, VerificationTarget::Type::DivByZero, _right == 0);
737738

738739
auto values = SMTEncoder::arithmeticOperation(_op, _left, _right, _commonType, _expression);
739740

741+
if (!m_checked)
742+
return values;
743+
740744
IntegerType const* intType = nullptr;
741745
if (auto const* type = dynamic_cast<IntegerType const*>(_commonType))
742746
intType = type;

libsolidity/formal/SMTEncoder.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,25 @@ void SMTEncoder::endVisit(FunctionDefinition const&)
283283
m_context.popSolver();
284284
}
285285

286+
bool SMTEncoder::visit(Block const& _block)
287+
{
288+
if (_block.unchecked())
289+
{
290+
solAssert(m_checked, "");
291+
m_checked = false;
292+
}
293+
return true;
294+
}
295+
296+
void SMTEncoder::endVisit(Block const& _block)
297+
{
298+
if (_block.unchecked())
299+
{
300+
solAssert(!m_checked, "");
301+
m_checked = true;
302+
}
303+
}
304+
286305
bool SMTEncoder::visit(InlineAssembly const& _inlineAsm)
287306
{
288307
m_errorReporter.warning(
@@ -745,6 +764,7 @@ void SMTEncoder::initContract(ContractDefinition const& _contract)
745764
createStateVariables(_contract);
746765
clearIndices(m_currentContract, nullptr);
747766
m_variableUsage.setCurrentContract(_contract);
767+
m_checked = true;
748768
}
749769

750770
void SMTEncoder::initFunction(FunctionDefinition const& _function)
@@ -759,6 +779,7 @@ void SMTEncoder::initFunction(FunctionDefinition const& _function)
759779
createLocalVariables(_function);
760780
m_arrayAssignmentHappened = false;
761781
clearIndices(m_currentContract, &_function);
782+
m_checked = true;
762783
}
763784

764785
void SMTEncoder::visitAssert(FunctionCall const& _funCall)
@@ -1762,6 +1783,9 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
17621783
}
17631784
}();
17641785

1786+
if (m_checked)
1787+
return {valueUnbounded, valueUnbounded};
1788+
17651789
if (_op == Token::Div || _op == Token::Mod)
17661790
{
17671791
// mod and unsigned division never underflow/overflow
@@ -2385,6 +2409,16 @@ void SMTEncoder::defineExpr(Expression const& _e, smtutil::Expression _value)
23852409
createExpr(_e);
23862410
solAssert(_value.sort->kind != smtutil::Kind::Function, "Equality operator applied to type that is not fully supported");
23872411
m_context.addAssertion(expr(_e) == _value);
2412+
2413+
if (
2414+
auto type = _e.annotation().type;
2415+
m_checked && smt::isNumber(*type)
2416+
)
2417+
m_context.addAssertion(smtutil::Expression::implies(
2418+
currentPathConditions(),
2419+
smt::symbolicUnknownConstraints(expr(_e), type)
2420+
));
2421+
23882422
}
23892423

23902424
void SMTEncoder::popPathCondition()

libsolidity/formal/SMTEncoder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ class SMTEncoder: public ASTConstVisitor
103103
bool visit(ModifierDefinition const& _node) override;
104104
bool visit(FunctionDefinition const& _node) override;
105105
void endVisit(FunctionDefinition const& _node) override;
106+
bool visit(Block const& _node) override;
107+
void endVisit(Block const& _node) override;
106108
bool visit(PlaceholderStatement const& _node) override;
107109
bool visit(IfStatement const&) override { return false; }
108110
bool visit(WhileStatement const&) override { return false; }
@@ -358,6 +360,11 @@ class SMTEncoder: public ASTConstVisitor
358360
/// Used to retrieve models.
359361
std::set<Expression const*> m_uninterpretedTerms;
360362
std::vector<smtutil::Expression> m_pathConditions;
363+
364+
/// Whether the currently visited block uses checked
365+
/// or unchecked arithmetic.
366+
bool m_checked = true;
367+
361368
/// Local SMTEncoder ErrorReporter.
362369
/// This is necessary to show the "No SMT solver available"
363370
/// warning before the others in case it's needed.

test/cmdlineTests/standard_model_checker_engine_bmc/output.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{"auxiliaryInputRequested":{"smtlib2queries":{"0xfb59e2e8177462af35c799138353d20a1d92e6078fa64073c48e01b66c94e568":"(set-option :produce-models true)
1+
{"auxiliaryInputRequested":{"smtlib2queries":{"0x058094a9af015b518e634e27c9b42140d8b77dd0f915986a1e2fbed694cdb7de":"(set-option :produce-models true)
22
(set-logic ALL)
33
(declare-fun |error_0| () Int)
44
(declare-fun |this_0| () Int)
@@ -17,7 +17,7 @@
1717
(declare-fun |expr_9_0| () Int)
1818
(declare-fun |expr_10_1| () Bool)
1919

20-
(assert (and (and (and true true) (and (= expr_10_1 (> expr_8_0 expr_9_0)) (and (= expr_9_0 0) (and (= expr_8_0 x_4_0) (and (and (>= x_4_0 0) (<= x_4_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975)) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4)) true)))))) (not expr_10_1)))
20+
(assert (and (and (and true true) (and (= expr_10_1 (> expr_8_0 expr_9_0)) (and (implies (and true true) true) (and (= expr_9_0 0) (and (implies (and true true) (and (>= expr_8_0 0) (<= expr_8_0 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (= expr_8_0 x_4_0) (and (and (>= x_4_0 0) (<= x_4_0 115792089237316195423570985008687907853269984665640564039457584007913129639935)) (and (and (and (and (and (and (and (and (and (and (and (and (and (and (and (>= (|block.coinbase| tx_0) 0) (<= (|block.coinbase| tx_0) 1461501637330902918203684832716283019655932542975)) (and (>= (|block.chainid| tx_0) 0) (<= (|block.chainid| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.difficulty| tx_0) 0) (<= (|block.difficulty| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.gaslimit| tx_0) 0) (<= (|block.gaslimit| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.number| tx_0) 0) (<= (|block.number| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|block.timestamp| tx_0) 0) (<= (|block.timestamp| tx_0) 115792089237316195423570985008687907853269984665640564039457584007913129639935))) (and (>= (|msg.sender| tx_0) 0) (<= (|msg.sender| tx_0) 1461501637330902918203684832716283019655932542975))) (and (>= (|tx.origin| tx_0) 0) (<= (|tx.origin| tx_0) 1461501637330902918203684832716283019655932542975))) (= (|msg.sig| tx_0) 3017696395)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 0) 179)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 1) 222)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 2) 100)) (= (select (|bytes_tuple_accessor_array| (|msg.data| tx_0)) 3) 139)) (>= (|bytes_tuple_accessor_length| (|msg.data| tx_0)) 4)) true)))))))) (not expr_10_1)))
2121
(declare-const |EVALEXPR_0| Int)
2222
(assert (= |EVALEXPR_0| x_4_0))
2323
(check-sat)

0 commit comments

Comments
 (0)