Refactoring of the ControlFlowGraph and use for detecting all uninitialized storage accesses.

This commit is contained in:
Daniel Kirchner
2018-12-12 04:20:53 +01:00
parent 1476acb804
commit 788612d2ef
29 changed files with 470 additions and 371 deletions
@@ -2,4 +2,4 @@ contract C {
function f() internal pure returns (mapping(uint=>uint) storage r) { }
}
// ----
// TypeError: (53-82): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (53-82): This variable is of storage pointer type and can be returned without prior assignment.
@@ -2,4 +2,4 @@ contract C {
function f() internal pure returns (mapping(uint=>uint) storage) {}
}
// ----
// TypeError: (53-80): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (53-80): This variable is of storage pointer type and can be returned without prior assignment.
@@ -7,4 +7,4 @@ contract C {
}
}
// ----
// TypeError: (87-96): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (87-96): This variable is of storage pointer type and can be returned without prior assignment.
@@ -1,26 +0,0 @@
contract C {
struct S { bool f; }
S s;
function f() internal returns (S storage c) {
assembly {
sstore(c_slot, sload(s_slot))
}
}
function g(bool flag) internal returns (S storage c) {
// control flow in assembly will not be analyzed for now,
// so this will not issue an error
assembly {
if flag {
sstore(c_slot, sload(s_slot))
}
}
}
function h() internal returns (S storage c) {
// any reference from assembly will be sufficient for now,
// so this will not issue an error
assembly {
sstore(s_slot, sload(c_slot))
}
}
}
// ----
@@ -45,8 +45,8 @@ contract C {
}
}
// ----
// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (223-234): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (440-451): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (654-665): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (871-882): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (223-234): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (440-451): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (654-665): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (871-882): This variable is of storage pointer type and can be returned without prior assignment.
@@ -12,5 +12,5 @@ contract C {
}
}
// ----
// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (182-193): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (182-193): This variable is of storage pointer type and can be returned without prior assignment.
@@ -14,5 +14,5 @@ contract C {
}
}
// ----
// TypeError: (96-107): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (186-197): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (96-107): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (186-197): This variable is of storage pointer type and can be returned without prior assignment.
@@ -18,5 +18,5 @@ contract C {
}
}
// ----
// TypeError: (249-258): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (367-376): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (249-258): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (367-376): This variable is of storage pointer type and can be returned without prior assignment.
@@ -13,6 +13,6 @@ contract C {
}
}
// ----
// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (176-187): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (264-275): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (176-187): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (264-275): This variable is of storage pointer type and can be returned without prior assignment.
@@ -9,5 +9,5 @@ contract C {
}
}
// ----
// TypeError: (96-107): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (200-211): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (96-107): This variable is of storage pointer type and can be returned without prior assignment.
// TypeError: (200-211): This variable is of storage pointer type and can be returned without prior assignment.
@@ -8,4 +8,4 @@ contract C {
}
}
// ----
// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error.
// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment.
@@ -0,0 +1,8 @@
contract C {
function f() internal view returns(uint[] storage a)
{
uint b = a[0];
revert();
b;
}
}
@@ -0,0 +1,9 @@
contract C {
uint[] r;
function f() internal view returns (uint[] storage s) {
assembly { pop(s_slot) }
s = r;
}
}
// ----
// TypeError: (92-126): This variable is of storage pointer type and can be accessed without prior assignment.
@@ -0,0 +1,8 @@
contract C {
// Make sure function parameters and return values are not considered
// for uninitialized return detection in the control flow analysis.
function f(function(uint[] storage) internal returns (uint[] storage)) internal pure
returns (function(uint[] storage) internal returns (uint[] storage))
{
}
}
@@ -0,0 +1,8 @@
contract C {
modifier m1(uint[] storage a) { _; }
modifier m2(uint[] storage a) { _; }
uint[] s;
function f() m1(b) m2(b = s) internal view returns (uint[] storage b) {}
}
// ----
// TypeError: (129-130): This variable is of storage pointer type and can be accessed without prior assignment.
@@ -0,0 +1,6 @@
contract C {
modifier m1(uint[] storage a) { _; }
modifier m2(uint[] storage a) { _; }
uint[] s;
function f() m1(b = s) m2(b) internal view returns (uint[] storage b) {}
}
@@ -0,0 +1,13 @@
contract C {
uint[] s;
modifier mod(uint[] storage b) {
_;
b[0] = 0;
}
function f() mod(a) internal returns (uint[] storage a)
{
a = s;
}
}
// ----
// TypeError: (120-121): This variable is of storage pointer type and can be accessed without prior assignment.
@@ -0,0 +1,13 @@
contract C {
uint[] s;
modifier mod(uint[] storage b) {
b[0] = 0;
_;
}
function f() mod(a) internal returns (uint[] storage a)
{
a = s;
}
}
// ----
// TypeError: (120-121): This variable is of storage pointer type and can be accessed without prior assignment.
@@ -0,0 +1,10 @@
contract C {
uint[] s;
function f() internal returns (uint[] storage a)
{
a[0] = 0;
a = s;
}
}
// ----
// TypeError: (94-95): This variable is of storage pointer type and can be accessed without prior assignment.
@@ -0,0 +1,11 @@
contract C {
struct S { uint a; }
S s;
function f() internal returns (S storage r)
{
r.a = 0;
r = s;
}
}
// ----
// TypeError: (109-110): This variable is of storage pointer type and can be accessed without prior assignment.
@@ -0,0 +1,10 @@
contract C {
uint[] s;
function f() internal returns (uint[] storage a)
{
revert();
a[0] = 0;
a = s;
}
}
// ----
@@ -8,3 +8,9 @@ library L {
function i(uint[] calldata, uint[] storage) external pure returns (S storage x) {return x; }
}
// ----
// TypeError: (197-198): This variable is of storage pointer type and can be accessed without prior assignment.
// TypeError: (203-204): This variable is of storage pointer type and can be accessed without prior assignment.
// TypeError: (359-360): This variable is of storage pointer type and can be accessed without prior assignment.
// TypeError: (365-366): This variable is of storage pointer type and can be accessed without prior assignment.
// TypeError: (460-461): This variable is of storage pointer type and can be accessed without prior assignment.
// TypeError: (557-558): This variable is of storage pointer type and can be accessed without prior assignment.