mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Assume that push will not overflow
This commit is contained in:
parent
82db35e563
commit
d4d26c02e4
@ -657,3 +657,14 @@ Notice that we do not clear knowledge about ``array`` and ``d`` because they
|
||||
are located in storage, even though they also have type ``uint[]``. However,
|
||||
if ``d`` was assigned, we would need to clear knowledge about ``array`` and
|
||||
vice-versa.
|
||||
|
||||
Real World Assumptions
|
||||
======================
|
||||
|
||||
Some scenarios are expressive in Solidity and the EVM, but are expected to
|
||||
never occur in practice.
|
||||
One of such cases is the length of a dynamic storage array overflowing after a
|
||||
push: If the ``push`` operation is applied to such array 2^256 times, its
|
||||
length silently overflows.
|
||||
However, this is unlikely to happen in practice, since the Earth, the sun and
|
||||
the universe might not be around anymore at the end of the 2^256 operations.
|
||||
|
@ -1085,6 +1085,11 @@ void SMTEncoder::arrayPush(FunctionCall const& _funCall)
|
||||
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
|
||||
solAssert(symbArray, "");
|
||||
auto oldLength = symbArray->length();
|
||||
m_context.addAssertion(oldLength >= 0);
|
||||
// Real world assumption: the array length is assumed to not overflow.
|
||||
// This assertion guarantees that both the current and updated lengths have the above property.
|
||||
m_context.addAssertion(oldLength + 1 < (smt::maxValue(*TypeProvider::uint256()) - 1));
|
||||
|
||||
auto const& arguments = _funCall.arguments();
|
||||
smt::Expression element = arguments.empty() ?
|
||||
smt::zeroValue(_funCall.annotation().type) :
|
||||
@ -1096,12 +1101,7 @@ void SMTEncoder::arrayPush(FunctionCall const& _funCall)
|
||||
);
|
||||
symbArray->increaseIndex();
|
||||
m_context.addAssertion(symbArray->elements() == store);
|
||||
auto newLength = smt::Expression::ite(
|
||||
oldLength == smt::maxValue(*TypeProvider::uint256()),
|
||||
0,
|
||||
oldLength + 1
|
||||
);
|
||||
m_context.addAssertion(symbArray->length() == newLength);
|
||||
m_context.addAssertion(symbArray->length() == oldLength + 1);
|
||||
|
||||
if (arguments.empty())
|
||||
defineExpr(_funCall, element);
|
||||
|
10
test/libsolidity/smtCheckerTests/array_members/push.sol
Normal file
10
test/libsolidity/smtCheckerTests/array_members/push.sol
Normal file
@ -0,0 +1,10 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
uint[] a;
|
||||
function f(uint x) public {
|
||||
require(a.length < 100000);
|
||||
a.push(x);
|
||||
assert(a[a.length - 1] == x);
|
||||
}
|
||||
}
|
13
test/libsolidity/smtCheckerTests/array_members/push_2d.sol
Normal file
13
test/libsolidity/smtCheckerTests/array_members/push_2d.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
uint[][] a;
|
||||
function f(uint[] memory x, uint y) public {
|
||||
require(a.length < 100000);
|
||||
a.push(x);
|
||||
assert(a[a.length - 1][0] == x[0]);
|
||||
require(a[0].length < 100000);
|
||||
a[0].push(y);
|
||||
assert(a[0][a[0].length - 1] == y);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
uint256[] x;
|
||||
constructor() public { x.push(42); }
|
||||
function f() public {
|
||||
x.push(23);
|
||||
assert(x[0] == 42 || x[0] == 23);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
uint256[] x;
|
||||
constructor() public { x.push(42); }
|
||||
function f() public {
|
||||
x.push(23);
|
||||
assert(x[0] == 42);
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,12 @@
|
||||
contract C {
|
||||
uint256[] x;
|
||||
function f(uint256 l) public {
|
||||
require(x.length == 0);
|
||||
x.push(42);
|
||||
x.push(84);
|
||||
for(uint256 i = 0; i < l; ++i)
|
||||
x.push(23);
|
||||
assert(x[0] == 42 || x[0] == 23);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
uint256[] x;
|
||||
function f(uint256 l) public {
|
||||
require(x.length == 0);
|
||||
x.push(42);
|
||||
x.push(84);
|
||||
for(uint256 i = 0; i < l; ++i)
|
||||
x.push(23);
|
||||
assert(x[0] == 42);
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
Loading…
Reference in New Issue
Block a user