diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py index d1306fce2..796b43ca6 100644 --- a/slither/solc_parsing/expressions/expression_parsing.py +++ b/slither/solc_parsing/expressions/expression_parsing.py @@ -306,9 +306,8 @@ def find_variable( all_contracts = sl.contracts all_functions_parser = sl_parser.all_functions_and_modifiers_parser - # Look for all references delcaration - # First look only in the context of function/contract - # Then look everywhere + # Only look for reference declaration in the direct contract, see comment at the end + # Reference looked are split between direct and all # Because functions are copied between contracts, two functions can have the same ref # So we need to first look with respect to the direct context @@ -318,12 +317,6 @@ def find_variable( if ret: return ret - ret = _find_variable_from_ref_declaration( - referenced_declaration, all_contracts, all_functions_parser - ) - if ret: - return ret - function_parser: Optional[FunctionSolc] = ( caller_context if isinstance(caller_context, FunctionSolc) else None ) @@ -368,6 +361,33 @@ def find_variable( if ret: return ret + # Look from reference declaration in all the contracts at the end + # Because they are many instances where this can't be trusted + # For example in + # contract A{ + # function _f() internal view returns(uint){ + # return 1; + # } + # + # function get() public view returns(uint){ + # return _f(); + # } + # } + # + # contract B is A{ + # function _f() internal view returns(uint){ + # return 2; + # } + # + # } + # get's AST will say that the ref declaration for _f() is A._f(), but in the context of B, its not + + ret = _find_variable_from_ref_declaration( + referenced_declaration, all_contracts, all_functions_parser + ) + if ret: + return ret + raise VariableNotFound("Variable not found: {} (context {})".format(var_name, caller_context))