|
|
@ -27,6 +27,7 @@ from slither.slithir.operations import ( |
|
|
|
BinaryType, |
|
|
|
BinaryType, |
|
|
|
InternalCall, |
|
|
|
InternalCall, |
|
|
|
Index, |
|
|
|
Index, |
|
|
|
|
|
|
|
InitArray, |
|
|
|
) |
|
|
|
) |
|
|
|
from slither.slithir.utils.ssa import is_used_later |
|
|
|
from slither.slithir.utils.ssa import is_used_later |
|
|
|
from slither.slithir.variables import ( |
|
|
|
from slither.slithir.variables import ( |
|
|
@ -796,20 +797,20 @@ def test_memory_array(): |
|
|
|
uint val1; |
|
|
|
uint val1; |
|
|
|
uint val2; |
|
|
|
uint val2; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function test_array() internal { |
|
|
|
function test_array() internal { |
|
|
|
A[] memory a= new A[](4); |
|
|
|
A[] memory a= new A[](4); |
|
|
|
// Create REF_0 -> a_1[2] |
|
|
|
// Create REF_0 -> a_1[2] |
|
|
|
accept_array_entry(a[2]); |
|
|
|
accept_array_entry(a[2]); |
|
|
|
|
|
|
|
|
|
|
|
// Create REF_1 -> a_1[3] |
|
|
|
// Create REF_1 -> a_1[3] |
|
|
|
accept_array_entry(a[3]); |
|
|
|
accept_array_entry(a[3]); |
|
|
|
|
|
|
|
|
|
|
|
A memory alocal; |
|
|
|
A memory alocal; |
|
|
|
accept_array_entry(alocal); |
|
|
|
accept_array_entry(alocal); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// val_1 = ϕ(val_0, REF_0, REF_1, alocal_1) |
|
|
|
// val_1 = ϕ(val_0, REF_0, REF_1, alocal_1) |
|
|
|
// val_0 is an unknown external value |
|
|
|
// val_0 is an unknown external value |
|
|
|
function accept_array_entry(A memory val) public returns (uint) { |
|
|
|
function accept_array_entry(A memory val) public returns (uint) { |
|
|
@ -818,9 +819,9 @@ def test_memory_array(): |
|
|
|
// Create REF_2 -> val_1.val1 |
|
|
|
// Create REF_2 -> val_1.val1 |
|
|
|
return b(val.val1); |
|
|
|
return b(val.val1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function b(uint arg) public returns (uint){ |
|
|
|
function b(uint arg) public returns (uint){ |
|
|
|
// arg_1 = ϕ(arg_0, zero_1, REF_2) |
|
|
|
// arg_1 = ϕ(arg_0, zero_1, REF_2) |
|
|
|
return arg + 1; |
|
|
|
return arg + 1; |
|
|
|
} |
|
|
|
} |
|
|
|
}""" |
|
|
|
}""" |
|
|
@ -862,12 +863,12 @@ def test_storage_array(): |
|
|
|
uint val1; |
|
|
|
uint val1; |
|
|
|
uint val2; |
|
|
|
uint val2; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// NOTE(hbrodin): a is never written, should only become a_0. Same for astorage (astorage_0). Phi-nodes at entry |
|
|
|
// NOTE(hbrodin): a is never written, should only become a_0. Same for astorage (astorage_0). Phi-nodes at entry |
|
|
|
// should only add new versions of a state variable if it is actually written. |
|
|
|
// should only add new versions of a state variable if it is actually written. |
|
|
|
A[] a; |
|
|
|
A[] a; |
|
|
|
A astorage; |
|
|
|
A astorage; |
|
|
|
|
|
|
|
|
|
|
|
function test_array() internal { |
|
|
|
function test_array() internal { |
|
|
|
accept_array_entry(a[2]); |
|
|
|
accept_array_entry(a[2]); |
|
|
|
accept_array_entry(a[3]); |
|
|
|
accept_array_entry(a[3]); |
|
|
@ -877,7 +878,7 @@ def test_storage_array(): |
|
|
|
function accept_array_entry(A storage val) internal returns (uint) { |
|
|
|
function accept_array_entry(A storage val) internal returns (uint) { |
|
|
|
// val is either a[2], a[3] or astorage_0. Ideally this could be identified. |
|
|
|
// val is either a[2], a[3] or astorage_0. Ideally this could be identified. |
|
|
|
uint five = 5; |
|
|
|
uint five = 5; |
|
|
|
|
|
|
|
|
|
|
|
// NOTE(hbrodin): If the following line is enabled, there would ideally be a phi-node representing writes |
|
|
|
// NOTE(hbrodin): If the following line is enabled, there would ideally be a phi-node representing writes |
|
|
|
// to either a or astorage. |
|
|
|
// to either a or astorage. |
|
|
|
//val.val2 = 4; |
|
|
|
//val.val2 = 4; |
|
|
@ -1059,3 +1060,20 @@ def test_issue_473(): |
|
|
|
# return is for second phi |
|
|
|
# return is for second phi |
|
|
|
assert len(return_value.values) == 1 |
|
|
|
assert len(return_value.values) == 1 |
|
|
|
assert second_phi.lvalue in return_value.values |
|
|
|
assert second_phi.lvalue in return_value.values |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_issue_1748(): |
|
|
|
|
|
|
|
source = """ |
|
|
|
|
|
|
|
contract Contract { |
|
|
|
|
|
|
|
uint[] arr; |
|
|
|
|
|
|
|
function foo(uint i) public { |
|
|
|
|
|
|
|
arr = [1]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
with slither_from_source(source) as slither: |
|
|
|
|
|
|
|
c = slither.get_contract_from_name("Contract")[0] |
|
|
|
|
|
|
|
f = c.functions[0] |
|
|
|
|
|
|
|
operations = f.slithir_operations |
|
|
|
|
|
|
|
assign_op = operations[0] |
|
|
|
|
|
|
|
assert isinstance(assign_op, InitArray) |
|
|
|