mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[SMTChecker] Implement support for memory allocation
This commit is contained in:
parent
1cc0d642e8
commit
9f3d5d3e2f
@ -10,6 +10,7 @@ Compiler Features:
|
|||||||
* SMTChecker: Support ``revert()``.
|
* SMTChecker: Support ``revert()``.
|
||||||
* SMTChecker: Support shifts.
|
* SMTChecker: Support shifts.
|
||||||
* SMTChecker: Support compound and, or, and xor operators.
|
* SMTChecker: Support compound and, or, and xor operators.
|
||||||
|
* SMTChecker: Support memory allocation, e.g. ``new bytes(123)``.
|
||||||
* SMTChecker: Support structs.
|
* SMTChecker: Support structs.
|
||||||
* SMTChecker: Support ``type(T).min``, ``type(T).max``, and ``type(I).interfaceId``.
|
* SMTChecker: Support ``type(T).min``, ``type(T).max``, and ``type(I).interfaceId``.
|
||||||
* SMTChecker: Support ``address`` type conversion with literals, e.g. ``address(0)``.
|
* SMTChecker: Support ``address`` type conversion with literals, e.g. ``address(0)``.
|
||||||
|
@ -663,6 +663,9 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall)
|
|||||||
case FunctionType::Kind::Event:
|
case FunctionType::Kind::Event:
|
||||||
// These can be safely ignored.
|
// These can be safely ignored.
|
||||||
break;
|
break;
|
||||||
|
case FunctionType::Kind::ObjectCreation:
|
||||||
|
visitObjectCreation(_funCall);
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
4588_error,
|
4588_error,
|
||||||
@ -735,6 +738,25 @@ void SMTEncoder::visitGasLeft(FunctionCall const& _funCall)
|
|||||||
m_context.addAssertion(symbolicVar->currentValue() <= symbolicVar->valueAtIndex(index - 1));
|
m_context.addAssertion(symbolicVar->currentValue() <= symbolicVar->valueAtIndex(index - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMTEncoder::visitObjectCreation(FunctionCall const& _funCall)
|
||||||
|
{
|
||||||
|
auto const& args = _funCall.arguments();
|
||||||
|
solAssert(args.size() >= 1, "");
|
||||||
|
auto argType = args.front()->annotation().type->category();
|
||||||
|
solAssert(argType == Type::Category::Integer || argType == Type::Category::RationalNumber, "");
|
||||||
|
|
||||||
|
smtutil::Expression arraySize = expr(*args.front());
|
||||||
|
setSymbolicUnknownValue(arraySize, TypeProvider::uint256(), m_context);
|
||||||
|
|
||||||
|
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(_funCall));
|
||||||
|
solAssert(symbArray, "");
|
||||||
|
smt::setSymbolicZeroValue(*symbArray, m_context);
|
||||||
|
auto zeroElements = symbArray->elements();
|
||||||
|
symbArray->increaseIndex();
|
||||||
|
m_context.addAssertion(symbArray->length() == arraySize);
|
||||||
|
m_context.addAssertion(symbArray->elements() == zeroElements);
|
||||||
|
}
|
||||||
|
|
||||||
void SMTEncoder::endVisit(Identifier const& _identifier)
|
void SMTEncoder::endVisit(Identifier const& _identifier)
|
||||||
{
|
{
|
||||||
if (auto decl = identifierToVariable(_identifier))
|
if (auto decl = identifierToVariable(_identifier))
|
||||||
|
@ -137,6 +137,7 @@ protected:
|
|||||||
void visitAssert(FunctionCall const& _funCall);
|
void visitAssert(FunctionCall const& _funCall);
|
||||||
void visitRequire(FunctionCall const& _funCall);
|
void visitRequire(FunctionCall const& _funCall);
|
||||||
void visitGasLeft(FunctionCall const& _funCall);
|
void visitGasLeft(FunctionCall const& _funCall);
|
||||||
|
void visitObjectCreation(FunctionCall const& _funCall);
|
||||||
void visitTypeConversion(FunctionCall const& _funCall);
|
void visitTypeConversion(FunctionCall const& _funCall);
|
||||||
void visitFunctionIdentifier(Identifier const& _identifier);
|
void visitFunctionIdentifier(Identifier const& _identifier);
|
||||||
|
|
||||||
|
36
test/libsolidity/smtCheckerTests/operators/bytes_new.sol
Normal file
36
test/libsolidity/smtCheckerTests/operators/bytes_new.sol
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
bytes memory x = new bytes(0);
|
||||||
|
assert(x.length == 0);
|
||||||
|
}
|
||||||
|
function g() public pure {
|
||||||
|
bytes memory x = new bytes(3);
|
||||||
|
assert(x.length == 3);
|
||||||
|
assert(x[0] == 0);
|
||||||
|
assert(x[1] == 0);
|
||||||
|
assert(x[2] == 0);
|
||||||
|
}
|
||||||
|
function h() public pure {
|
||||||
|
bytes memory x = new bytes(3);
|
||||||
|
assert(x.length == 3);
|
||||||
|
x[0] = 0x12;
|
||||||
|
x[1] = 0x34;
|
||||||
|
assert(x[0] == 0x12);
|
||||||
|
assert(x[1] == 0x34);
|
||||||
|
// This should be an out-of-bounds assertion.
|
||||||
|
x[5] = 0xff;
|
||||||
|
assert(x[5] == 0xff);
|
||||||
|
}
|
||||||
|
function h(uint size) public pure {
|
||||||
|
bytes memory x = new bytes(size);
|
||||||
|
assert(x.length == size);
|
||||||
|
require(size >= 2);
|
||||||
|
x[0] = 0x12;
|
||||||
|
x[1] = 0x34;
|
||||||
|
assert(x[0] == 0x12);
|
||||||
|
assert(x[1] == 0x34);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
36
test/libsolidity/smtCheckerTests/operators/integer_new.sol
Normal file
36
test/libsolidity/smtCheckerTests/operators/integer_new.sol
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
uint[] memory x = new uint[](0);
|
||||||
|
assert(x.length == 0);
|
||||||
|
}
|
||||||
|
function g() public pure {
|
||||||
|
uint[] memory x = new uint[](3);
|
||||||
|
assert(x.length == 3);
|
||||||
|
assert(x[0] == 0);
|
||||||
|
assert(x[1] == 0);
|
||||||
|
assert(x[2] == 0);
|
||||||
|
}
|
||||||
|
function h() public pure {
|
||||||
|
uint[] memory x = new uint[](3);
|
||||||
|
assert(x.length == 3);
|
||||||
|
x[0] = 0x12;
|
||||||
|
x[1] = 0x34;
|
||||||
|
assert(x[0] == 0x12);
|
||||||
|
assert(x[1] == 0x34);
|
||||||
|
// This should be an out-of-bounds assertion.
|
||||||
|
x[5] = 0xff;
|
||||||
|
assert(x[5] == 0xff);
|
||||||
|
}
|
||||||
|
function h(uint size) public pure {
|
||||||
|
uint[] memory x = new uint[](size);
|
||||||
|
assert(x.length == size);
|
||||||
|
require(size >= 2);
|
||||||
|
x[0] = 0x12;
|
||||||
|
x[1] = 0x34;
|
||||||
|
assert(x[0] == 0x12);
|
||||||
|
assert(x[1] == 0x34);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -7,8 +7,8 @@ contract C {
|
|||||||
function(uint) returns (uint)[10] storage b = y;
|
function(uint) returns (uint)[10] storage b = y;
|
||||||
function(uint) external returns (uint)[] memory c;
|
function(uint) external returns (uint)[] memory c;
|
||||||
c = new function(uint) external returns (uint)[](200);
|
c = new function(uint) external returns (uint)[](200);
|
||||||
|
assert(c.length == 200);
|
||||||
a; b;
|
a; b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Warning 4588: (361-410): Assertion checker does not yet implement this type of function call.
|
|
||||||
|
@ -14,6 +14,7 @@ contract C {
|
|||||||
}
|
}
|
||||||
function f() public pure {
|
function f() public pure {
|
||||||
S[] memory s1 = new S[](3);
|
S[] memory s1 = new S[](3);
|
||||||
|
assert(s1.length == 3);
|
||||||
s1[0].x = 2;
|
s1[0].x = 2;
|
||||||
assert(s1[0].x == 2);
|
assert(s1[0].x == 2);
|
||||||
s1[1].t.y = 3;
|
s1[1].t.y = 3;
|
||||||
@ -27,4 +28,3 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Warning 4588: (217-227): Assertion checker does not yet implement this type of function call.
|
|
||||||
|
@ -14,6 +14,7 @@ contract C {
|
|||||||
}
|
}
|
||||||
function f(S memory s2) public pure {
|
function f(S memory s2) public pure {
|
||||||
S[] memory s1 = new S[](3);
|
S[] memory s1 = new S[](3);
|
||||||
|
assert(s1.length == 3);
|
||||||
s1[0].x = 2;
|
s1[0].x = 2;
|
||||||
assert(s1[0].x == s2.x);
|
assert(s1[0].x == s2.x);
|
||||||
s1[1].t.y = 3;
|
s1[1].t.y = 3;
|
||||||
@ -27,9 +28,8 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Warning 6328: (257-280): Assertion violation happens here.
|
// Warning 6328: (283-306): Assertion violation happens here.
|
||||||
// Warning 6328: (301-328): Assertion violation happens here.
|
// Warning 6328: (327-354): Assertion violation happens here.
|
||||||
// Warning 6328: (350-379): Assertion violation happens here.
|
// Warning 6328: (376-405): Assertion violation happens here.
|
||||||
// Warning 6328: (404-439): Assertion violation happens here.
|
// Warning 6328: (430-465): Assertion violation happens here.
|
||||||
// Warning 6328: (467-508): Assertion violation happens here.
|
// Warning 6328: (493-534): Assertion violation happens here.
|
||||||
// Warning 4588: (228-238): Assertion checker does not yet implement this type of function call.
|
|
||||||
|
Loading…
Reference in New Issue
Block a user