From 0b20aca729fdb372d2055f5e0d33163b74110a1e Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 31 Jan 2023 17:53:35 -0600 Subject: [PATCH 1/3] fix compilation unit missing in source API --- slither/core/source_mapping/source_mapping.py | 36 ++++++++----------- slither/printers/summary/declaration.py | 28 +++++++-------- slither/utils/source_mapping.py | 5 ++- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/slither/core/source_mapping/source_mapping.py b/slither/core/source_mapping/source_mapping.py index ee5211c7c2..2a1266e224 100644 --- a/slither/core/source_mapping/source_mapping.py +++ b/slither/core/source_mapping/source_mapping.py @@ -18,7 +18,7 @@ # pylint: disable=too-many-instance-attributes class Source: - def __init__(self) -> None: + def __init__(self, compilation_unit: "SlitherCompilationUnit") -> None: self.start: int = 0 self.length: int = 0 self.filename: Filename = Filename("", "", "", "") @@ -27,7 +27,7 @@ def __init__(self) -> None: self.starting_column: int = 0 self.ending_column: int = 0 self.end: int = 0 - self.compilation_unit: Optional["SlitherCompilationUnit"] = None + self.compilation_unit = compilation_unit def to_json(self) -> Dict: return { @@ -51,17 +51,16 @@ def to_markdown(self, markdown_root: str) -> str: filename_relative: str = self.filename.relative if self.filename.relative else "" return f"{markdown_root}{filename_relative}{lines}" - def to_detailled_str(self) -> str: + def to_detailed_str(self) -> str: lines = self._get_lines_str() filename_short: str = self.filename.short if self.filename.short else "" return f"{filename_short}{lines} ({self.starting_column} - {self.ending_column})" - def _get_lines_str(self, line_descr=""): - - # If the compilation unit was not initialized, it means that the set_offset was never called - # on the corresponding object, which should not happen - assert self.compilation_unit is not None + def span(self) -> str: + with open (self.filename.absolute, "r") as f: + return f.readlines()[self.start:self.end] + def _get_lines_str(self, line_descr=""): line_prefix = self.compilation_unit.core.line_prefix lines = self.lines @@ -105,6 +104,7 @@ def _compute_line( Not done in an efficient way """ + start_line, starting_column = compilation_unit.core.crytic_compile.get_line_from_offset( filename, start ) @@ -127,7 +127,7 @@ def _convert_source_mapping( position = re.findall("([0-9]*):([0-9]*):([-]?[0-9]*)", offset) if len(position) != 1: - return Source() + return Source(compilation_unit) s, l, f = position[0] s = int(s) @@ -135,7 +135,7 @@ def _convert_source_mapping( f = int(f) if f not in sourceUnits: - new_source = Source() + new_source = Source(compilation_unit) new_source.start = s new_source.length = l return new_source @@ -149,7 +149,7 @@ def _convert_source_mapping( (lines, starting_column, ending_column) = _compute_line(compilation_unit, filename, s, l) - new_source = Source() + new_source = Source(compilation_unit) new_source.start = s new_source.length = l new_source.filename = filename @@ -158,28 +158,22 @@ def _convert_source_mapping( new_source.starting_column = starting_column new_source.ending_column = ending_column new_source.end = new_source.start + l + return new_source class SourceMapping(Context, metaclass=ABCMeta): def __init__(self) -> None: super().__init__() - # self._source_mapping: Optional[Dict] = None - self.source_mapping: Source = Source() + self.source_mapping: Optional[Source] = None self.references: List[Source] = [] def set_offset( self, offset: Union["Source", str], compilation_unit: "SlitherCompilationUnit" ) -> None: + assert compilation_unit if isinstance(offset, Source): - self.source_mapping.start = offset.start - self.source_mapping.length = offset.length - self.source_mapping.filename = offset.filename - self.source_mapping.is_dependency = offset.is_dependency - self.source_mapping.lines = offset.lines - self.source_mapping.starting_column = offset.starting_column - self.source_mapping.ending_column = offset.ending_column - self.source_mapping.end = offset.end + self.source_mapping = offset else: self.source_mapping = _convert_source_mapping(offset, compilation_unit) self.source_mapping.compilation_unit = compilation_unit diff --git a/slither/printers/summary/declaration.py b/slither/printers/summary/declaration.py index 5888a1f00f..529aba5f08 100644 --- a/slither/printers/summary/declaration.py +++ b/slither/printers/summary/declaration.py @@ -20,37 +20,37 @@ def output(self, _filename): txt += "\n# Contracts\n" for contract in compilation_unit.contracts: txt += f"# {contract.name}\n" - txt += f"\t- Declaration: {get_definition(contract, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += f"\t- Implementation: {get_implementation(contract).to_detailled_str()}\n" + txt += f"\t- Declaration: {get_definition(contract, compilation_unit.core.crytic_compile).to_detailed_str()}\n" + txt += f"\t- Implementation: {get_implementation(contract).to_detailed_str()}\n" txt += ( - f"\t- References: {[x.to_detailled_str() for x in get_references(contract)]}\n" + f"\t- References: {[x.to_detailed_str() for x in get_references(contract)]}\n" ) txt += "\n\t## Function\n" for func in contract.functions: txt += f"\t\t- {func.canonical_name}\n" - txt += f"\t\t\t- Declaration: {get_definition(func, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += ( - f"\t\t\t- Implementation: {get_implementation(func).to_detailled_str()}\n" - ) - txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(func)]}\n" + txt += f"\t\t\t- Declaration: {get_definition(func, compilation_unit.core.crytic_compile).to_detailed_str()}\n" + txt += f"\t\t\t- Implementation: {get_implementation(func).to_detailed_str()}\n" + txt += f"\t\t\t- References: {[x.to_detailed_str() for x in get_references(func)]}\n" txt += "\n\t## State variables\n" for var in contract.state_variables: txt += f"\t\t- {var.name}\n" - txt += f"\t\t\t- Declaration: {get_definition(var, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += f"\t\t\t- Implementation: {get_implementation(var).to_detailled_str()}\n" - txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(var)]}\n" + txt += f"\t\t\t- Declaration: {get_definition(var, compilation_unit.core.crytic_compile).to_detailed_str()}\n" + txt += f"\t\t\t- Implementation: {get_implementation(var).to_detailed_str()}\n" + txt += f"\t\t\t- References: {[x.to_detailed_str() for x in get_references(var)]}\n" txt += "\n\t## Structures\n" for st in contract.structures: txt += f"\t\t- {st.name}\n" - txt += f"\t\t\t- Declaration: {get_definition(st, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += f"\t\t\t- Implementation: {get_implementation(st).to_detailled_str()}\n" - txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(st)]}\n" + txt += f"\t\t\t- Declaration: {get_definition(st, compilation_unit.core.crytic_compile).txt}\n" + txt += f"\t\t\t- Implementation: {get_implementation(st).to_detailed_str()}\n" + txt += ( + f"\t\t\t- References: {[x.to_detailed_str() for x in get_references(st)]}\n" + ) self.info(txt) res = self.generate_output(txt) diff --git a/slither/utils/source_mapping.py b/slither/utils/source_mapping.py index 26ad7c0d22..b117cd5f78 100644 --- a/slither/utils/source_mapping.py +++ b/slither/utils/source_mapping.py @@ -35,7 +35,7 @@ def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Sour target.source_mapping.filename, target.source_mapping.start + start_offset + len(pattern) ) - s = Source() + s = Source(target.source_mapping.compilation_unit) s.start = target.source_mapping.start + start_offset s.length = len(pattern) s.filename = target.source_mapping.filename @@ -44,8 +44,7 @@ def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Sour s.starting_column = starting_column s.ending_column = ending_column s.end = s.start + s.length - s.compilation_unit = target.compilation_unit - + s.txt = txt return s From 20fbfd45dfbb01abe3af0e32a57407f822fa3c90 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 16 Mar 2023 22:19:01 -0500 Subject: [PATCH 2/3] fix evm printer --- slither/printers/summary/evm.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slither/printers/summary/evm.py b/slither/printers/summary/evm.py index 660d912042..7e949b5156 100644 --- a/slither/printers/summary/evm.py +++ b/slither/printers/summary/evm.py @@ -21,8 +21,8 @@ def _extract_evm_info(slither): CFG = load_evm_cfg_builder() for contract in slither.contracts_derived: - contract_bytecode_runtime = contract.scope.bytecode_runtime(contract.name) - contract_srcmap_runtime = contract.scope.srcmap_runtime(contract.name) + contract_bytecode_runtime = contract.file_scope.bytecode_runtime(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) + contract_srcmap_runtime = contract.file_scope.srcmap_runtime(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) cfg = CFG(contract_bytecode_runtime) evm_info["cfg", contract.name] = cfg evm_info["mapping", contract.name] = generate_source_to_evm_ins_mapping( @@ -32,8 +32,8 @@ def _extract_evm_info(slither): contract.source_mapping.filename.absolute, ) - contract_bytecode_init = contract.scope.bytecode_init(contract.name) - contract_srcmap_init = contract.scope.srcmap_init(contract.name) + contract_bytecode_init = contract.file_scope.bytecode_init(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) + contract_srcmap_init = contract.file_scope.srcmap_init(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) cfg_init = CFG(contract_bytecode_init) evm_info["cfg_init", contract.name] = cfg_init From d6adbca5199ccadbf2947f0601882d444f83bdff Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 16 Mar 2023 22:21:19 -0500 Subject: [PATCH 3/3] update printer tests --- scripts/ci_test_printers.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index e542286fe4..f6eaf0fc84 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -5,11 +5,20 @@ cd tests/ast-parsing/compile || exit # Do not test the evm printer,as it needs a refactoring -ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,human-summary,inheritance,inheritance-graph,slithir,slithir-ssa,vars-and-auth,require,variable-order" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,human-summary,inheritance,inheritance-graph,slithir,slithir-ssa,vars-and-auth,require,variable-order,declaration" # Only test 0.5.17 to limit test time for file in *0.5.17-compact.zip; do - if ! slither "$file" --print "$ALL_PRINTERS" > /dev/null 2>&1 ; then + if ! slither "$file" --print "$ALL_PRINTERS" ; then + echo "Printer failed" + echo "$file" + exit 1 + fi +done + +# Only test 0.8.12 to limit test time +for file in *0.8.12-compact.zip; do + if ! slither "$file" --print "declaration" ; then echo "Printer failed" echo "$file" exit 1