-Added function to add generic/other source mapped elements to JSON results.

-Added naive element to JSON results for rtlo detector.
pull/263/head
David Pokora 6 years ago
parent 4fe2eb169e
commit 1e1b736eca
No known key found for this signature in database
GPG Key ID: 3CED48D1BB21BDD7
  1. 178
      slither/detectors/abstract_detector.py
  2. 1
      slither/detectors/source/rtlo.py

@ -2,9 +2,10 @@ import abc
import re import re
from slither.utils.colors import green, yellow, red from slither.utils.colors import green, yellow, red
from slither.core.source_mapping.source_mapping import SourceMapping
from collections import OrderedDict from collections import OrderedDict
class IncorrectDetectorInitialization(Exception): class IncorrectDetectorInitialization(Exception):
pass pass
@ -30,6 +31,7 @@ classification_txt = {
DetectorClassification.HIGH: 'High', DetectorClassification.HIGH: 'High',
} }
class AbstractDetector(metaclass=abc.ABCMeta): class AbstractDetector(metaclass=abc.ABCMeta):
ARGUMENT = '' # run the detector with slither.py --ARGUMENT ARGUMENT = '' # run the detector with slither.py --ARGUMENT
HELP = '' # help information HELP = '' # help information
@ -43,7 +45,6 @@ class AbstractDetector(metaclass=abc.ABCMeta):
WIKI_EXPLOIT_SCENARIO = '' WIKI_EXPLOIT_SCENARIO = ''
WIKI_RECOMMENDATION = '' WIKI_RECOMMENDATION = ''
def __init__(self, slither, logger): def __init__(self, slither, logger):
self.slither = slither self.slither = slither
self.contracts = slither.contracts self.contracts = slither.contracts
@ -86,7 +87,6 @@ class AbstractDetector(metaclass=abc.ABCMeta):
DetectorClassification.INFORMATIONAL]: DetectorClassification.INFORMATIONAL]:
raise IncorrectDetectorInitialization('CONFIDENCE is not initialized {}'.format(self.__class__.__name__)) raise IncorrectDetectorInitialization('CONFIDENCE is not initialized {}'.format(self.__class__.__name__))
def _log(self, info): def _log(self, info):
self.logger.info(self.color(info)) self.logger.info(self.color(info))
@ -129,7 +129,6 @@ class AbstractDetector(metaclass=abc.ABCMeta):
self.logger.error(yellow('Malformed input. Example of valid input: 0,1,2,3')) self.logger.error(yellow('Malformed input. Example of valid input: 0,1,2,3'))
return results return results
@property @property
def color(self): def color(self):
return classification_colors[self.IMPACT] return classification_colors[self.IMPACT]
@ -156,139 +155,152 @@ class AbstractDetector(metaclass=abc.ABCMeta):
element['additional_fields'] = additional_fields element['additional_fields'] = additional_fields
return element return element
@staticmethod def _create_parent_element(self, element):
def _create_parent_element(element):
from slither.core.children.child_contract import ChildContract from slither.core.children.child_contract import ChildContract
from slither.core.children.child_function import ChildFunction from slither.core.children.child_function import ChildFunction
from slither.core.children.child_inheritance import ChildInheritance from slither.core.children.child_inheritance import ChildInheritance
if isinstance(element, ChildInheritance): if isinstance(element, ChildInheritance):
if element.contract_declarer: if element.contract_declarer:
contract = {'elements': []} contract = {'elements': []}
AbstractDetector.add_contract_to_json(element.contract_declarer, contract) self.add_contract_to_json(element.contract_declarer, contract)
return contract['elements'][0] return contract['elements'][0]
elif isinstance(element, ChildContract): elif isinstance(element, ChildContract):
if element.contract: if element.contract:
contract = {'elements': []} contract = {'elements': []}
AbstractDetector.add_contract_to_json(element.contract, contract) self.add_contract_to_json(element.contract, contract)
return contract['elements'][0] return contract['elements'][0]
elif isinstance(element, ChildFunction): elif isinstance(element, ChildFunction):
if element.function: if element.function:
function = {'elements': []} function = {'elements': []}
AbstractDetector.add_function_to_json(element.function, function) self.add_function_to_json(element.function, function)
return function['elements'][0] return function['elements'][0]
return None return None
@staticmethod def add_variable_to_json(self, variable, d, additional_fields={}):
def add_variable_to_json(variable, d, additional_fields={}):
type_specific_fields = { type_specific_fields = {
'parent': AbstractDetector._create_parent_element(variable) 'parent': self._create_parent_element(variable)
} }
element = AbstractDetector._create_base_element('variable', element = self._create_base_element('variable',
variable.name, variable.name,
variable.source_mapping, variable.source_mapping,
type_specific_fields, type_specific_fields,
additional_fields) additional_fields)
d['elements'].append(element) d['elements'].append(element)
@staticmethod def add_variables_to_json(self, variables, d):
def add_variables_to_json(variables, d):
for variable in sorted(variables, key=lambda x:x.name): for variable in sorted(variables, key=lambda x:x.name):
AbstractDetector.add_variable_to_json(variable, d) self.add_variable_to_json(variable, d)
@staticmethod def add_contract_to_json(self, contract, d, additional_fields={}):
def add_contract_to_json(contract, d, additional_fields={}): element = self._create_base_element('contract',
element = AbstractDetector._create_base_element('contract', contract.name,
contract.name, contract.source_mapping,
contract.source_mapping, {},
{}, additional_fields)
additional_fields)
d['elements'].append(element) d['elements'].append(element)
@staticmethod def add_function_to_json(self, function, d, additional_fields={}):
def add_function_to_json(function, d, additional_fields={}):
type_specific_fields = { type_specific_fields = {
'parent': AbstractDetector._create_parent_element(function), 'parent': self._create_parent_element(function),
'signature': function.full_name 'signature': function.full_name
} }
element = AbstractDetector._create_base_element('function', element = self._create_base_element('function',
function.name, function.name,
function.source_mapping, function.source_mapping,
type_specific_fields, type_specific_fields,
additional_fields) additional_fields)
d['elements'].append(element) d['elements'].append(element)
def add_functions_to_json(self, functions, d, additional_fields={}):
@staticmethod
def add_functions_to_json(functions, d, additional_fields={}):
for function in sorted(functions, key=lambda x: x.name): for function in sorted(functions, key=lambda x: x.name):
AbstractDetector.add_function_to_json(function, d, additional_fields) self.add_function_to_json(function, d, additional_fields)
@staticmethod def add_enum_to_json(self, enum, d, additional_fields={}):
def add_enum_to_json(enum, d, additional_fields={}):
type_specific_fields = { type_specific_fields = {
'parent': AbstractDetector._create_parent_element(enum) 'parent': self._create_parent_element(enum)
} }
element = AbstractDetector._create_base_element('enum', element = self._create_base_element('enum',
enum.name, enum.name,
enum.source_mapping, enum.source_mapping,
type_specific_fields, type_specific_fields,
additional_fields) additional_fields)
d['elements'].append(element) d['elements'].append(element)
@staticmethod def add_struct_to_json(self, struct, d, additional_fields={}):
def add_struct_to_json(struct, d, additional_fields={}):
type_specific_fields = { type_specific_fields = {
'parent': AbstractDetector._create_parent_element(struct) 'parent': self._create_parent_element(struct)
} }
element = AbstractDetector._create_base_element('struct', element = self._create_base_element('struct',
struct.name, struct.name,
struct.source_mapping, struct.source_mapping,
type_specific_fields, type_specific_fields,
additional_fields) additional_fields)
d['elements'].append(element) d['elements'].append(element)
@staticmethod def add_event_to_json(self, event, d, additional_fields={}):
def add_event_to_json(event, d, additional_fields={}):
type_specific_fields = { type_specific_fields = {
'parent': AbstractDetector._create_parent_element(event), 'parent': self._create_parent_element(event),
'signature': event.full_name 'signature': event.full_name
} }
element = AbstractDetector._create_base_element('event', element = self._create_base_element('event',
event.name, event.name,
event.source_mapping, event.source_mapping,
type_specific_fields, type_specific_fields,
additional_fields) additional_fields)
d['elements'].append(element) d['elements'].append(element)
@staticmethod def add_node_to_json(self, node, d, additional_fields={}):
def add_node_to_json(node, d, additional_fields={}):
type_specific_fields = { type_specific_fields = {
'parent': AbstractDetector._create_parent_element(node), 'parent': self._create_parent_element(node),
} }
node_name = str(node.expression) if node.expression else "" node_name = str(node.expression) if node.expression else ""
element = AbstractDetector._create_base_element('node', element = self._create_base_element('node',
node_name, node_name,
node.source_mapping, node.source_mapping,
type_specific_fields, type_specific_fields,
additional_fields) additional_fields)
d['elements'].append(element) d['elements'].append(element)
def add_nodes_to_json(self, nodes, d):
@staticmethod
def add_nodes_to_json(nodes, d):
for node in sorted(nodes, key=lambda x: x.node_id): for node in sorted(nodes, key=lambda x: x.node_id):
AbstractDetector.add_node_to_json(node, d) self.add_node_to_json(node, d)
@staticmethod def add_pragma_to_json(self, pragma, d, additional_fields={}):
def add_pragma_to_json(pragma, d, additional_fields={}):
type_specific_fields = { type_specific_fields = {
'directive': pragma.directive 'directive': pragma.directive
} }
element = AbstractDetector._create_base_element('pragma', element = self._create_base_element('pragma',
pragma.version, pragma.version,
pragma.source_mapping, pragma.source_mapping,
type_specific_fields, type_specific_fields,
additional_fields) additional_fields)
d['elements'].append(element)
def add_other_to_json(self, name, source_mapping, d, additional_fields={}):
# If this a tuple with (filename, start, end), convert it to a source mapping.
if isinstance(source_mapping, tuple):
# Parse the source id
(filename, start, end) = source_mapping
source_id = next((source_unit_id for (source_unit_id, source_unit_filename) in self.slither.source_units.items() if source_unit_filename == filename), -1)
# Convert to a source mapping string
source_mapping = f"{start}:{end}:{source_id}"
# If this is a source mapping string, parse it.
if isinstance(source_mapping, str):
source_mapping_str = source_mapping
source_mapping = SourceMapping()
source_mapping.set_offset(source_mapping_str, self.slither)
# If this is a source mapping object, get the underlying source mapping dictionary
if isinstance(source_mapping, SourceMapping):
source_mapping = source_mapping.source_mapping
# Create the underlying element and add it to our resulting json
element = self._create_base_element('other',
name,
source_mapping,
{},
additional_fields)
d['elements'].append(element) d['elements'].append(element)

@ -58,6 +58,7 @@ contract Token
if found: if found:
json = self.generate_json_result(info) json = self.generate_json_result(info)
self.add_other_to_json("rtlo-character", (filename, 0, 0), json)
results.append(json) results.append(json)
return results return results

Loading…
Cancel
Save