Skip to content

Commit

Permalink
Remove UnderOverflow verification target for BMC engine
Browse files Browse the repository at this point in the history
  • Loading branch information
pgebal committed May 9, 2024
1 parent 7c94f53 commit 3c5aa3b
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 55 deletions.
2 changes: 1 addition & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Language Features:


Compiler Features:
* SMTChecker: Create balance check verification target for CHC engine.
* SMTChecker: Add balance check verification target for CHC engine.

Bugfixes:
* Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence.
Expand Down
75 changes: 23 additions & 52 deletions libsolidity/formal/BMC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,11 +569,18 @@ void BMC::endVisit(UnaryOperation const& _op)
return;

if (_op.getOperator() == Token::Sub && smt::isInteger(*_op.annotation().type))
{
addVerificationTarget(
VerificationTargetType::Underflow,
expr(_op),
&_op
);
addVerificationTarget(
VerificationTargetType::UnderOverflow,
VerificationTargetType::Overflow,
expr(_op),
&_op
);
}
}

void BMC::endVisit(BinaryOperation const& _op)
Expand Down Expand Up @@ -813,32 +820,29 @@ std::pair<smtutil::Expression, smtutil::Expression> BMC::arithmeticOperation(
if (_op == Token::Mod)
return values;

VerificationTargetType type;
// The order matters here:
// If _op is Div and intType is signed, we only care about overflow.
if (_op == Token::Div)
{
if (intType->isSigned())
// Signed division can only overflow.
type = VerificationTargetType::Overflow;
addVerificationTarget(VerificationTargetType::Overflow, values.second, &_expression);
else
// Unsigned division cannot underflow/overflow.
return values;
}
else if (intType->isSigned())
type = VerificationTargetType::UnderOverflow;
{
addVerificationTarget(VerificationTargetType::Overflow, values.second, &_expression);
addVerificationTarget(VerificationTargetType::Underflow, values.second, &_expression);
}
else if (_op == Token::Sub)
type = VerificationTargetType::Underflow;
addVerificationTarget(VerificationTargetType::Underflow, values.second, &_expression);
else if (_op == Token::Add || _op == Token::Mul)
type = VerificationTargetType::Overflow;
addVerificationTarget(VerificationTargetType::Overflow, values.second, &_expression);
else
solAssert(false, "");

addVerificationTarget(
type,
values.second,
&_expression
);
return values;
}

Expand Down Expand Up @@ -919,6 +923,12 @@ void BMC::checkVerificationTargets()

void BMC::checkVerificationTarget(BMCVerificationTarget& _target)
{
if (
m_solvedTargets.count(_target.expression) &&
m_solvedTargets.at(_target.expression).count(_target.type)
)
return;

switch (_target.type)
{
case VerificationTargetType::ConstantCondition:
Expand All @@ -930,10 +940,6 @@ void BMC::checkVerificationTarget(BMCVerificationTarget& _target)
case VerificationTargetType::Overflow:
checkOverflow(_target);
break;
case VerificationTargetType::UnderOverflow:
checkUnderflow(_target);
checkOverflow(_target);
break;
case VerificationTargetType::DivByZero:
checkDivByZero(_target);
break;
Expand Down Expand Up @@ -961,19 +967,10 @@ void BMC::checkConstantCondition(BMCVerificationTarget& _target)
void BMC::checkUnderflow(BMCVerificationTarget& _target)
{
solAssert(
_target.type == VerificationTargetType::Underflow ||
_target.type == VerificationTargetType::UnderOverflow,
_target.type == VerificationTargetType::Underflow,
""
);

if (
m_solvedTargets.count(_target.expression) && (
m_solvedTargets.at(_target.expression).count(VerificationTargetType::Underflow) ||
m_solvedTargets.at(_target.expression).count(VerificationTargetType::UnderOverflow)
)
)
return;

auto const* intType = dynamic_cast<IntegerType const*>(_target.expression->annotation().type);
if (!intType)
intType = TypeProvider::uint256();
Expand All @@ -994,19 +991,10 @@ void BMC::checkUnderflow(BMCVerificationTarget& _target)
void BMC::checkOverflow(BMCVerificationTarget& _target)
{
solAssert(
_target.type == VerificationTargetType::Overflow ||
_target.type == VerificationTargetType::UnderOverflow,
_target.type == VerificationTargetType::Overflow,
""
);

if (
m_solvedTargets.count(_target.expression) && (
m_solvedTargets.at(_target.expression).count(VerificationTargetType::Overflow) ||
m_solvedTargets.at(_target.expression).count(VerificationTargetType::UnderOverflow)
)
)
return;

auto const* intType = dynamic_cast<IntegerType const*>(_target.expression->annotation().type);
if (!intType)
intType = TypeProvider::uint256();
Expand All @@ -1028,12 +1016,6 @@ void BMC::checkDivByZero(BMCVerificationTarget& _target)
{
solAssert(_target.type == VerificationTargetType::DivByZero, "");

if (
m_solvedTargets.count(_target.expression) &&
m_solvedTargets.at(_target.expression).count(VerificationTargetType::DivByZero)
)
return;

checkCondition(
_target,
_target.constraints && (_target.value == 0),
Expand All @@ -1051,11 +1033,6 @@ void BMC::checkBalance(BMCVerificationTarget& _target)
{
solAssert(_target.type == VerificationTargetType::Balance, "");

if (
m_solvedTargets.count(_target.expression) &&
m_solvedTargets.at(_target.expression).count(VerificationTargetType::Balance)
)
return;
checkCondition(
_target,
_target.constraints && _target.value,
Expand All @@ -1072,12 +1049,6 @@ void BMC::checkAssert(BMCVerificationTarget& _target)
{
solAssert(_target.type == VerificationTargetType::Assert, "");

if (
m_solvedTargets.count(_target.expression) &&
m_solvedTargets.at(_target.expression).count(_target.type)
)
return;

checkCondition(
_target,
_target.constraints && !_target.value,
Expand Down
2 changes: 1 addition & 1 deletion libsolidity/formal/ModelCheckerSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct ModelCheckerInvariants
std::set<InvariantType> invariants;
};

enum class VerificationTargetType { ConstantCondition, Underflow, Overflow, UnderOverflow, DivByZero, Balance, Assert, PopEmptyArray, OutOfBounds };
enum class VerificationTargetType { ConstantCondition, Underflow, Overflow, DivByZero, Balance, Assert, PopEmptyArray, OutOfBounds };

struct ModelCheckerTargets
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ contract C {
// SMTIgnoreCex: yes
// ----
// Warning 6328: (166-201): CHC: Assertion violation happens here.
// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them.
// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them.

0 comments on commit 3c5aa3b

Please sign in to comment.