Merge pull request #1765 from crytic/declaration-printer

fix declaration and evm printer
pull/1770/head
Feist Josselin 2 years ago committed by GitHub
commit f0603b4ea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      scripts/ci_test_printers.sh
  2. 31
      slither/core/source_mapping/source_mapping.py
  3. 28
      slither/printers/summary/declaration.py
  4. 16
      slither/printers/summary/evm.py
  5. 5
      slither/utils/source_mapping.py

@ -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

@ -18,7 +18,7 @@ if TYPE_CHECKING:
# 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 @@ class Source:
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,13 @@ class Source:
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: str = "") -> str:
# 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
line_prefix = self.compilation_unit.core.line_prefix
lines = self.lines
@ -129,6 +125,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
)
@ -151,7 +148,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)
@ -159,7 +156,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
@ -173,7 +170,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
@ -182,28 +179,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

@ -20,37 +20,37 @@ class Declaration(AbstractPrinter):
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)

@ -21,8 +21,12 @@ 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 +36,12 @@ 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

@ -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

Loading…
Cancel
Save