Merge pull request #460 from crytic/dev-myprettytable

Add wrapper around PrettyTable
pull/463/head
Feist Josselin 5 years ago committed by GitHub
commit fc4cc3bad9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      scripts/travis_test_printers.sh
  2. 4
      slither/printers/functions/authorization.py
  3. 7
      slither/printers/summary/data_depenency.py
  4. 28
      slither/printers/summary/function.py
  5. 6
      slither/printers/summary/function_ids.py
  6. 6
      slither/printers/summary/modifier_calls.py
  7. 6
      slither/printers/summary/require_calls.py
  8. 4
      slither/printers/summary/variable_order.py
  9. 6
      slither/tools/properties/__main__.py
  10. 15
      slither/tools/upgradeability/utils/command_line.py
  11. 18
      slither/utils/command_line.py
  12. 28
      slither/utils/myprettytable.py
  13. 6
      slither/utils/output.py

@ -5,7 +5,7 @@
# Needed for evm printer # Needed for evm printer
pip install evm-cfg-builder pip install evm-cfg-builder
slither "tests/*.json" --print all slither "tests/*.json" --print all --json -
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Printer tests failed" echo "Printer tests failed"

@ -2,9 +2,9 @@
Module printing summary of the contract Module printing summary of the contract
""" """
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.myprettytable import MyPrettyTable
class PrinterWrittenVariablesAndAuthorization(AbstractPrinter): class PrinterWrittenVariablesAndAuthorization(AbstractPrinter):
@ -38,7 +38,7 @@ class PrinterWrittenVariablesAndAuthorization(AbstractPrinter):
all_tables = [] all_tables = []
for contract in self.contracts: for contract in self.contracts:
txt += "\nContract %s\n"%contract.name txt += "\nContract %s\n"%contract.name
table = PrettyTable(["Function", "State variables written", "Conditions on msg.sender"]) table = MyPrettyTable(["Function", "State variables written", "Conditions on msg.sender"])
for function in contract.functions: for function in contract.functions:
state_variables_written = [v.name for v in function.all_state_variables_written()] state_variables_written = [v.name for v in function.all_state_variables_written()]

@ -2,10 +2,11 @@
Module printing summary of the contract Module printing summary of the contract
""" """
from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.analyses.data_dependency.data_dependency import get_dependencies from slither.analyses.data_dependency.data_dependency import get_dependencies
from slither.slithir.variables import TemporaryVariable, ReferenceVariable from slither.slithir.variables import TemporaryVariable, ReferenceVariable
from slither.utils.myprettytable import MyPrettyTable
def _get(v, c): def _get(v, c):
return list(set([d.name for d in get_dependencies(v, c) if not isinstance(d, (TemporaryVariable, return list(set([d.name for d in get_dependencies(v, c) if not isinstance(d, (TemporaryVariable,
@ -31,7 +32,7 @@ class DataDependency(AbstractPrinter):
txt = '' txt = ''
for c in self.contracts: for c in self.contracts:
txt += "\nContract %s\n"%c.name txt += "\nContract %s\n"%c.name
table = PrettyTable(['Variable', 'Dependencies']) table = MyPrettyTable(['Variable', 'Dependencies'])
for v in c.state_variables: for v in c.state_variables:
table.add_row([v.name, _get(v, c)]) table.add_row([v.name, _get(v, c)])
@ -40,7 +41,7 @@ class DataDependency(AbstractPrinter):
txt += "\n" txt += "\n"
for f in c.functions_and_modifiers_declared: for f in c.functions_and_modifiers_declared:
txt += "\nFunction %s\n"%f.full_name txt += "\nFunction %s\n"%f.full_name
table = PrettyTable(['Variable', 'Dependencies']) table = MyPrettyTable(['Variable', 'Dependencies'])
for v in f.variables: for v in f.variables:
table.add_row([v.name, _get(v, f)]) table.add_row([v.name, _get(v, f)])
for v in c.state_variables: for v in c.state_variables:

@ -2,8 +2,8 @@
Module printing summary of the contract Module printing summary of the contract
""" """
from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils.myprettytable import MyPrettyTable
class FunctionSummary(AbstractPrinter): class FunctionSummary(AbstractPrinter):
@ -37,13 +37,13 @@ class FunctionSummary(AbstractPrinter):
txt = "\nContract %s"%name txt = "\nContract %s"%name
txt += '\nContract vars: '+str(var) txt += '\nContract vars: '+str(var)
txt += '\nInheritance:: '+str(inheritance) txt += '\nInheritance:: '+str(inheritance)
table = PrettyTable(["Function", table = MyPrettyTable(["Function",
"Visibility", "Visibility",
"Modifiers", "Modifiers",
"Read", "Read",
"Write", "Write",
"Internal Calls", "Internal Calls",
"External Calls"]) "External Calls"])
for (_c_name, f_name, visi, modifiers, read, write, internal_calls, external_calls) in func_summaries: for (_c_name, f_name, visi, modifiers, read, write, internal_calls, external_calls) in func_summaries:
read = self._convert(read) read = self._convert(read)
write = self._convert(write) write = self._convert(write)
@ -51,12 +51,12 @@ class FunctionSummary(AbstractPrinter):
external_calls = self._convert(external_calls) external_calls = self._convert(external_calls)
table.add_row([f_name, visi, modifiers, read, write, internal_calls, external_calls]) table.add_row([f_name, visi, modifiers, read, write, internal_calls, external_calls])
txt += "\n \n"+str(table) txt += "\n \n"+str(table)
table = PrettyTable(["Modifiers", table = MyPrettyTable(["Modifiers",
"Visibility", "Visibility",
"Read", "Read",
"Write", "Write",
"Internal Calls", "Internal Calls",
"External Calls"]) "External Calls"])
for (_c_name, f_name, visi, _, read, write, internal_calls, external_calls) in modif_summaries: for (_c_name, f_name, visi, _, read, write, internal_calls, external_calls) in modif_summaries:
read = self._convert(read) read = self._convert(read)
write = self._convert(write) write = self._convert(write)

@ -1,10 +1,10 @@
""" """
Module printing summary of the contract Module printing summary of the contract
""" """
from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils.function import get_function_id from slither.utils.function import get_function_id
from slither.utils.myprettytable import MyPrettyTable
class FunctionIds(AbstractPrinter): class FunctionIds(AbstractPrinter):
@ -24,7 +24,7 @@ class FunctionIds(AbstractPrinter):
all_tables = [] all_tables = []
for contract in self.slither.contracts_derived: for contract in self.slither.contracts_derived:
txt += '\n{}:\n'.format(contract.name) txt += '\n{}:\n'.format(contract.name)
table = PrettyTable(['Name', 'ID']) table = MyPrettyTable(['Name', 'ID'])
for function in contract.functions: for function in contract.functions:
if function.visibility in ['public', 'external']: if function.visibility in ['public', 'external']:
table.add_row([function.solidity_signature, hex(get_function_id(function.solidity_signature))]) table.add_row([function.solidity_signature, hex(get_function_id(function.solidity_signature))])

@ -2,9 +2,9 @@
Module printing summary of the contract Module printing summary of the contract
""" """
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.myprettytable import MyPrettyTable
class Modifiers(AbstractPrinter): class Modifiers(AbstractPrinter):
@ -26,8 +26,8 @@ class Modifiers(AbstractPrinter):
for contract in self.slither.contracts_derived: for contract in self.slither.contracts_derived:
txt = "\nContract %s"%contract.name txt = "\nContract %s"%contract.name
table = PrettyTable(["Function", table = MyPrettyTable(["Function",
"Modifiers"]) "Modifiers"])
for function in contract.functions: for function in contract.functions:
modifiers = function.modifiers modifiers = function.modifiers
for call in function.all_internal_calls(): for call in function.all_internal_calls():

@ -2,10 +2,10 @@
Module printing summary of the contract Module printing summary of the contract
""" """
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.myprettytable import MyPrettyTable
require_or_assert = [SolidityFunction("assert(bool)"), require_or_assert = [SolidityFunction("assert(bool)"),
SolidityFunction("require(bool)"), SolidityFunction("require(bool)"),
@ -33,8 +33,8 @@ class RequireOrAssert(AbstractPrinter):
all_txt = '' all_txt = ''
for contract in self.slither.contracts_derived: for contract in self.slither.contracts_derived:
txt = "\nContract %s"%contract.name txt = "\nContract %s"%contract.name
table = PrettyTable(["Function", table = MyPrettyTable(["Function",
"require or assert"]) "require or assert"])
for function in contract.functions: for function in contract.functions:
require = function.all_slithir_operations() require = function.all_slithir_operations()
require = [ir for ir in require if isinstance(ir, SolidityCall) and ir.function in require_or_assert] require = [ir for ir in require if isinstance(ir, SolidityCall) and ir.function in require_or_assert]

@ -2,8 +2,8 @@
Module printing summary of the contract Module printing summary of the contract
""" """
from prettytable import PrettyTable
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.utils.myprettytable import MyPrettyTable
class VariableOrder(AbstractPrinter): class VariableOrder(AbstractPrinter):
@ -26,7 +26,7 @@ class VariableOrder(AbstractPrinter):
for contract in self.slither.contracts_derived: for contract in self.slither.contracts_derived:
txt += '\n{}:\n'.format(contract.name) txt += '\n{}:\n'.format(contract.name)
table = PrettyTable(['Name', 'Type']) table = MyPrettyTable(['Name', 'Type'])
for variable in contract.state_variables_ordered: for variable in contract.state_variables_ordered:
if not variable.is_constant: if not variable.is_constant:
table.add_row([variable.canonical_name, str(variable.type)]) table.add_row([variable.canonical_name, str(variable.type)])

@ -1,16 +1,14 @@
import os
import argparse import argparse
import logging import logging
import sys import sys
from prettytable import PrettyTable
from slither import Slither from slither import Slither
from crytic_compile import cryticparser from crytic_compile import cryticparser
from slither.tools.properties.addresses.address import Addresses from slither.tools.properties.addresses.address import Addresses
from slither.tools.properties.properties.erc20 import generate_erc20, ERC20_PROPERTIES from slither.tools.properties.properties.erc20 import generate_erc20, ERC20_PROPERTIES
from slither.tools.properties.addresses.address import OWNER_ADDRESS, USER_ADDRESS, ATTACKER_ADDRESS from slither.tools.properties.addresses.address import OWNER_ADDRESS, USER_ADDRESS, ATTACKER_ADDRESS
from slither.utils.myprettytable import MyPrettyTable
logging.basicConfig() logging.basicConfig()
logging.getLogger("Slither").setLevel(logging.INFO) logging.getLogger("Slither").setLevel(logging.INFO)
@ -33,7 +31,7 @@ def _all_scenarios():
return txt return txt
def _all_properties(): def _all_properties():
table = PrettyTable(["Num", "Description", "Scenario"]) table = MyPrettyTable(["Num", "Description", "Scenario"])
idx = 0 idx = 0
for scenario, value in ERC20_PROPERTIES.items(): for scenario, value in ERC20_PROPERTIES.items():
for prop in value.properties: for prop in value.properties:

@ -1,6 +1,5 @@
from prettytable import PrettyTable
from slither.tools.upgradeability.checks.abstract_checks import classification_txt from slither.tools.upgradeability.checks.abstract_checks import classification_txt
from slither.utils.myprettytable import MyPrettyTable
def output_wiki(detector_classes, filter_wiki): def output_wiki(detector_classes, filter_wiki):
@ -39,12 +38,12 @@ def output_detectors(detector_classes):
require_proxy = detector.REQUIRE_PROXY require_proxy = detector.REQUIRE_PROXY
require_v2 = detector.REQUIRE_CONTRACT_V2 require_v2 = detector.REQUIRE_CONTRACT_V2
detectors_list.append((argument, help_info, impact, require_proxy, require_v2)) detectors_list.append((argument, help_info, impact, require_proxy, require_v2))
table = PrettyTable(["Num", table = MyPrettyTable(["Num",
"Check", "Check",
"What it Detects", "What it Detects",
"Impact", "Impact",
"Proxy", "Proxy",
"Contract V2"]) "Contract V2"])
# Sort by impact, confidence, and name # Sort by impact, confidence, and name
detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[0])) detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[0]))

@ -2,11 +2,11 @@ import json
import os import os
import logging import logging
from collections import defaultdict from collections import defaultdict
from prettytable import PrettyTable
from crytic_compile.cryticparser.defaults import DEFAULTS_FLAG_IN_CONFIG as DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE from crytic_compile.cryticparser.defaults import DEFAULTS_FLAG_IN_CONFIG as DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE
from slither.detectors.abstract_detector import classification_txt from slither.detectors.abstract_detector import classification_txt
from .colors import yellow, red from .colors import yellow, red
from .myprettytable import MyPrettyTable
logger = logging.getLogger("Slither") logger = logging.getLogger("Slither")
@ -192,11 +192,11 @@ def output_detectors(detector_classes):
impact = detector.IMPACT impact = detector.IMPACT
confidence = classification_txt[detector.CONFIDENCE] confidence = classification_txt[detector.CONFIDENCE]
detectors_list.append((argument, help_info, impact, confidence)) detectors_list.append((argument, help_info, impact, confidence))
table = PrettyTable(["Num", table = MyPrettyTable(["Num",
"Check", "Check",
"What it Detects", "What it Detects",
"Impact", "Impact",
"Confidence"]) "Confidence"])
# Sort by impact, confidence, and name # Sort by impact, confidence, and name
detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[3], element[0])) detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[3], element[0]))
@ -254,9 +254,9 @@ def output_printers(printer_classes):
argument = printer.ARGUMENT argument = printer.ARGUMENT
help_info = printer.HELP help_info = printer.HELP
printers_list.append((argument, help_info)) printers_list.append((argument, help_info))
table = PrettyTable(["Num", table = MyPrettyTable(["Num",
"Printer", "Printer",
"What it Does"]) "What it Does"])
# Sort by impact, confidence, and name # Sort by impact, confidence, and name
printers_list = sorted(printers_list, key=lambda element: (element[0])) printers_list = sorted(printers_list, key=lambda element: (element[0]))

@ -0,0 +1,28 @@
from typing import List, Dict
from prettytable import PrettyTable
class MyPrettyTable:
def __init__(self, field_names: List[str]):
self._field_names = field_names
self._rows: List = []
def add_row(self, row):
self._rows.append(row)
def to_pretty_table(self):
table = PrettyTable(self._field_names)
for row in self._rows:
table.add_row(row)
return table
def to_json(self) -> Dict:
return {
'fields_names': self._field_names,
'rows': self._rows
}
def __str__(self):
return str(self.to_pretty_table())

@ -13,6 +13,7 @@ from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.variable import Variable from slither.core.variables.variable import Variable
from slither.exceptions import SlitherError from slither.exceptions import SlitherError
from slither.utils.colors import yellow from slither.utils.colors import yellow
from slither.utils.myprettytable import MyPrettyTable
logger = logging.getLogger("Slither") logger = logging.getLogger("Slither")
@ -23,6 +24,7 @@ logger = logging.getLogger("Slither")
################################################################################### ###################################################################################
################################################################################### ###################################################################################
def output_to_json(filename, error, results): def output_to_json(filename, error, results):
""" """
@ -467,11 +469,11 @@ class Output:
################################################################################### ###################################################################################
################################################################################### ###################################################################################
def add_pretty_table(self, content, name, additional_fields=None): def add_pretty_table(self, content: MyPrettyTable, name, additional_fields=None):
if additional_fields is None: if additional_fields is None:
additional_fields = {} additional_fields = {}
type_specific_fields = { type_specific_fields = {
'content': content, 'content': content.to_json(),
'name': name 'name': name
} }
element = _create_base_element('pretty_table', element = _create_base_element('pretty_table',

Loading…
Cancel
Save