mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[SMTChecker] Keeping better track of path condition through branches with return statement in the BMC engine.
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
uint x;
|
||||
|
||||
modifier check() {
|
||||
require(x == 0);
|
||||
_;
|
||||
assert(x == 1); // should fail;
|
||||
assert(x == 0); // should hold;
|
||||
}
|
||||
|
||||
modifier inc() {
|
||||
if (x == 0) {
|
||||
return;
|
||||
}
|
||||
x = x + 1;
|
||||
_;
|
||||
}
|
||||
|
||||
function test() check inc public {
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (103-117): BMC: Assertion violation happens here.
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
uint x;
|
||||
|
||||
function reset_if_overflow() internal postinc {
|
||||
if (x < 10)
|
||||
return;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
modifier postinc() {
|
||||
if (x == 0) {
|
||||
return;
|
||||
}
|
||||
_;
|
||||
x = x + 1;
|
||||
}
|
||||
|
||||
function test() public {
|
||||
if (x == 0) {
|
||||
reset_if_overflow();
|
||||
assert(x == 1); // should fail;
|
||||
assert(x == 0); // should hold;
|
||||
return;
|
||||
}
|
||||
if (x < 10) {
|
||||
uint oldx = x;
|
||||
reset_if_overflow();
|
||||
assert(oldx + 1 == x); // should hold;
|
||||
assert(oldx == x); // should fail;
|
||||
return;
|
||||
}
|
||||
reset_if_overflow();
|
||||
assert(x == 1); // should hold;
|
||||
assert(x == 0); // should fail;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (384-398): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (635-652): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (781-795): BMC: Assertion violation happens here.
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract A {
|
||||
int x;
|
||||
constructor (int a) { x = a;}
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
int y;
|
||||
constructor(int a) A(-a) {
|
||||
if (a > 0) {
|
||||
y = 2;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
y = 3;
|
||||
}
|
||||
y = 4; // overwrites the else branch
|
||||
}
|
||||
}
|
||||
|
||||
contract C is B {
|
||||
constructor(int a) B(a) {
|
||||
assert(y != 3); // should hold
|
||||
assert(y == 4); // should fail
|
||||
if (a > 0) {
|
||||
assert(x < 0 && y == 2); // should hold
|
||||
assert(x < 0 && y == 4); // should fail
|
||||
}
|
||||
else {
|
||||
assert(x >= 0 && y == 4); // should hold
|
||||
assert(x >= 0 && y == 2); // should fail
|
||||
assert(x > 0); // should fail
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (330-344): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (422-445): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (522-546): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (566-579): BMC: Assertion violation happens here.
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract A {
|
||||
uint x = 1;
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
constructor(int a) {
|
||||
if (a > 0) {
|
||||
x = 2;
|
||||
return;
|
||||
}
|
||||
x = 3;
|
||||
}
|
||||
}
|
||||
|
||||
abstract contract C is B {
|
||||
}
|
||||
|
||||
contract D is C {
|
||||
constructor(int a) B(a) {
|
||||
assert(a > 0 || x == 3); // should hold
|
||||
assert(a <= 0 || x == 2); // should hold
|
||||
assert(x == 1); // should fail
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (319-333): BMC: Assertion violation happens here.
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract A {
|
||||
int x;
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
int y;
|
||||
constructor (int a) {
|
||||
if (a >= 0) {
|
||||
y = 1;
|
||||
return;
|
||||
}
|
||||
x = 1;
|
||||
y = 2;
|
||||
}
|
||||
}
|
||||
|
||||
contract C is A {
|
||||
int z;
|
||||
constructor (int a) {
|
||||
if (a >= 0) {
|
||||
z = 1;
|
||||
return;
|
||||
}
|
||||
x = -1;
|
||||
z = 2;
|
||||
}
|
||||
}
|
||||
|
||||
contract D1 is B, C {
|
||||
constructor() B(1) C(1) {
|
||||
assert(x == 0); // should hold
|
||||
assert(x == 1); // should fail
|
||||
assert(x == -1); // should fail
|
||||
}
|
||||
}
|
||||
|
||||
contract D2 is B, C {
|
||||
constructor() B(1) C(-1) {
|
||||
assert(x == 0); // should fail
|
||||
assert(x == 1); // should fail
|
||||
assert(x == -1); // should hold (constructor of C is executed AFTER constructor of B)
|
||||
}
|
||||
}
|
||||
|
||||
contract D3 is B, C {
|
||||
constructor() B(-1) C(1) {
|
||||
assert(x == 0); // should fail
|
||||
assert(x == 1); // should hold
|
||||
assert(x == -1); // should fail
|
||||
}
|
||||
}
|
||||
|
||||
contract D4 is B, C {
|
||||
constructor() B(-1) C(-1) {
|
||||
assert(x == 0); // should fail
|
||||
assert(x == 1); // should fail
|
||||
assert(x == -1); // should hold (constructor of C is executed AFTER constructor of B)
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (370-384): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (403-418): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (493-507): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (526-540): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (703-717): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (769-784): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (860-874): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (893-907): BMC: Assertion violation happens here.
|
||||
@@ -0,0 +1,33 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract B {
|
||||
int x;
|
||||
constructor(int b) {
|
||||
if (b > 0) {
|
||||
x = 1;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
x = 2;
|
||||
return;
|
||||
}
|
||||
x = 3; // dead code
|
||||
}
|
||||
}
|
||||
|
||||
contract C is B {
|
||||
constructor(int a) B(a) {
|
||||
assert(a > 0 || x == 2); // should hold
|
||||
assert(a <= 0 || x == 1); // should hold
|
||||
assert(x == 3); // should fail
|
||||
assert(x == 2); // should fail
|
||||
assert(x == 1); // should fail
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 5740: (152-157): Unreachable code.
|
||||
// Warning 4661: (310-324): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (343-357): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (376-390): BMC: Assertion violation happens here.
|
||||
@@ -0,0 +1,28 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
function test(uint256 a, uint256 b) public pure {
|
||||
assert(nested_if(a,b) != 42); // should hold
|
||||
assert(nested_if(a,b) == 1); // should fail
|
||||
}
|
||||
|
||||
function nested_if(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
if (a < 5) {
|
||||
if (b > 1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (a == 2 && b == 2) {
|
||||
return 42; // unreachable
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (147-174): BMC: Assertion violation happens here.
|
||||
// Warning 6838: (332-348): BMC: Condition is always false.
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
function test() public pure {
|
||||
assert(branches(0) == 0);
|
||||
assert(branches(1) == 42);
|
||||
}
|
||||
|
||||
function branches(uint256 a) internal pure returns (uint256) {
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 42;
|
||||
}
|
||||
return 1; // dead code
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 5740: (265-273): Unreachable code.
|
||||
@@ -0,0 +1,13 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
function test(uint256 a, uint256 b) public pure returns (uint256) {
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
return b / a; // This division is safe because of the early return in if-block.
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
@@ -0,0 +1,19 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
function test(uint256 a) public pure {
|
||||
assert(simple_if(a) == 1); // should fail for a == 0
|
||||
}
|
||||
|
||||
function simple_if(uint256 a) internal pure returns (uint256) {
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (89-114): BMC: Assertion violation happens here.
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
uint[] a;
|
||||
|
||||
constructor () {
|
||||
a.push();
|
||||
a.push();
|
||||
}
|
||||
|
||||
function check() public {
|
||||
require(a.length >= 2);
|
||||
require(a[1] == 0);
|
||||
conditional_store();
|
||||
assert(a[1] == 1); // should fail;
|
||||
assert(a[1] == 0); // should hold;
|
||||
}
|
||||
|
||||
function conditional_store() internal {
|
||||
if (a[1] == 0) {
|
||||
return;
|
||||
}
|
||||
a[1] = 1;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (205-222): BMC: Assertion violation happens here.
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
uint x;
|
||||
|
||||
function check() public {
|
||||
require(x == 0);
|
||||
conditional_increment();
|
||||
assert(x == 1); // should fail;
|
||||
assert(x == 0); // should hold;
|
||||
}
|
||||
|
||||
function conditional_increment() internal {
|
||||
if (x == 0) {
|
||||
return;
|
||||
}
|
||||
x = 1;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (132-146): BMC: Assertion violation happens here.
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
struct S {
|
||||
uint x;
|
||||
}
|
||||
S s;
|
||||
|
||||
function check() public {
|
||||
require(s.x == 0);
|
||||
conditional_increment();
|
||||
assert(s.x == 1); // should fail;
|
||||
assert(s.x == 0); // should hold;
|
||||
}
|
||||
|
||||
function conditional_increment() internal {
|
||||
if (s.x == 0) {
|
||||
return;
|
||||
}
|
||||
s.x = 1;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (156-172): BMC: Assertion violation happens here.
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
struct S {
|
||||
uint x;
|
||||
}
|
||||
S s;
|
||||
|
||||
function check() public {
|
||||
require(s.x == 0);
|
||||
conditional_increment();
|
||||
assert(s.x == 1); // should fail;
|
||||
assert(s.x == 0); // should hold;
|
||||
}
|
||||
|
||||
function conditional_increment() internal {
|
||||
if (s.x == 0) {
|
||||
return;
|
||||
}
|
||||
s = S(1);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (156-172): BMC: Assertion violation happens here.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
uint x;
|
||||
uint y;
|
||||
|
||||
function check() public {
|
||||
require(x == 0);
|
||||
require(y == 0);
|
||||
conditional_increment();
|
||||
assert(x == 0); // should fail;
|
||||
assert(x == 1); // should fail;
|
||||
assert(x == 2); // should hold;
|
||||
}
|
||||
|
||||
function conditional_increment() internal {
|
||||
if (x == 0) {
|
||||
(x,y) = (2,2);
|
||||
return;
|
||||
}
|
||||
(x,y) = (1,1);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
// Warning 4661: (160-174): BMC: Assertion violation happens here.
|
||||
// Warning 4661: (194-208): BMC: Assertion violation happens here.
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
pragma experimental SMTChecker;
|
||||
|
||||
contract C {
|
||||
|
||||
uint a;
|
||||
uint b;
|
||||
uint c;
|
||||
|
||||
function test() public view {
|
||||
if (a == 0) {
|
||||
if (b == 0) {
|
||||
if (c == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(a != 0 || b != 0 || c != 0);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// SMTEngine: bmc
|
||||
// ----
|
||||
@@ -1,14 +1,14 @@
|
||||
pragma experimental SMTChecker;
|
||||
contract C {
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
function mul(uint256 a, uint256 b) public pure returns (uint256) {
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
// TODO remove when SMTChecker sees that this code is the `else` of the `return`.
|
||||
require(a != 0);
|
||||
uint256 c = a * b;
|
||||
require(c / a == b);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning 4984: (160-165): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.
|
||||
// Warning 4281: (177-182): CHC: Division by zero happens here.
|
||||
|
||||
Reference in New Issue
Block a user