|
|
@ -5,7 +5,7 @@ from slither.core.declarations import Modifier, Event, EnumContract, StructureCo |
|
|
|
from slither.core.declarations.contract import Contract |
|
|
|
from slither.core.declarations.contract import Contract |
|
|
|
from slither.core.declarations.custom_error_contract import CustomErrorContract |
|
|
|
from slither.core.declarations.custom_error_contract import CustomErrorContract |
|
|
|
from slither.core.declarations.function_contract import FunctionContract |
|
|
|
from slither.core.declarations.function_contract import FunctionContract |
|
|
|
from slither.core.solidity_types import ElementaryType, TypeAliasContract |
|
|
|
from slither.core.solidity_types import ElementaryType, TypeAliasContract, Type |
|
|
|
from slither.core.variables.state_variable import StateVariable |
|
|
|
from slither.core.variables.state_variable import StateVariable |
|
|
|
from slither.solc_parsing.declarations.caller_context import CallerContextExpression |
|
|
|
from slither.solc_parsing.declarations.caller_context import CallerContextExpression |
|
|
|
from slither.solc_parsing.declarations.custom_error import CustomErrorSolc |
|
|
|
from slither.solc_parsing.declarations.custom_error import CustomErrorSolc |
|
|
@ -574,7 +574,7 @@ class ContractSolc(CallerContextExpression): |
|
|
|
except (VariableNotFound, KeyError) as e: |
|
|
|
except (VariableNotFound, KeyError) as e: |
|
|
|
self.log_incorrect_parsing(f"Missing state variable {e}") |
|
|
|
self.log_incorrect_parsing(f"Missing state variable {e}") |
|
|
|
|
|
|
|
|
|
|
|
def analyze_using_for(self): |
|
|
|
def analyze_using_for(self): # pylint: disable=too-many-branches |
|
|
|
try: |
|
|
|
try: |
|
|
|
for father in self._contract.inheritance: |
|
|
|
for father in self._contract.inheritance: |
|
|
|
self._contract.using_for.update(father.using_for) |
|
|
|
self._contract.using_for.update(father.using_for) |
|
|
@ -593,18 +593,7 @@ class ContractSolc(CallerContextExpression): |
|
|
|
) |
|
|
|
) |
|
|
|
else: |
|
|
|
else: |
|
|
|
# We have a list of functions. A function can be topLevel or a library function |
|
|
|
# We have a list of functions. A function can be topLevel or a library function |
|
|
|
# at this point library function are yet to be parsed so we add the function name |
|
|
|
self._analyze_function_list(using_for["functionList"], type_name) |
|
|
|
# and add the real function later |
|
|
|
|
|
|
|
for f in using_for["functionList"]: |
|
|
|
|
|
|
|
function_name = f["function"]["name"] |
|
|
|
|
|
|
|
if function_name.find(".") != -1: |
|
|
|
|
|
|
|
# Library function |
|
|
|
|
|
|
|
self._contract.using_for[type_name].append(function_name) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
# Top level function |
|
|
|
|
|
|
|
for tl_function in self.compilation_unit.functions_top_level: |
|
|
|
|
|
|
|
if tl_function.name == function_name: |
|
|
|
|
|
|
|
self._contract.using_for[type_name].append(tl_function) |
|
|
|
|
|
|
|
else: |
|
|
|
else: |
|
|
|
for using_for in self._usingForNotParsed: |
|
|
|
for using_for in self._usingForNotParsed: |
|
|
|
children = using_for[self.get_children()] |
|
|
|
children = using_for[self.get_children()] |
|
|
@ -622,34 +611,42 @@ class ContractSolc(CallerContextExpression): |
|
|
|
except (VariableNotFound, KeyError) as e: |
|
|
|
except (VariableNotFound, KeyError) as e: |
|
|
|
self.log_incorrect_parsing(f"Missing using for {e}") |
|
|
|
self.log_incorrect_parsing(f"Missing using for {e}") |
|
|
|
|
|
|
|
|
|
|
|
def analyze_library_function_using_for(self): |
|
|
|
def _analyze_function_list(self, function_list: List, type_name: Type): |
|
|
|
for type_name, full_names in self._contract.using_for.items(): |
|
|
|
for f in function_list: |
|
|
|
# If it's a string is a library function e.g. L.a |
|
|
|
function_name = f["function"]["name"] |
|
|
|
# We add the actual function and remove the string |
|
|
|
if function_name.find(".") != -1: |
|
|
|
for full_name in full_names: |
|
|
|
# Library function |
|
|
|
if isinstance(full_name, str): |
|
|
|
self._analyze_library_function(function_name, type_name) |
|
|
|
full_name_split = full_name.split(".") |
|
|
|
else: |
|
|
|
# TODO this doesn't handle the case if there is an import with an alias |
|
|
|
# Top level function |
|
|
|
# e.g. MyImport.MyLib.a |
|
|
|
for tl_function in self.compilation_unit.functions_top_level: |
|
|
|
if len(full_name_split) == 2: |
|
|
|
if tl_function.name == function_name: |
|
|
|
library_name = full_name_split[0] |
|
|
|
self._contract.using_for[type_name].append(tl_function) |
|
|
|
function_name = full_name_split[1] |
|
|
|
|
|
|
|
# Get the library function |
|
|
|
def _analyze_library_function(self, function_name: str, type_name: Type) -> None: |
|
|
|
found = False |
|
|
|
function_name_split = function_name.split(".") |
|
|
|
for c in self.compilation_unit.contracts: |
|
|
|
# TODO this doesn't handle the case if there is an import with an alias |
|
|
|
if found: |
|
|
|
# e.g. MyImport.MyLib.a |
|
|
|
break |
|
|
|
if len(function_name_split) == 2: |
|
|
|
if c.name == library_name: |
|
|
|
library_name = function_name_split[0] |
|
|
|
for f in c.functions: |
|
|
|
function_name = function_name_split[1] |
|
|
|
if f.name == function_name: |
|
|
|
# Get the library function |
|
|
|
self._contract.using_for[type_name].append(f) |
|
|
|
found = False |
|
|
|
found = True |
|
|
|
for c in self.compilation_unit.contracts: |
|
|
|
break |
|
|
|
if found: |
|
|
|
self._contract.using_for[type_name].remove(full_name) |
|
|
|
break |
|
|
|
else: |
|
|
|
if c.name == library_name: |
|
|
|
self.log_incorrect_parsing( |
|
|
|
for f in c.functions: |
|
|
|
f"Expected library function instead received {full_name}" |
|
|
|
if f.name == function_name: |
|
|
|
) |
|
|
|
self._contract.using_for[type_name].append(f) |
|
|
|
|
|
|
|
found = True |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
if not found: |
|
|
|
|
|
|
|
self.log_incorrect_parsing(f"Library function not found {function_name}") |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
self.log_incorrect_parsing( |
|
|
|
|
|
|
|
f"Expected library function instead received {function_name}" |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def analyze_enums(self): |
|
|
|
def analyze_enums(self): |
|
|
|
try: |
|
|
|
try: |
|
|
|