From 84aa0bdad64a5eb636737e5a347bbf43d18a68b2 Mon Sep 17 00:00:00 2001 From: samczsun Date: Thu, 3 Sep 2020 19:03:14 -0400 Subject: [PATCH 1/3] improve push ir conversion --- slither/slithir/convert.py | 133 ++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 77 deletions(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 323ed3c2f..ba391275b 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -364,39 +364,12 @@ def propagate_type_and_convert_call(result, node): new_ins = propagate_types(ins, node) if new_ins: if isinstance(new_ins, (list,)): - if len(new_ins) == 2: - new_ins[0].set_node(ins.node) - new_ins[1].set_node(ins.node) - del result[idx] - result.insert(idx, new_ins[0]) - result.insert(idx + 1, new_ins[1]) - idx = idx + 1 - elif len(new_ins) == 3: - new_ins[0].set_node(ins.node) - new_ins[1].set_node(ins.node) - new_ins[2].set_node(ins.node) - del result[idx] - result.insert(idx, new_ins[0]) - result.insert(idx + 1, new_ins[1]) - result.insert(idx + 2, new_ins[2]) - idx = idx + 2 - else: - # Pop conversion - assert len(new_ins) == 6 - new_ins[0].set_node(ins.node) - new_ins[1].set_node(ins.node) - new_ins[2].set_node(ins.node) - new_ins[3].set_node(ins.node) - new_ins[4].set_node(ins.node) - new_ins[5].set_node(ins.node) - del result[idx] - result.insert(idx, new_ins[0]) - result.insert(idx + 1, new_ins[1]) - result.insert(idx + 2, new_ins[2]) - result.insert(idx + 3, new_ins[3]) - result.insert(idx + 4, new_ins[4]) - result.insert(idx + 5, new_ins[5]) - idx = idx + 5 + for new_ins_ in new_ins: + new_ins_.set_node(ins.node) + del result[idx] + for i in range(len(new_ins)): + result.insert(idx + i, new_ins[i]) + idx = idx + len(new_ins) - 1 else: new_ins.set_node(ins.node) result[idx] = new_ins @@ -516,7 +489,7 @@ def propagate_types(ir, node): # pylint: disable=too-many-locals if isinstance(t, ArrayType) or ( isinstance(t, ElementaryType) and t.type == "bytes" ): - if ir.function_name == "push" and len(ir.arguments) == 1: + if ir.function_name == "push" and len(ir.arguments) <= 1: return convert_to_push(ir, node) if ir.function_name == "pop" and len(ir.arguments) == 0: return convert_to_pop(ir, node) @@ -1028,65 +1001,71 @@ def convert_to_solidity_func(ir): def convert_to_push(ir, node): """ - Convert a call to a PUSH operaiton + Convert a call to a series of operations to push a new value onto the array - The funciton assume to receive a correct IR + The function assume to receive a correct IR The checks must be done by the caller May necessitate to create an intermediate operation (InitArray) - Necessitate to return the lenght (see push documentation) + Necessitate to return the length (see push documentation) As a result, the function return may return a list """ - # TODO remove Push Operator, and change this to existing operators - - lvalue = ir.lvalue - if isinstance(ir.arguments[0], list): - ret = [] - - val = TemporaryVariable(node) - operation = InitArray(ir.arguments[0], val) - operation.set_expression(ir.expression) - operation.set_node(ir.node) - ret.append(operation) + ret = [] - prev_ir = ir - ir = Push(ir.destination, val) - ir.set_expression(prev_ir.expression) - ir.set_node(prev_ir.node) + arr = ir.destination - length = Literal(len(operation.init_values), "uint256") - t = operation.init_values[0].type - ir.lvalue.set_type(ArrayType(t, length)) + length = ReferenceVariable(node) + length.set_type(ElementaryType("uint256")) - ret.append(ir) + ir_length = Length(arr, length) + ir_length.set_expression(ir.expression) + ir_length.set_node(ir.node) + ir_length.lvalue.points_to = arr + ret.append(ir_length) - if lvalue: - length = Length(ir.array, lvalue) - length.set_expression(ir.expression) - length.lvalue.points_to = ir.lvalue - length.set_node(ir.node) - ret.append(length) + length_val = TemporaryVariable(node) + length_val.set_type(ElementaryType("uint256")) + ir_get_length = Assignment(length_val, length, ElementaryType("uint256")) + ir_get_length.set_expression(ir.expression) + ir_get_length.set_node(ir.node) + ret.append(ir_get_length) - return ret + new_length_val = TemporaryVariable(node) + ir_add_1 = Binary(new_length_val, length_val, Constant("1", ElementaryType("uint256")), BinaryType.ADDITION) + ir_add_1.set_expression(ir.expression) + ir_add_1.set_node(ir.node) + ret.append(ir_add_1) - prev_ir = ir - ir = Push(ir.destination, ir.arguments[0]) - ir.set_expression(prev_ir.expression) - ir.set_node(prev_ir.node) + ir_assign_length = Assignment(length, new_length_val, ElementaryType("uint256")) + ir_assign_length.set_expression(ir.expression) + ir_assign_length.set_node(ir.node) + ret.append(ir_assign_length) - if lvalue: - ret = [] - ret.append(ir) + new_type = ir.destination.type.type - length = Length(ir.array, lvalue) - length.set_expression(ir.expression) - length.lvalue.points_to = ir.lvalue - length.set_node(ir.node) - ret.append(length) - return ret + element_to_add = ReferenceVariable(node) + element_to_add.set_type(new_type) + ir_assign_element_to_add = Index(element_to_add, arr, length_val, ElementaryType("uint256")) + ir_length.lvalue.points_to = arr + ir_assign_element_to_add.set_expression(ir.expression) + ir_assign_element_to_add.set_node(ir.node) + ret.append(ir_assign_element_to_add) + + if len(ir.arguments) > 0: + ir_assign_value = Assignment(element_to_add, ir.arguments[0], ir.arguments[0].type) + ir_assign_value.set_expression(ir.expression) + ir_assign_value.set_node(ir.node) + ret.append(ir_assign_value) + else: + new_element = ir.lvalue + new_element.set_type(new_type) + ir_assign_value = Assignment(new_element, element_to_add, new_type) + ir_assign_value.set_expression(ir.expression) + ir_assign_value.set_node(ir.node) + ret.append(ir_assign_value) - return ir + return ret def convert_to_pop(ir, node): From d51a6f38f2090f543f3a673feeb0eb730a83ab22 Mon Sep 17 00:00:00 2001 From: samczsun Date: Fri, 4 Sep 2020 11:26:53 -0400 Subject: [PATCH 2/3] even more improved push ir parshing --- slither/slithir/convert.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index ba391275b..b8c597c87 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -1053,7 +1053,16 @@ def convert_to_push(ir, node): ret.append(ir_assign_element_to_add) if len(ir.arguments) > 0: - ir_assign_value = Assignment(element_to_add, ir.arguments[0], ir.arguments[0].type) + assign_value = ir.arguments[0] + if isinstance(assign_value, list): + assign_value = TemporaryVariable(node) + assign_value.set_type(element_to_add.type) + ir_assign_value = InitArray(ir.arguments[0], assign_value) + ir_assign_value.set_expression(ir.expression) + ir_assign_value.set_node(ir.node) + ret.append(ir_assign_value) + + ir_assign_value = Assignment(element_to_add, assign_value, assign_value.type) ir_assign_value.set_expression(ir.expression) ir_assign_value.set_node(ir.node) ret.append(ir_assign_value) From 23346cbe3e44b7529826b8fa4db4e25a576bf7f1 Mon Sep 17 00:00:00 2001 From: samczsun Date: Mon, 21 Sep 2020 13:52:36 -0400 Subject: [PATCH 3/3] make pylint and black happy --- slither/slithir/convert.py | 48 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index b8c597c87..7cdb11b8d 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -367,8 +367,8 @@ def propagate_type_and_convert_call(result, node): for new_ins_ in new_ins: new_ins_.set_node(ins.node) del result[idx] - for i in range(len(new_ins)): - result.insert(idx + i, new_ins[i]) + for i, ins in enumerate(new_ins): + result.insert(idx + i, ins) idx = idx + len(new_ins) - 1 else: new_ins.set_node(ins.node) @@ -999,20 +999,7 @@ def convert_to_solidity_func(ir): return new_ir -def convert_to_push(ir, node): - """ - Convert a call to a series of operations to push a new value onto the array - - The function assume to receive a correct IR - The checks must be done by the caller - - May necessitate to create an intermediate operation (InitArray) - Necessitate to return the length (see push documentation) - As a result, the function return may return a list - """ - - ret = [] - +def convert_to_push_expand_arr(ir, node, ret): arr = ir.destination length = ReferenceVariable(node) @@ -1032,7 +1019,9 @@ def convert_to_push(ir, node): ret.append(ir_get_length) new_length_val = TemporaryVariable(node) - ir_add_1 = Binary(new_length_val, length_val, Constant("1", ElementaryType("uint256")), BinaryType.ADDITION) + ir_add_1 = Binary( + new_length_val, length_val, Constant("1", ElementaryType("uint256")), BinaryType.ADDITION + ) ir_add_1.set_expression(ir.expression) ir_add_1.set_node(ir.node) ret.append(ir_add_1) @@ -1042,12 +1031,17 @@ def convert_to_push(ir, node): ir_assign_length.set_node(ir.node) ret.append(ir_assign_length) + return length_val + + +def convert_to_push_set_val(ir, node, length_val, ret): + arr = ir.destination + new_type = ir.destination.type.type element_to_add = ReferenceVariable(node) element_to_add.set_type(new_type) ir_assign_element_to_add = Index(element_to_add, arr, length_val, ElementaryType("uint256")) - ir_length.lvalue.points_to = arr ir_assign_element_to_add.set_expression(ir.expression) ir_assign_element_to_add.set_node(ir.node) ret.append(ir_assign_element_to_add) @@ -1074,6 +1068,24 @@ def convert_to_push(ir, node): ir_assign_value.set_node(ir.node) ret.append(ir_assign_value) + +def convert_to_push(ir, node): + """ + Convert a call to a series of operations to push a new value onto the array + + The function assume to receive a correct IR + The checks must be done by the caller + + May necessitate to create an intermediate operation (InitArray) + Necessitate to return the length (see push documentation) + As a result, the function return may return a list + """ + + ret = [] + + length_val = convert_to_push_expand_arr(ir, node, ret) + convert_to_push_set_val(ir, node, length_val, ret) + return ret