|
|
|
@ -1,14 +1,15 @@ |
|
|
|
|
import hashlib |
|
|
|
|
import json |
|
|
|
|
from jinja2 import PackageLoader, Environment |
|
|
|
|
|
|
|
|
|
class Issue: |
|
|
|
|
|
|
|
|
|
def __init__(self, contract, function, pc, title, _type="Informational", description="", debug=""): |
|
|
|
|
def __init__(self, contract, function, address, title, _type="Informational", description="", debug=""): |
|
|
|
|
|
|
|
|
|
self.title = title |
|
|
|
|
self.contract = contract |
|
|
|
|
self.function = function |
|
|
|
|
self.pc = pc |
|
|
|
|
self.address = address |
|
|
|
|
self.description = description |
|
|
|
|
self.type = _type |
|
|
|
|
self.debug = debug |
|
|
|
@ -18,7 +19,7 @@ class Issue: |
|
|
|
|
|
|
|
|
|
def as_dict(self): |
|
|
|
|
|
|
|
|
|
issue = {'title': self.title, 'description':self.description, 'function': self.function, 'type': self.type, 'address': self.pc, 'debug': self.debug} |
|
|
|
|
issue = {'title': self.title, 'description':self.description, 'function': self.function, 'type': self.type, 'address': self.address, 'debug': self.debug} |
|
|
|
|
|
|
|
|
|
if self.filename and self.lineno: |
|
|
|
|
issue['filename'] = self.filename |
|
|
|
@ -30,13 +31,14 @@ class Issue: |
|
|
|
|
return issue |
|
|
|
|
|
|
|
|
|
def add_code_info(self, contract): |
|
|
|
|
if self.pc: |
|
|
|
|
codeinfo = contract.get_source_info(self.pc) |
|
|
|
|
if self.address: |
|
|
|
|
codeinfo = contract.get_source_info(self.address) |
|
|
|
|
self.filename = codeinfo.filename |
|
|
|
|
self.code = codeinfo.code |
|
|
|
|
self.lineno = codeinfo.lineno |
|
|
|
|
|
|
|
|
|
class Report: |
|
|
|
|
environment = Environment(loader=PackageLoader('mythril.analysis')) |
|
|
|
|
|
|
|
|
|
def __init__(self, verbose=False): |
|
|
|
|
self.issues = {} |
|
|
|
@ -45,44 +47,16 @@ class Report: |
|
|
|
|
|
|
|
|
|
def append_issue(self, issue): |
|
|
|
|
m = hashlib.md5() |
|
|
|
|
m.update((issue.contract + str(issue.pc) + issue.title).encode('utf-8')) |
|
|
|
|
m.update((issue.contract + str(issue.address) + issue.title).encode('utf-8')) |
|
|
|
|
self.issues[m.digest()] = issue |
|
|
|
|
|
|
|
|
|
def as_text(self): |
|
|
|
|
text = "" |
|
|
|
|
|
|
|
|
|
for key, issue in self.issues.items(): |
|
|
|
|
|
|
|
|
|
text += "==== " + issue.title + " ====\n" |
|
|
|
|
text += "Type: " + issue.type + "\n" |
|
|
|
|
|
|
|
|
|
if len(issue.contract): |
|
|
|
|
text += "Contract: " + issue.contract + "\n" |
|
|
|
|
else: |
|
|
|
|
text += "Contract: Unknown\n" |
|
|
|
|
|
|
|
|
|
text += "Function name: " + issue.function + "\n" |
|
|
|
|
text += "PC address: " + str(issue.pc) + "\n" |
|
|
|
|
|
|
|
|
|
text += issue.description + "\n--------------------\n" |
|
|
|
|
|
|
|
|
|
if issue.filename and issue.lineno: |
|
|
|
|
text += "In file: " + issue.filename + ":" + str(issue.lineno) |
|
|
|
|
|
|
|
|
|
if issue.code: |
|
|
|
|
text += "\n\n" + issue.code + "\n\n--------------------\n" |
|
|
|
|
|
|
|
|
|
if self.verbose and issue.debug: |
|
|
|
|
text += "\nDEBUGGING INFORMATION:\n\n" + issue.debug + "\n--------------------\n" |
|
|
|
|
|
|
|
|
|
text += "\n" |
|
|
|
|
|
|
|
|
|
return text |
|
|
|
|
filename = list(self.issues.values())[0].filename |
|
|
|
|
template = Report.environment.get_template('report_as_text.jinja2') |
|
|
|
|
return template.render(filename=filename, issues=self.issues, verbose=self.verbose) |
|
|
|
|
|
|
|
|
|
def as_json(self): |
|
|
|
|
issues = [] |
|
|
|
|
for key, issue in self.issues.items(): |
|
|
|
|
issues.append(issue.as_dict()) |
|
|
|
|
issues = [issue.as_dict() for key, issue in self.issues.items()] |
|
|
|
|
result = {'success': True, 'error': None, 'issues': issues} |
|
|
|
|
return json.dumps(result) |
|
|
|
|
|
|
|
|
@ -104,7 +78,7 @@ class Report: |
|
|
|
|
text += "- Contract: Unknown\n" |
|
|
|
|
|
|
|
|
|
text += "- Function name: `" + issue.function + "`\n" |
|
|
|
|
text += "- PC address: " + str(issue.pc) + "\n\n" |
|
|
|
|
text += "- PC address: " + str(issue.address) + "\n\n" |
|
|
|
|
|
|
|
|
|
text += "### Description\n\n" + issue.description |
|
|
|
|
|
|
|
|
|