mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9451 from ethereum/smt_fix_push_push
[SMTChecker] Fix push().push()
This commit is contained in:
commit
e19e4d9db1
@ -13,6 +13,7 @@ Bugfixes:
|
|||||||
* SMTChecker: Fix internal error when using bitwise operators on fixed bytes type.
|
* SMTChecker: Fix internal error when using bitwise operators on fixed bytes type.
|
||||||
* SMTChecker: Fix internal error when using compound bitwise operator assignments on array indices inside branches.
|
* SMTChecker: Fix internal error when using compound bitwise operator assignments on array indices inside branches.
|
||||||
* SMTChecker: Fix error in events with indices of type static array.
|
* SMTChecker: Fix error in events with indices of type static array.
|
||||||
|
* SMTChecker: Fix internal error in sequential storage array pushes (``push().push()`).
|
||||||
* Type Checker: Fix overload resolution in combination with ``{value: ...}``.
|
* Type Checker: Fix overload resolution in combination with ``{value: ...}``.
|
||||||
* Type Checker: Fix internal compiler error related to oversized types.
|
* Type Checker: Fix internal compiler error related to oversized types.
|
||||||
* Code Generator: Avoid double cleanup when copying to memory.
|
* Code Generator: Avoid double cleanup when copying to memory.
|
||||||
|
@ -1077,7 +1077,7 @@ void SMTEncoder::arrayPush(FunctionCall const& _funCall)
|
|||||||
m_context.addAssertion(symbArray->length() == oldLength + 1);
|
m_context.addAssertion(symbArray->length() == oldLength + 1);
|
||||||
|
|
||||||
if (arguments.empty())
|
if (arguments.empty())
|
||||||
defineExpr(_funCall, element);
|
defineExpr(_funCall, smtutil::Expression::select(symbArray->elements(), oldLength));
|
||||||
|
|
||||||
arrayPushPopAssign(memberAccess->expression(), symbArray->currentValue());
|
arrayPushPopAssign(memberAccess->expression(), symbArray->currentValue());
|
||||||
}
|
}
|
||||||
@ -1119,6 +1119,28 @@ void SMTEncoder::arrayPushPopAssign(Expression const& _expr, smtutil::Expression
|
|||||||
}
|
}
|
||||||
else if (auto const* indexAccess = dynamic_cast<IndexAccess const*>(&_expr))
|
else if (auto const* indexAccess = dynamic_cast<IndexAccess const*>(&_expr))
|
||||||
arrayIndexAssignment(*indexAccess, _array);
|
arrayIndexAssignment(*indexAccess, _array);
|
||||||
|
else if (auto const* funCall = dynamic_cast<FunctionCall const*>(&_expr))
|
||||||
|
{
|
||||||
|
FunctionType const& funType = dynamic_cast<FunctionType const&>(*funCall->expression().annotation().type);
|
||||||
|
if (funType.kind() == FunctionType::Kind::ArrayPush)
|
||||||
|
{
|
||||||
|
auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression());
|
||||||
|
solAssert(memberAccess, "");
|
||||||
|
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
|
||||||
|
solAssert(symbArray, "");
|
||||||
|
|
||||||
|
auto oldLength = symbArray->length();
|
||||||
|
auto store = smtutil::Expression::store(
|
||||||
|
symbArray->elements(),
|
||||||
|
symbArray->length() - 1,
|
||||||
|
_array
|
||||||
|
);
|
||||||
|
symbArray->increaseIndex();
|
||||||
|
m_context.addAssertion(symbArray->elements() == store);
|
||||||
|
m_context.addAssertion(symbArray->length() == oldLength);
|
||||||
|
arrayPushPopAssign(memberAccess->expression(), symbArray->currentValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (dynamic_cast<MemberAccess const*>(&_expr))
|
else if (dynamic_cast<MemberAccess const*>(&_expr))
|
||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
9599_error,
|
9599_error,
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract C {
|
||||||
|
int[][] array2d;
|
||||||
|
function l() public {
|
||||||
|
array2d.push().push();
|
||||||
|
assert(array2d.length > 0);
|
||||||
|
assert(array2d[array2d.length - 1].length > 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract C {
|
||||||
|
int[][] array2d;
|
||||||
|
function l() public {
|
||||||
|
array2d.push().push();
|
||||||
|
assert(array2d.length > 2);
|
||||||
|
assert(array2d[array2d.length - 1].length > 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 4661: (113-139): Assertion violation happens here
|
||||||
|
// Warning 4661: (143-189): Assertion violation happens here
|
@ -0,0 +1,11 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract C {
|
||||||
|
int[][][] array2d;
|
||||||
|
function l() public {
|
||||||
|
array2d.push().push().push();
|
||||||
|
assert(array2d.length > 0);
|
||||||
|
uint last = array2d[array2d.length - 1].length;
|
||||||
|
assert(last > 0);
|
||||||
|
assert(array2d[array2d.length - 1][last - 1].length > 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract C {
|
||||||
|
int[][][] array2d;
|
||||||
|
function l() public {
|
||||||
|
array2d.push().push().push();
|
||||||
|
assert(array2d.length > 2);
|
||||||
|
uint last = array2d[array2d.length - 1].length;
|
||||||
|
assert(last > 3);
|
||||||
|
assert(array2d[array2d.length - 1][last - 1].length > 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 4661: (122-148): Assertion violation happens here
|
||||||
|
// Warning 4661: (202-218): Assertion violation happens here
|
||||||
|
// Warning 4661: (222-278): Assertion violation happens here
|
@ -0,0 +1,18 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract C {
|
||||||
|
int[][] array2d;
|
||||||
|
function l() public {
|
||||||
|
s().push();
|
||||||
|
// False positive.
|
||||||
|
// Knowledge is erased because `s()` is a storage pointer.
|
||||||
|
assert(array2d[2].length > 0);
|
||||||
|
}
|
||||||
|
function s() internal returns (int[] storage) {
|
||||||
|
array2d.push();
|
||||||
|
array2d.push();
|
||||||
|
array2d.push();
|
||||||
|
return array2d[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 4661: (184-213): Assertion violation happens here
|
@ -0,0 +1,15 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
contract C {
|
||||||
|
int[][] array2d;
|
||||||
|
function l() public {
|
||||||
|
s();
|
||||||
|
array2d[2].push();
|
||||||
|
assert(array2d[2].length > 0);
|
||||||
|
}
|
||||||
|
function s() internal returns (int[] storage) {
|
||||||
|
array2d.push();
|
||||||
|
array2d.push();
|
||||||
|
array2d.push();
|
||||||
|
return array2d[2];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user