From a4428211a31dd214ec03f2badcb83d90b70d1655 Mon Sep 17 00:00:00 2001 From: Josselin Date: Mon, 1 Jul 2019 12:44:10 +0200 Subject: [PATCH] Improve naming convetion formater + add ReadVarSyntactic visitor --- slither/core/children/child_expression.py | 0 .../visitors/expression/read_var_syntactic.py | 105 ++++++++++++++++++ .../formatters/naming_convention.py | 30 ++++- utils/slither_format/utils/usages.py | 0 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 slither/core/children/child_expression.py create mode 100644 slither/visitors/expression/read_var_syntactic.py create mode 100644 utils/slither_format/utils/usages.py diff --git a/slither/core/children/child_expression.py b/slither/core/children/child_expression.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/visitors/expression/read_var_syntactic.py b/slither/visitors/expression/read_var_syntactic.py new file mode 100644 index 000000000..92cfd4ae9 --- /dev/null +++ b/slither/visitors/expression/read_var_syntactic.py @@ -0,0 +1,105 @@ + +from slither.visitors.expression.expression import ExpressionVisitor + +from slither.core.expressions.assignment_operation import AssignmentOperationType + +from slither.core.variables.variable import Variable +from slither.core.declarations.solidity_variables import SolidityVariable + +key = 'ReadVarSyntactic' + +def get(expression): + val = expression.context[key] + # we delete the item to reduce memory use + del expression.context[key] + return val + +def set_val(expression, val): + expression.context[key] = val + +# This Visitor is similar to ReadVar +# Except that it does explore all assignements operations +# Read is in the context of source code read, rather than semantic-based read +class ReadVarSyntactic(ExpressionVisitor): + + def result(self): + if self._result is None: + self._result = list(set(get(self.expression))) + return self._result + + + def _post_assignement_operation(self, expression): + left = get(expression.expression_left) + right = get(expression.expression_right) + val = left + right + set_val(expression, val) + + def _post_binary_operation(self, expression): + left = get(expression.expression_left) + right = get(expression.expression_right) + val = left + right + set_val(expression, val) + + def _post_call_expression(self, expression): + called = get(expression.called) + args = [get(a) for a in expression.arguments if a] + args = [item for sublist in args for item in sublist] + val = called + args + set_val(expression, val) + + def _post_conditional_expression(self, expression): + if_expr = get(expression.if_expression) + else_expr = get(expression.else_expression) + then_expr = get(expression.then_expression) + val = if_expr + else_expr + then_expr + set_val(expression, val) + + def _post_elementary_type_name_expression(self, expression): + set_val(expression, []) + + # save only identifier expression + def _post_identifier(self, expression): + if isinstance(expression.value, Variable): + set_val(expression, [expression]) + elif isinstance(expression.value, SolidityVariable): + set_val(expression, [expression]) + else: + set_val(expression, []) + + def _post_index_access(self, expression): + left = get(expression.expression_left) + right = get(expression.expression_right) + val = left + right + [expression] + set_val(expression, val) + + def _post_literal(self, expression): + set_val(expression, []) + + def _post_member_access(self, expression): + expr = get(expression.expression) + val = expr + set_val(expression, val) + + def _post_new_array(self, expression): + set_val(expression, []) + + def _post_new_contract(self, expression): + set_val(expression, []) + + def _post_new_elementary_type(self, expression): + set_val(expression, []) + + def _post_tuple_expression(self, expression): + expressions = [get(e) for e in expression.expressions if e] + val = [item for sublist in expressions for item in sublist] + set_val(expression, val) + + def _post_type_conversion(self, expression): + expr = get(expression.expression) + val = expr + set_val(expression, val) + + def _post_unary_operation(self, expression): + expr = get(expression.expression) + val = expr + set_val(expression, val) diff --git a/utils/slither_format/formatters/naming_convention.py b/utils/slither_format/formatters/naming_convention.py index 3c2060e3a..307613b78 100644 --- a/utils/slither_format/formatters/naming_convention.py +++ b/utils/slither_format/formatters/naming_convention.py @@ -1,8 +1,11 @@ import re import logging from slither.core.expressions.identifier import Identifier +from slither.core.declarations import Structure +from slither.core.solidity_types import UserDefinedType from slither.slithir.operations import NewContract from slither.slithir.operations import Member +from slither.visitors.expression.read_var_syntactic import ReadVarSyntactic from ..exceptions import FormatError from ..utils.patches import create_patch @@ -652,7 +655,10 @@ def _create_patch_state_variable_uses(slither, result, element): fms = target_contract.functions + target_contract.modifiers for fm in fms: for node in fm.nodes: - vars = node._expression_vars_written + node._expression_vars_read + if not node.expression: + continue + visitor = ReadVarSyntactic(node.expression) + vars = visitor.result() for v in vars: if isinstance(v, Identifier) and str(v) == name and [str(sv) for sv in (node._state_vars_read + @@ -775,6 +781,7 @@ def _create_patch_enum_uses(slither, result, element): + def _create_patch_struct_uses(slither, result, element): in_file, in_file_str, old_str_of_interest, loc_start, loc_end = _unpack_info(slither, element) @@ -824,5 +831,26 @@ def _create_patch_struct_uses(slither, result, element): # To-do: Check any other place/way where struct type is used (e.g. typecast) + for st in contract.structures: + for elem in st.elems.values(): + if isinstance(elem.type, UserDefinedType): + if isinstance(elem.type.type, Structure): + if str(elem.type.type) == name: + old_str = str(elem.type.type) + new_str = name.capitalize() + + in_file = elem.source_mapping['filename_absolute'] + loc_start = elem.source_mapping['start'] + loc_end = loc_start + len(old_str) + + create_patch(result, + in_file, + loc_start, + loc_end, + old_str, + new_str) + # endregion + + diff --git a/utils/slither_format/utils/usages.py b/utils/slither_format/utils/usages.py new file mode 100644 index 000000000..e69de29bb