Skip to content

Commit 78afd71

Browse files
author
Leonardo
authored
Merge pull request #11860 from ethereum/smt_static_array
[SMTChecker] Add static array length constraint
2 parents 525b4c7 + ac528cf commit 78afd71

10 files changed

+79
-17
lines changed

libsolidity/formal/SymbolicTypes.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,11 @@ smtutil::Expression symbolicUnknownConstraints(smtutil::Expression _expr, fronte
551551
solAssert(_type, "");
552552
if (isEnum(*_type) || isInteger(*_type) || isAddress(*_type) || isFixedBytes(*_type))
553553
return _expr >= minValue(_type) && _expr <= maxValue(_type);
554+
else if (
555+
auto arrayType = dynamic_cast<ArrayType const*>(_type);
556+
arrayType && !arrayType->isDynamicallySized()
557+
)
558+
return smtutil::Expression::tuple_get(_expr, 1) == arrayType->length();
554559
else if (isArray(*_type) || isMapping(*_type))
555560
/// Length cannot be negative.
556561
return smtutil::Expression::tuple_get(_expr, 1) >= 0;

test/libsolidity/smtCheckerTests/types/array_static_aliasing_memory_5.sol

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
contract C
22
{
33
function f(uint[2] memory a, uint[2] memory b, uint[2] memory c) public pure {
4-
require(a.length > 0);
5-
require(b.length > 0);
6-
require(c.length > 0);
74
require(c[0] == 42);
85
require(a[0] == 2);
96
b[0] = 1;
@@ -19,5 +16,4 @@ contract C
1916
// ====
2017
// SMTEngine: all
2118
// ----
22-
// Warning 6368: (467-471): CHC: Out of bounds access happens here.
23-
// Warning 6328: (460-477): CHC: Assertion violation happens here.
19+
// Warning 6328: (385-402): CHC: Assertion violation happens here.

test/libsolidity/smtCheckerTests/types/array_static_aliasing_storage_5.sol

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,3 @@ contract C
2424
// SMTEngine: all
2525
// SMTIgnoreCex: yes
2626
// ----
27-
// Warning 6368: (165-169): CHC: Out of bounds access happens here.
28-
// Warning 6368: (178-182): CHC: Out of bounds access happens here.
29-
// Warning 6368: (190-195): CHC: Out of bounds access happens here.
30-
// Warning 6368: (314-318): CHC: Out of bounds access happens here.
31-
// Warning 6368: (440-445): CHC: Out of bounds access happens here.

test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_1.sol

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,4 @@ contract C
2727
// SMTEngine: all
2828
// SMTIgnoreCex: yes
2929
// ----
30-
// Warning 6368: (353-369): CHC: Out of bounds access happens here.
31-
// Warning 6368: (353-372): CHC: Out of bounds access happens here.
32-
// Warning 6368: (463-477): CHC: Out of bounds access happens here.
3330
// Warning 6328: (456-487): CHC: Assertion violation happens here.

test/libsolidity/smtCheckerTests/types/array_static_mapping_aliasing_2.sol

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ contract C
3030
// SMTEngine: all
3131
// SMTIgnoreCex: yes
3232
// ----
33-
// Warning 6368: (314-328): CHC: Out of bounds access happens here.
34-
// Warning 6368: (367-383): CHC: Out of bounds access happens here.
35-
// Warning 6368: (367-386): CHC: Out of bounds access happens here.
36-
// Warning 6368: (497-511): CHC: Out of bounds access happens here.
3733
// Warning 6328: (860-880): CHC: Assertion violation happens here.
3834
// Warning 6368: (936-952): CHC: Out of bounds access might happen here.
3935
// Warning 6368: (936-955): CHC: Out of bounds access might happen here.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
contract C {
2+
function f(address[2] memory a) public pure {
3+
assert(a.length == 2); // should hold
4+
assert(a.length < 2); // should fail
5+
assert(a.length > 2); // should fail
6+
}
7+
}
8+
// ====
9+
// SMTEngine: all
10+
// ----
11+
// Warning 6328: (102-122): CHC: Assertion violation happens here.\nCounterexample:\n\na = [9, 9]\n\nTransaction trace:\nC.constructor()\nC.f([9, 9])
12+
// Warning 6328: (141-161): CHC: Assertion violation happens here.\nCounterexample:\n\na = [9, 9]\n\nTransaction trace:\nC.constructor()\nC.f([9, 9])
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
contract C {
2+
function f() public pure returns (address[2] memory a) {
3+
assert(a.length == 2); // should hold
4+
assert(a.length < 2); // should fail
5+
assert(a.length > 2); // should fail
6+
}
7+
}
8+
// ====
9+
// SMTEngine: all
10+
// ----
11+
// Warning 6328: (113-133): CHC: Assertion violation happens here.\nCounterexample:\n\na = [0, 0]\n\nTransaction trace:\nC.constructor()\nC.f()
12+
// Warning 6328: (152-172): CHC: Assertion violation happens here.\nCounterexample:\n\na = [0, 0]\n\nTransaction trace:\nC.constructor()\nC.f()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
contract C {
2+
function f() public pure {
3+
address[2] memory a;
4+
assert(a.length == 2); // should hold
5+
assert(a.length < 2); // should fail
6+
assert(a.length > 2); // should fail
7+
}
8+
}
9+
// ====
10+
// SMTEngine: all
11+
// ----
12+
// Warning 6328: (106-126): CHC: Assertion violation happens here.\nCounterexample:\n\na = [0, 0]\n\nTransaction trace:\nC.constructor()\nC.f()
13+
// Warning 6328: (145-165): CHC: Assertion violation happens here.\nCounterexample:\n\na = [0, 0]\n\nTransaction trace:\nC.constructor()\nC.f()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
contract C {
2+
uint[2] a;
3+
uint x = f();
4+
constructor() {
5+
assert(a.length == 2); // should hold
6+
assert(x == 2); // should hold
7+
assert(a.length < 2); // should fail
8+
assert(a.length > 2); // should fail
9+
}
10+
function f() internal view returns (uint) {
11+
assert(a.length == 2); // should hold
12+
assert(a.length < 2); // should fail
13+
assert(a.length > 2); // should fail
14+
return a.length;
15+
}
16+
}
17+
// ====
18+
// SMTEngine: all
19+
// ----
20+
// Warning 6328: (132-152): CHC: Assertion violation happens here.\nCounterexample:\na = [0, 0], x = 2\n\nTransaction trace:\nC.constructor()
21+
// Warning 6328: (171-191): CHC: Assertion violation happens here.\nCounterexample:\na = [0, 0], x = 2\n\nTransaction trace:\nC.constructor()
22+
// Warning 6328: (298-318): CHC: Assertion violation happens here.\nCounterexample:\na = [0, 0], x = 0\n\nTransaction trace:\nC.constructor()
23+
// Warning 6328: (337-357): CHC: Assertion violation happens here.\nCounterexample:\na = [0, 0], x = 0\n\nTransaction trace:\nC.constructor()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
contract C {
2+
uint[2] a;
3+
function f() public view {
4+
assert(a.length == 2); // should hold
5+
assert(a.length < 2); // should fail
6+
assert(a.length > 2); // should fail
7+
}
8+
}
9+
// ====
10+
// SMTEngine: all
11+
// ----
12+
// Warning 6328: (95-115): CHC: Assertion violation happens here.\nCounterexample:\na = [0, 0]\n\nTransaction trace:\nC.constructor()\nState: a = [0, 0]\nC.f()
13+
// Warning 6328: (134-154): CHC: Assertion violation happens here.\nCounterexample:\na = [0, 0]\n\nTransaction trace:\nC.constructor()\nState: a = [0, 0]\nC.f()

0 commit comments

Comments
 (0)