Add raw source_code to slither when possible

Use raw source_code to generate sourceMapping
Update pragma detector output
pull/72/head
Josselin 6 years ago
parent 8fafb75cc7
commit 72ab14003c
  1. 2
      slither/core/declarations/pragma_directive.py
  2. 6
      slither/core/slither_core.py
  3. 40
      slither/core/source_mapping/source_mapping.py
  4. 4
      slither/detectors/attributes/constant_pragma.py
  5. 8
      slither/solc_parsing/slitherSolc.py

@ -18,4 +18,4 @@ class Pragma(SourceMapping):
return ''.join(self.directive[1:]) return ''.join(self.directive[1:])
def __str__(self): def __str__(self):
return 'pragma '+str(self.directive) return 'pragma '+''.join(self.directive)

@ -17,6 +17,7 @@ class Slither(Context):
self._solc_version = None # '0.3' or '0.4':! self._solc_version = None # '0.3' or '0.4':!
self._pragma_directives = [] self._pragma_directives = []
self._import_directives = [] self._import_directives = []
self._raw_source_code = {}
@property @property
def source_units(self): def source_units(self):
@ -58,6 +59,11 @@ class Slither(Context):
""" list(str): Import directives""" """ list(str): Import directives"""
return self._import_directives return self._import_directives
@property
def source_code(self):
""" {filename: source_code}: source code """
return self._raw_source_code
def get_contract_from_name(self, contract_name): def get_contract_from_name(self, contract_name):
""" """
Return a contract from a name Return a contract from a name

@ -11,6 +11,26 @@ class SourceMapping(Context):
def source_mapping(self): def source_mapping(self):
return self._source_mapping return self._source_mapping
@staticmethod
def _compute_line(source_code, start, end):
"""
Compute line(s) number from a start/end offset
Not done in an efficient way
"""
total_length = len(source_code)
source_code = source_code.split('\n')
counter = 0
i = 0
lines = []
while counter < total_length:
counter += len(source_code[i]) +1
i = i+1
if counter > start:
lines.append(i)
if counter > end:
break
return lines
@staticmethod @staticmethod
def _convert_source_mapping(offset, slither): def _convert_source_mapping(offset, slither):
''' '''
@ -33,8 +53,26 @@ class SourceMapping(Context):
if f not in sourceUnits: if f not in sourceUnits:
return {'start':s, 'length':l} return {'start':s, 'length':l}
filename = sourceUnits[f] filename = sourceUnits[f]
return {'start':s, 'length':l, 'filename': filename}
lines = []
if filename in slither.source_code:
lines = SourceMapping._compute_line(slither.source_code[filename], s, l)
return {'start':s, 'length':l, 'filename': filename, 'lines' : lines }
def set_offset(self, offset, slither): def set_offset(self, offset, slither):
self._source_mapping = self._convert_source_mapping(offset, slither) self._source_mapping = self._convert_source_mapping(offset, slither)
@property
def source_mapping_str(self):
lines = self.source_mapping['lines']
if not lines:
lines = '[source code not found]'
elif len(lines) == 1:
lines = 'line {}'.format(lines[0])
else:
lines = 'lines: {}'.format(','.join(lines))
return '{} {}'.format(self.source_mapping['filename'], lines)

@ -22,7 +22,9 @@ class ConstantPragma(AbstractDetector):
versions = list(set(versions)) versions = list(set(versions))
if len(versions) > 1: if len(versions) > 1:
info = "Different version of Solidity used in {}: {}".format(self.filename, versions) info = "\nDifferent version of Solidity used in {}:\n".format(self.filename)
for p in pragma:
info += "\t- {} uses {}\n".format(p.source_mapping_str, str(p))
self.log(info) self.log(info)
source = [p.source_mapping for p in pragma] source = [p.source_mapping for p in pragma]

@ -1,3 +1,4 @@
import os
import json import json
import re import re
import logging import logging
@ -115,6 +116,13 @@ class SlitherSolc(Slither):
self._source_units[sourceUnit] = name self._source_units[sourceUnit] = name
if os.path.isfile(name):
with open(name) as f:
source_code = f.read()
self.source_code[name] = source_code
def _analyze_contracts(self): def _analyze_contracts(self):
if self._analyzed: if self._analyzed:
raise Exception('Contract analysis can be run only once!') raise Exception('Contract analysis can be run only once!')

Loading…
Cancel
Save