Static Analyzer for Solidity
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
slither/utils/slither_format/format_pragma.py

75 lines
3.2 KiB

import re, logging, sys
from slither.utils.colors import red, yellow, set_colorization_enabled
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('Slither.Format')
set_colorization_enabled(True)
class FormatPragma:
# Indicates the recommended versions for replacement
REPLACEMENT_VERSIONS = ["0.4.25", "0.5.3"]
# group:
# 0: ^ > >= < <= (optional)
# 1: ' ' (optional)
# 2: version number
# 3: version number
# 4: version number
PATTERN = re.compile('(\^|>|>=|<|<=)?([ ]+)?(\d+)\.(\d+)\.(\d+)')
@staticmethod
def format(slither, patches, elements):
versions_used = []
for element in elements:
versions_used.append(''.join(element['type_specific_fields']['directive'][1:]))
solc_version_replace = FormatPragma.analyse_versions(versions_used)
for element in elements:
FormatPragma.create_patch(slither, patches, element['source_mapping']['filename_absolute'], element['source_mapping']['filename_relative'], solc_version_replace, element['source_mapping']['start'], element['source_mapping']['start'] + element['source_mapping']['length'])
@staticmethod
def analyse_versions(used_solc_versions):
replace_solc_versions = list()
for version in used_solc_versions:
replace_solc_versions.append(FormatPragma.determine_solc_version_replacement(version))
if not all(version == replace_solc_versions[0] for version in replace_solc_versions):
logger.error(red("Multiple incompatible versions!"))
sys.exit(-1)
else:
return replace_solc_versions[0]
@staticmethod
def determine_solc_version_replacement(used_solc_version):
versions = FormatPragma.PATTERN.findall(used_solc_version)
if len(versions) == 1:
version = versions[0]
minor_version = '.'.join(version[2:])[2]
if minor_version == '4':
return "pragma solidity " + FormatPragma.REPLACEMENT_VERSIONS[0] + ';'
elif minor_version == '5':
return "pragma solidity " + FormatPragma.REPLACEMENT_VERSIONS[1] + ';'
else:
logger.error(red("Unknown version!"))
sys.exit(-1)
elif len(versions) == 2:
version_left = versions[0]
version_right = versions[1]
minor_version_left = '.'.join(version_left[2:])[2]
minor_version_right = '.'.join(version_right[2:])[2]
if minor_version_right == '4':
return "pragma solidity " + FormatPragma.REPLACEMENT_VERSIONS[0] + ';'
elif minor_version_right in ['5','6']:
return "pragma solidity " + FormatPragma.REPLACEMENT_VERSIONS[1] + ';'
@staticmethod
def create_patch(slither, patches, in_file, in_file_relative, pragma, modify_loc_start, modify_loc_end):
in_file_str = slither.source_code[in_file].encode('utf-8')
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
patches[in_file_relative].append({
"file" : in_file,
"detector" : "pragma",
"start" : modify_loc_start,
"end" : modify_loc_end,
"old_string" : old_str_of_interest.decode('utf-8'),
"new_string" : pragma
})