Add self.add_X_to_json to AbstractPrinter

Refactor contract summary and human summary
pull/356/head
Josselin 5 years ago
parent 721e5592b9
commit 1cd7dc80d5
  1. 5
      slither/__main__.py
  2. 28
      slither/printers/abstract_printer.py
  3. 8
      slither/printers/call/call_graph.py
  4. 3
      slither/printers/functions/authorization.py
  5. 4
      slither/printers/functions/cfg.py
  6. 1
      slither/printers/inheritance/inheritance.py
  7. 3
      slither/printers/inheritance/inheritance_graph.py
  8. 55
      slither/printers/summary/contract.py
  9. 2
      slither/printers/summary/data_depenency.py
  10. 3
      slither/printers/summary/function.py
  11. 3
      slither/printers/summary/function_ids.py
  12. 8
      slither/printers/summary/human_summary.py
  13. 3
      slither/printers/summary/modifier_calls.py
  14. 3
      slither/printers/summary/require_calls.py
  15. 2
      slither/printers/summary/slithir_ssa.py
  16. 3
      slither/printers/summary/variable_order.py

@ -604,11 +604,12 @@ def main_impl(all_detector_classes, all_printer_classes):
# Dont print the number of result for printers # Dont print the number of result for printers
if number_contracts == 0: if number_contracts == 0:
logger.warn(red('No contract was analyzed')) logger.warning(red('No contract was analyzed'))
if printer_classes: if printer_classes:
logger.info('%s analyzed (%d contracts)', filename, number_contracts) logger.info('%s analyzed (%d contracts)', filename, number_contracts)
else: else:
logger.info('%s analyzed (%d contracts with %d detectors), %d result(s) found', filename, number_contracts, len(detector_classes), len(results)) logger.info('%s analyzed (%d contracts with %d detectors), %d result(s) found', filename,
number_contracts, len(detector_classes), len(results_detectors))
if args.ignore_return_value: if args.ignore_return_value:
return return

@ -33,12 +33,38 @@ class AbstractPrinter(metaclass=abc.ABCMeta):
self.logger.info(info) self.logger.info(info)
def generate_json_result(self, info, additional_fields={}): def generate_json_result(self, info, additional_fields=None):
if additional_fields is None:
additional_fields = {}
d = json_utils.generate_json_result(info, additional_fields) d = json_utils.generate_json_result(info, additional_fields)
d['printer'] = self.ARGUMENT d['printer'] = self.ARGUMENT
return d return d
@staticmethod
def add_contract_to_json(e, d, additional_fields=None):
json_utils.add_contract_to_json(e, d, additional_fields=additional_fields)
@staticmethod
def add_function_to_json(e, d, additional_fields=None):
json_utils.add_function_to_json(e, d, additional_fields=additional_fields)
@staticmethod
def add_functions_to_json(e, d, additional_fields=None):
json_utils.add_functions_to_json(e, d, additional_fields=additional_fields)
@staticmethod
def add_file_to_json(e, content, d, additional_fields=None):
json_utils.add_file_to_json(e, content, d, additional_fields)
@staticmethod
def add_pretty_table_to_json(e, content, d, additional_fields=None):
json_utils.add_pretty_table_to_json(e, content, d, additional_fields)
@staticmethod
def add_other_to_json(name, source_mapping, d, slither, additional_fields=None):
json_utils.add_other_to_json(name, source_mapping, d, slither, additional_fields)
@abc.abstractmethod @abc.abstractmethod
def output(self, filename): def output(self, filename):
"""TODO Documentation""" """TODO Documentation"""

@ -9,14 +9,8 @@ from collections import defaultdict
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.core.declarations.solidity_variables import SolidityFunction from slither.core.declarations.solidity_variables import SolidityFunction
from slither.core.declarations.function import Function from slither.core.declarations.function import Function
from slither.core.declarations.contract import Contract
from slither.core.expressions.member_access import MemberAccess
from slither.core.expressions.identifier import Identifier
from slither.core.variables.variable import Variable from slither.core.variables.variable import Variable
from slither.core.solidity_types.user_defined_type import UserDefinedType
# return unique id for contract to use as subgraph name
from slither.utils import json_utils
def _contract_subgraph(contract): def _contract_subgraph(contract):
@ -184,7 +178,7 @@ class PrinterCallGraph(AbstractPrinter):
self.info(info) self.info(info)
json = self.generate_json_result(info) json = self.generate_json_result(info)
for filename, content in results: for filename, content in results:
json_utils.add_file_to_json(filename, content, json) self.add_file_to_json(filename, content, json)
return json return json

@ -5,7 +5,6 @@
from prettytable import PrettyTable from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.core.declarations.function import Function from slither.core.declarations.function import Function
from slither.utils import json_utils
class PrinterWrittenVariablesAndAuthorization(AbstractPrinter): class PrinterWrittenVariablesAndAuthorization(AbstractPrinter):
@ -51,6 +50,6 @@ class PrinterWrittenVariablesAndAuthorization(AbstractPrinter):
self.info(txt) self.info(txt)
json = self.generate_json_result(txt) json = self.generate_json_result(txt)
for name, table in all_tables: for name, table in all_tables:
json_utils.add_pretty_table_to_json(table, name, json) self.add_pretty_table_to_json(table, name, json)
return json return json

@ -2,8 +2,6 @@
""" """
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.core.declarations.function import Function
from slither.utils import json_utils
class CFG(AbstractPrinter): class CFG(AbstractPrinter):
@ -35,5 +33,5 @@ class CFG(AbstractPrinter):
json = self.generate_json_result(info) json = self.generate_json_result(info)
for filename, content in all_files: for filename, content in all_files:
json_utils.add_file_to_json(filename, content, json) self.add_file_to_json(filename, content, json)
return json return json

@ -5,7 +5,6 @@
""" """
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
from slither.utils.colors import blue, green from slither.utils.colors import blue, green

@ -9,7 +9,6 @@
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.solidity_types.user_defined_type import UserDefinedType from slither.core.solidity_types.user_defined_type import UserDefinedType
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
from slither.utils.inheritance_analysis import (detect_c3_function_shadowing, from slither.utils.inheritance_analysis import (detect_c3_function_shadowing,
detect_state_variable_shadowing) detect_state_variable_shadowing)
@ -174,6 +173,6 @@ class PrinterInheritanceGraph(AbstractPrinter):
f.write(content) f.write(content)
json = self.generate_json_result(info) json = self.generate_json_result(info)
json_utils.add_file_to_json(filename, content, json) self.add_file_to_json(filename, content, json)
return json return json

@ -3,11 +3,10 @@
""" """
import collections import collections
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
from slither.utils.colors import blue, green, magenta from slither.utils.colors import blue, green, magenta
class ContractSummary(AbstractPrinter):
class ContractSummary(AbstractPrinter):
ARGUMENT = 'contract-summary' ARGUMENT = 'contract-summary'
HELP = 'Print a summary of the contracts' HELP = 'Print a summary of the contracts'
@ -21,42 +20,42 @@ class ContractSummary(AbstractPrinter):
""" """
txt = "" txt = ""
result = {}
all_contracts = []
for c in self.contracts: for c in self.contracts:
(name, _inheritance, _var, func_summaries, _modif_summaries) = c.get_summary(False) txt += blue("\n+ Contract %s\n" % c.name)
txt += blue("\n+ Contract %s\n"%name) additional_fields = {"elements": []}
result[name] = {}
# (c_name, f_name, visi, _, _, _, _, _) in func_summaries
public = [(elem[0], (elem[1], elem[2]) ) for elem in func_summaries]
# Order the function with
# contract_declarer -> list_functions
public = [(f.contract_declarer.name, f) for f in c.functions if (not f.is_shadowed)]
collect = collections.defaultdict(list) collect = collections.defaultdict(list)
for a,b in public: for a, b in public:
collect[a].append(b) collect[a].append(b)
public = list(collect.items()) public = list(collect.items())
for contract, functions in public: for contract, functions in public:
txt += blue(" - From {}\n".format(contract)) txt += blue(" - From {}\n".format(contract))
result[name]['from'] = str(contract)
functions = sorted(functions) functions = sorted(functions, key=lambda f: f.full_name)
result[name]['functions'] = {}
result[name]['functions']['visible'] = [] for function in functions:
result[name]['functions']['invisible'] = [] if function.visibility in ['external', 'public']:
result[name]['functions']['others'] = [] txt += green(" - {} ({})\n".format(function, function.visibility))
for (function, visi) in functions: if function.visibility in ['internal', 'private']:
if visi in ['external', 'public']: txt += magenta(" - {} ({})\n".format(function, function.visibility))
result[name]['functions']['visible'].append({'function': function, 'visi': visi}) if function.visibility not in ['external', 'public', 'internal', 'private']:
txt += green(" - {} ({})\n".format(function, visi)) txt += " - {}  ({})\n".format(function, function.visibility)
for (function, visi) in functions:
if visi in ['internal', 'private']: self.add_function_to_json(function, additional_fields, additional_fields={"visibility":
result[name]['functions']['invisible'].append({'function': function, 'visi': visi}) function.visibility})
txt += magenta(" - {} ({})\n".format(function, visi))
for (function, visi) in functions: all_contracts.append((c, additional_fields))
if visi not in ['external', 'public', 'internal', 'private']:
result[name]['functions']['others'].append({'function': function, 'visi': visi})
txt += " - {}  ({})\n".format(function, visi)
self.info(txt) self.info(txt)
json = self.generate_json_result(txt, additional_fields=result) json = self.generate_json_result(txt)
for contract, additional_fields in all_contracts:
self.add_contract_to_json(contract, json, additional_fields=additional_fields)
return json return json

@ -53,6 +53,6 @@ class DataDependency(AbstractPrinter):
json = self.generate_json_result(all_txt) json = self.generate_json_result(all_txt)
for name, table in all_tables: for name, table in all_tables:
json_utils.add_pretty_table_to_json(table, name, json) self.add_pretty_table_to_json(table, name, json)
return json return json

@ -4,7 +4,6 @@
from prettytable import PrettyTable from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
class FunctionSummary(AbstractPrinter): class FunctionSummary(AbstractPrinter):
@ -73,6 +72,6 @@ class FunctionSummary(AbstractPrinter):
json = self.generate_json_result(all_txt) json = self.generate_json_result(all_txt)
for name, table in all_tables: for name, table in all_tables:
json_utils.add_pretty_table_to_json(table, name, json) self.add_pretty_table_to_json(table, name, json)
return json return json

@ -4,7 +4,6 @@
from prettytable import PrettyTable from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
from slither.utils.function import get_function_id from slither.utils.function import get_function_id
class FunctionIds(AbstractPrinter): class FunctionIds(AbstractPrinter):
@ -40,6 +39,6 @@ class FunctionIds(AbstractPrinter):
json = self.generate_json_result(txt) json = self.generate_json_result(txt)
for name, table in all_tables: for name, table in all_tables:
json_utils.add_pretty_table_to_json(table, name, json) self.add_pretty_table_to_json(table, name, json)
return json return json

@ -4,7 +4,6 @@ Module printing summary of the contract
import logging import logging
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
from slither.utils.code_complexity import compute_cyclomatic_complexity from slither.utils.code_complexity import compute_cyclomatic_complexity
from slither.utils.colors import green, red, yellow from slither.utils.colors import green, red, yellow
from slither.utils.standard_libraries import is_standard_library from slither.utils.standard_libraries import is_standard_library
@ -197,7 +196,9 @@ class PrinterHumanSummary(AbstractPrinter):
txt += self._compilation_type() txt += self._compilation_type()
results = { results = {
'contracts': [], 'contracts': {
"elements": []
},
'number_lines': 0, 'number_lines': 0,
'number_lines_in_dependencies': 0, 'number_lines_in_dependencies': 0,
'standard_libraries': [], 'standard_libraries': [],
@ -260,7 +261,8 @@ class PrinterHumanSummary(AbstractPrinter):
else: else:
contract_d['erc20_can_mint'] = False contract_d['erc20_can_mint'] = False
contract_d['erc20_race_condition_mitigated'] = race_condition_mitigated contract_d['erc20_race_condition_mitigated'] = race_condition_mitigated
results['contracts'].append(contract_d)
self.add_contract_to_json(contract, results['contracts'], additional_fields=contract_d)
json = self.generate_json_result(txt, additional_fields=results) json = self.generate_json_result(txt, additional_fields=results)

@ -5,7 +5,6 @@
from prettytable import PrettyTable from prettytable import PrettyTable
from slither.core.declarations import Function from slither.core.declarations import Function
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
class Modifiers(AbstractPrinter): class Modifiers(AbstractPrinter):
@ -43,6 +42,6 @@ class Modifiers(AbstractPrinter):
json = self.generate_json_result(all_txt) json = self.generate_json_result(all_txt)
for name, table in all_tables: for name, table in all_tables:
json_utils.add_pretty_table_to_json(table, name, json) self.add_pretty_table_to_json(table, name, json)
return json return json

@ -6,7 +6,6 @@ from prettytable import PrettyTable
from slither.core.declarations import SolidityFunction from slither.core.declarations import SolidityFunction
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.slithir.operations import SolidityCall from slither.slithir.operations import SolidityCall
from slither.utils import json_utils
require_or_assert = [SolidityFunction("assert(bool)"), require_or_assert = [SolidityFunction("assert(bool)"),
SolidityFunction("require(bool)"), SolidityFunction("require(bool)"),
@ -48,6 +47,6 @@ class RequireOrAssert(AbstractPrinter):
json = self.generate_json_result(all_txt) json = self.generate_json_result(all_txt)
for name, table in all_tables: for name, table in all_tables:
json_utils.add_pretty_table_to_json(table, name, json) self.add_pretty_table_to_json(table, name, json)
return json return json

@ -3,7 +3,7 @@
""" """
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils.colors import blue, green, magenta
class PrinterSlithIRSSA(AbstractPrinter): class PrinterSlithIRSSA(AbstractPrinter):

@ -4,7 +4,6 @@
from prettytable import PrettyTable from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils import json_utils
class VariableOrder(AbstractPrinter): class VariableOrder(AbstractPrinter):
@ -39,6 +38,6 @@ class VariableOrder(AbstractPrinter):
json = self.generate_json_result(txt) json = self.generate_json_result(txt)
for name, table in all_tables: for name, table in all_tables:
json_utils.add_pretty_table_to_json(table, name, json) self.add_pretty_table_to_json(table, name, json)
return json return json
Loading…
Cancel
Save