Skip to content

Commit

Permalink
Add JSON output functionality for printers
Browse files Browse the repository at this point in the history
This changes the code to return the result as output if --json argument
is passed to printers.

Solves crytic#286
  • Loading branch information
Man-Jain committed Jul 31, 2019
1 parent 54241c0 commit 696c1c7
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 4 deletions.
19 changes: 18 additions & 1 deletion slither/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def _process(slither, detector_classes, printer_classes):

results.extend(detector_results)

slither.run_printers() # Currently printers does not return results
results.extend(slither.run_printers())

return slither, results, analyzed_contracts_count

Expand Down Expand Up @@ -429,6 +429,12 @@ def parse_args(detector_classes, printer_classes):
args = parser.parse_args()
read_config_file(args)

json_types_args = args.json_types.split(',')
if args.printers_to_run is not None and 'printers' not in json_types_args:
args.json_types = json_types_args.append('printers')
args.json_types = json_types_args.remove('detectors')
args.json_types = ','.join(json_types_args)

args.filter_paths = parse_filter_paths(args)

# Verify our json-type output is valid
Expand Down Expand Up @@ -458,6 +464,13 @@ def __call__(self, parser, *args, **kwargs):
output_printers(printers)
parser.exit()

class ListPrintersJson(argparse.Action):
def __call__(self, parser, *args, **kwargs):
_, printers = get_detectors_and_printers()
printer_types_json = output_printers_json(detectors)
print(json.dumps(printer_types_json))
parser.exit()

class OutputMarkdown(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
detectors, printers = get_detectors_and_printers()
Expand Down Expand Up @@ -597,6 +610,10 @@ def main_impl(all_detector_classes, all_printer_classes):
if results and 'detectors' in args.json_types:
json_results['detectors'] = results

# Add our printer results to JSON if desired.
if results and 'printers' in args.json_types:
json_results['printers'] = results

# Add our detector types to JSON
if 'list-detectors' in args.json_types:
detectors, _ = get_detectors_and_printers()
Expand Down
6 changes: 6 additions & 0 deletions slither/printers/inheritance/inheritance_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,20 @@ def output(self, filename):
Args:
filename(string)
"""
json_results = {}
if filename == '':
filename = 'contracts.dot'
if not filename.endswith('.dot'):
filename += ".dot"
info = 'Inheritance Graph: ' + filename
self.info(info)
json_results['filename'] = filename
with open(filename, 'w', encoding='utf8') as f:
f.write('digraph "" {\n')
json_results['digraph'] = []
for c in self.contracts:
json_results['digraph'].append(self._summary(c))
f.write(self._summary(c))
f.write('}')

return json_results
11 changes: 11 additions & 0 deletions slither/printers/summary/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ def output(self, _filename):
"""

txt = ""
json_result = {}
for c in self.contracts:
(name, _inheritance, _var, func_summaries, _modif_summaries) = c.get_summary()
txt += blue("\n+ Contract %s\n"%name)
json_result[name] = {}
# (c_name, f_name, visi, _, _, _, _, _) in func_summaries
public = [(elem[0], (elem[1], elem[2]) ) for elem in func_summaries]

Expand All @@ -33,15 +35,24 @@ def output(self, _filename):

for contract, functions in public:
txt += blue(" - From {}\n".format(contract))
json_result[name]['from'] = str(contract)
functions = sorted(functions)
json_result[name]['functions'] = {}
json_result[name]['functions']['visible'] = []
json_result[name]['functions']['invisible'] = []
json_result[name]['functions']['others'] = []
for (function, visi) in functions:
if visi in ['external', 'public']:
json_result[name]['functions']['visible'].append({'function':function,'visi':visi})
txt += green(" - {} ({})\n".format(function, visi))
for (function, visi) in functions:
if visi in ['internal', 'private']:
json_result[name]['functions']['invisible'].append({'function':function,'visi':visi})
txt += magenta(" - {} ({})\n".format(function, visi))
for (function, visi) in functions:
if visi not in ['external', 'public', 'internal', 'private']:
json_result[name]['functions']['others'].append({'function':function,'visi':visi})
txt += " - {}  ({})\n".format(function, visi)

self.info(txt)
return json_result
13 changes: 12 additions & 1 deletion slither/slither.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,18 @@ def run_printers(self):
:return: List of registered printers outputs.
"""

return [p.output(self.filename) for p in self._printers]
results = []

for p in self._printers:
result = p.output(self.filename)
result['name'] = p.ARGUMENT
if 'filename' in result:
result['result_type'] = 'graph'
else:
result['result_type'] = 'text'

results.append(result)
return results

def _check_common_things(self, thing_name, cls, base_cls, instances_list):

Expand Down
3 changes: 1 addition & 2 deletions slither/utils/command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
logger = logging.getLogger("Slither")

DEFAULT_JSON_OUTPUT_TYPES = ["detectors"]
JSON_OUTPUT_TYPES = ["compilations", "console", "detectors", "list-detectors", "list-printers"]

JSON_OUTPUT_TYPES = ["compilations", "console", "detectors", "list-detectors", "list-printers","printers"]

# Those are the flags shared by the command line and the config file
defaults_flag_in_config = {
Expand Down

0 comments on commit 696c1c7

Please sign in to comment.