diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index c150ee20be..3a975939ab 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -220,6 +220,12 @@ def _post_assignement_operation(self, expression: AssignmentOperation) -> None: operation.set_expression(expression) self._result.append(operation) set_val(expression, left) + elif isinstance(left.type, ArrayType): + # Special case for init of array, when the right has only one element + operation = InitArray([right], left) + operation.set_expression(expression) + self._result.append(operation) + set_val(expression, left) else: operation = convert_assignment( left, right, expression.type, expression.expression_return_type diff --git a/tests/test_ssa_generation.py b/tests/test_ssa_generation.py index f002ec4e13..00d2f23fd4 100644 --- a/tests/test_ssa_generation.py +++ b/tests/test_ssa_generation.py @@ -27,6 +27,7 @@ BinaryType, InternalCall, Index, + InitArray, ) from slither.slithir.utils.ssa import is_used_later from slither.slithir.variables import ( @@ -796,20 +797,20 @@ def test_memory_array(): uint val1; uint val2; } - + function test_array() internal { A[] memory a= new A[](4); // Create REF_0 -> a_1[2] accept_array_entry(a[2]); - + // Create REF_1 -> a_1[3] accept_array_entry(a[3]); - + A memory alocal; accept_array_entry(alocal); - + } - + // val_1 = ϕ(val_0, REF_0, REF_1, alocal_1) // val_0 is an unknown external value function accept_array_entry(A memory val) public returns (uint) { @@ -818,9 +819,9 @@ def test_memory_array(): // Create REF_2 -> val_1.val1 return b(val.val1); } - + 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; } }""" @@ -862,12 +863,12 @@ def test_storage_array(): uint val1; uint val2; } - + // 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 astorage; - + function test_array() internal { accept_array_entry(a[2]); accept_array_entry(a[3]); @@ -877,7 +878,7 @@ def test_storage_array(): 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. uint five = 5; - + // NOTE(hbrodin): If the following line is enabled, there would ideally be a phi-node representing writes // to either a or astorage. //val.val2 = 4; @@ -1059,3 +1060,20 @@ def test_issue_473(): # return is for second phi assert len(return_value.values) == 1 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)