slither-format: improve error handling

pull/238/head
Josselin 5 years ago
parent 91b8b7da93
commit 80db6cc543
  1. 5
      utils/slither_format/exceptions.py
  2. 4
      utils/slither_format/formatters/constable_states.py
  3. 4
      utils/slither_format/formatters/constant_function.py
  4. 45
      utils/slither_format/formatters/naming_convention.py
  5. 6
      utils/slither_format/formatters/pragma.py
  6. 4
      utils/slither_format/formatters/solc_version.py
  7. 10
      utils/slither_format/slither_format.py

@ -0,0 +1,5 @@
from slither.exceptions import SlitherException
class FormatImpossible(SlitherException): pass
class FormatError(SlitherException): pass

@ -1,5 +1,5 @@
import re import re
from slither.exceptions import SlitherException from ..exceptions import FormatError
from ..utils.patches import create_patch from ..utils.patches import create_patch
def format(slither, result): def format(slither, result):
@ -26,5 +26,5 @@ def _patch(slither, result, in_file, match_text, replace_text, modify_loc_start,
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("State variable not found?!") raise FormatError("State variable not found?!")

@ -1,5 +1,5 @@
import re import re
from slither.exceptions import SlitherException from ..exceptions import FormatError
from ..utils.patches import create_patch from ..utils.patches import create_patch
def format(slither, patches, elements): def format(slither, patches, elements):
@ -32,4 +32,4 @@ def _patch(slither, patches, in_file, in_file_relative, modify_loc_start, modify
m.groups(0)[0], # this is view|pure|constant m.groups(0)[0], # this is view|pure|constant
"") "")
else: else:
raise SlitherException("No view/pure/constant specifier exists. Regex failed to remove specifier!") raise FormatError("No view/pure/constant specifier exists. Regex failed to remove specifier!")

@ -1,10 +1,9 @@
import re import re
import logging import logging
from collections import namedtuple
from slither.exceptions import SlitherException
from slither.core.expressions.identifier import Identifier from slither.core.expressions.identifier import Identifier
from slither.slithir.operations import NewContract from slither.slithir.operations import NewContract
from slither.slithir.operations import Member from slither.slithir.operations import Member
from ..exceptions import FormatError
from ..utils.patches import create_patch from ..utils.patches import create_patch
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
@ -102,7 +101,7 @@ def _patch(slither, result, element, _target):
_create_patch_modifier_uses(slither, result, element) _create_patch_modifier_uses(slither, result, element)
else: else:
raise SlitherException("Unknown naming convention! " + _target) raise FormatError("Unknown naming convention! " + _target)
# endregion # endregion
################################################################################### ###################################################################################
@ -127,7 +126,7 @@ def _create_patch_contract_definition(slither, result, element):
old_str_of_interest.decode('utf-8'), 1) old_str_of_interest.decode('utf-8'), 1)
if num_repl == 0: if num_repl == 0:
raise SlitherException(f"Could not find contract: {name}") raise FormatError(f"Could not find contract: {name}")
old_string = old_str_of_interest.decode('utf-8') old_string = old_str_of_interest.decode('utf-8')
@ -206,7 +205,7 @@ def _create_patch_enum_declaration(slither, result, element):
old_str_of_interest.decode('utf-8'), 1) old_str_of_interest.decode('utf-8'), 1)
if num_repl == 0: if num_repl == 0:
raise SlitherException(f"Could not find enum: {name}") raise FormatError(f"Could not find enum: {name}")
old_string = old_str_of_interest.decode('utf-8') old_string = old_str_of_interest.decode('utf-8')
@ -234,7 +233,7 @@ def _create_patch_struct_definition(slither, result, element):
old_str_of_interest.decode('utf-8'), 1) old_str_of_interest.decode('utf-8'), 1)
if num_repl == 0: if num_repl == 0:
raise SlitherException(f"Could not find struct: {name}") raise FormatError(f"Could not find struct: {name}")
old_string = old_str_of_interest.decode('utf-8') old_string = old_str_of_interest.decode('utf-8')
@ -266,7 +265,7 @@ def _create_patch_modifier_definition(slither, result, element):
old_str_of_interest.decode('utf-8'), old_str_of_interest.decode('utf-8'),
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find modifier?!") raise FormatError(f"Could not find modifier {name}")
def _create_patch_function_definition(slither, result, element): def _create_patch_function_definition(slither, result, element):
@ -290,7 +289,7 @@ def _create_patch_function_definition(slither, result, element):
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException(f"Could not find function {name}") raise FormatError(f"Could not find function {name}")
def _create_patch_event_definition(slither, result, element): def _create_patch_event_definition(slither, result, element):
in_file, in_file_str, old_str_of_interest, loc_start, loc_end = _unpack_info(slither, element) in_file, in_file_str, old_str_of_interest, loc_start, loc_end = _unpack_info(slither, element)
@ -300,7 +299,7 @@ def _create_patch_event_definition(slither, result, element):
target_contract = slither.get_contract_from_name(contract_name) target_contract = slither.get_contract_from_name(contract_name)
if not target_contract: if not target_contract:
raise SlitherException("Contract not found?!") raise FormatError(f"Contract not found {contract_name}")
for event in target_contract.events: for event in target_contract.events:
if event.name == name: if event.name == name:
# Get only event name without parameters # Get only event name without parameters
@ -320,7 +319,7 @@ def _create_patch_event_definition(slither, result, element):
old_str_of_interest.decode('utf-8'), old_str_of_interest.decode('utf-8'),
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find event?!") raise FormatError(f"Could not find event {name}")
def _create_patch_parameter_declaration(slither, result, element): def _create_patch_parameter_declaration(slither, result, element):
in_file, in_file_str, old_str_of_interest, loc_start, loc_end = _unpack_info(slither, element) in_file, in_file_str, old_str_of_interest, loc_start, loc_end = _unpack_info(slither, element)
@ -343,7 +342,7 @@ def _create_patch_parameter_declaration(slither, result, element):
old_str_of_interest.decode('utf-8'), old_str_of_interest.decode('utf-8'),
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find parameter declaration?!") raise FormatError(f"Could not find parameter declaration {name}")
# endregion # endregion
################################################################################### ###################################################################################
@ -359,7 +358,7 @@ def _create_patch_contract_uses(slither, result, element):
target_contract = slither.get_contract_from_name(name) target_contract = slither.get_contract_from_name(name)
if not target_contract: if not target_contract:
raise SlitherException(f"Contract not found {name}") raise FormatError(f"Contract not found {name}")
# Check state variables of contract type # Check state variables of contract type
# To-do: Deep-check aggregate types (struct and mapping) # To-do: Deep-check aggregate types (struct and mapping)
@ -420,7 +419,7 @@ def _create_patch_contract_uses(slither, result, element):
old_str_of_interest, old_str_of_interest,
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find new object?!") raise FormatError(f"Could not find new object {name}")
def _create_patch_modifier_uses(slither, result, element): def _create_patch_modifier_uses(slither, result, element):
@ -433,7 +432,7 @@ def _create_patch_modifier_uses(slither, result, element):
target_contract = slither.get_contract_from_name(contract_name) target_contract = slither.get_contract_from_name(contract_name)
if not target_contract: if not target_contract:
raise SlitherException("Contract not found?!") raise FormatError(f"Contract not found {contract_name}")
modifier_contract = target_contract.get_modifier_from_signature(modifier_sig) modifier_contract = target_contract.get_modifier_from_signature(modifier_sig)
@ -458,7 +457,7 @@ def _create_patch_modifier_uses(slither, result, element):
old_str_of_interest.decode('utf-8'), old_str_of_interest.decode('utf-8'),
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find modifier name?!") raise FormatError(f"Could not find modifier {modifier_sig}")
@ -534,7 +533,7 @@ def _create_patch_event_calls(slither, result, element):
event_name = name.split('(')[0] event_name = name.split('(')[0]
target_contract = slither.get_contract_from_name(contract_name) target_contract = slither.get_contract_from_name(contract_name)
if not target_contract: if not target_contract:
raise SlitherException("Contract not found?!") raise FormatError(f"Contract not found {name}")
for contract in [target_contract] + target_contract.derived_contracts: for contract in [target_contract] + target_contract.derived_contracts:
for function in contract.functions: for function in contract.functions:
for node in function.nodes: for node in function.nodes:
@ -602,7 +601,7 @@ def _create_patch_parameter_uses(slither, result, element):
old_str_of_interest.decode('utf-8'), old_str_of_interest.decode('utf-8'),
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find parameter use?!") raise FormatError(f"Could not find parameter use {name}")
# Process function parameters passed to modifiers # Process function parameters passed to modifiers
# _expression_modifiers is used to access the source mapping of the call rather # _expression_modifiers is used to access the source mapping of the call rather
@ -637,20 +636,18 @@ def _create_patch_parameter_uses(slither, result, element):
old_str_of_interest_beyond_modifier_name, old_str_of_interest_beyond_modifier_name,
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find parameter use in modifier?!") raise FormatError(f"Could not find parameter use in modifier {modifier}")
def _create_patch_state_variable_uses(slither, result, element): def _create_patch_state_variable_uses(slither, result, element):
in_file, in_file_str, old_str_of_interest, loc_start, loc_end = _unpack_info(slither, element)
name = get_name(element) name = get_name(element)
contract_name = get_contract_name(element) contract_name = get_contract_name(element)
# To-do: Check cross-contract state variable uses # To-do: Check cross-contract state variable uses
target_contract = slither.get_contract_from_name(contract_name) target_contract = slither.get_contract_from_name(contract_name)
if not target_contract: if not target_contract:
raise SlitherException(f"Contract not found {contract_name}") raise FormatError(f"Contract not found {contract_name}")
fms = target_contract.functions + target_contract.modifiers fms = target_contract.functions + target_contract.modifiers
for fm in fms: for fm in fms:
@ -690,7 +687,7 @@ def _create_patch_enum_uses(slither, result, element):
target_contract = slither.get_contract_from_name(contract_name) target_contract = slither.get_contract_from_name(contract_name)
if not target_contract: if not target_contract:
raise SlitherException(f"Contract not found {contract_name}") raise FormatError(f"Contract not found {contract_name}")
in_file_str = slither.source_code[in_file].encode('utf-8') in_file_str = slither.source_code[in_file].encode('utf-8')
# Check state variable declarations of enum type # Check state variable declarations of enum type
@ -771,7 +768,7 @@ def _create_patch_enum_uses(slither, result, element):
new_str_of_interest) new_str_of_interest)
else: else:
raise SlitherException("Could not find new object?!") raise FormatError(f"Could not find new object {function}")
# To-do: Check any other place/way where enum type is used # To-do: Check any other place/way where enum type is used
@ -786,7 +783,7 @@ def _create_patch_struct_uses(slither, result, element):
target_contract = slither.get_contract_from_name(contract_name) target_contract = slither.get_contract_from_name(contract_name)
if not target_contract: if not target_contract:
raise SlitherException(f"Contract not found {contract_name}") raise FormatError(f"Contract not found {contract_name}")
for contract in [target_contract] + target_contract.derived_contracts: for contract in [target_contract] + target_contract.derived_contracts:
f_contract = contract.source_mapping['filename_absolute'] f_contract = contract.source_mapping['filename_absolute']

@ -1,5 +1,5 @@
import re import re
from slither.exceptions import SlitherException from ..exceptions import FormatImpossible
from ..utils.patches import create_patch from ..utils.patches import create_patch
# Indicates the recommended versions for replacement # Indicates the recommended versions for replacement
@ -31,7 +31,7 @@ def _analyse_versions(used_solc_versions):
for version in used_solc_versions: for version in used_solc_versions:
replace_solc_versions.append(_determine_solc_version_replacement(version)) replace_solc_versions.append(_determine_solc_version_replacement(version))
if not all(version == replace_solc_versions[0] for version in replace_solc_versions): if not all(version == replace_solc_versions[0] for version in replace_solc_versions):
raise SlitherException("Multiple incompatible versions!") raise FormatImpossible("Multiple incompatible versions!")
else: else:
return replace_solc_versions[0] return replace_solc_versions[0]
@ -46,7 +46,7 @@ def _determine_solc_version_replacement(used_solc_version):
elif minor_version == '5': elif minor_version == '5':
return "pragma solidity " + REPLACEMENT_VERSIONS[1] + ';' return "pragma solidity " + REPLACEMENT_VERSIONS[1] + ';'
else: else:
raise SlitherException("Unknown version!") raise FormatImpossible("Unknown version!")
elif len(versions) == 2: elif len(versions) == 2:
version_right = versions[1] version_right = versions[1]
minor_version_right = '.'.join(version_right[2:])[2] minor_version_right = '.'.join(version_right[2:])[2]

@ -1,5 +1,5 @@
import re import re
from slither.exceptions import SlitherException from ..exceptions import FormatImpossible
from ..utils.patches import create_patch from ..utils.patches import create_patch
@ -36,7 +36,7 @@ def _determine_solc_version_replacement(used_solc_version):
# Replace with 0.5.3 # Replace with 0.5.3
return "pragma solidity " + REPLACEMENT_VERSIONS[1] + ';' return "pragma solidity " + REPLACEMENT_VERSIONS[1] + ';'
else: else:
raise SlitherException("Unknown version!") raise FormatImpossible(f"Unknown version {versions}")
elif len(versions) == 2: elif len(versions) == 2:
version_right = versions[1] version_right = versions[1]
minor_version_right = '.'.join(version_right[2:])[2] minor_version_right = '.'.join(version_right[2:])[2]

@ -1,7 +1,5 @@
import sys
import logging import logging
import os import os
from slither.utils.colors import red, set_colorization_enabled
from slither.detectors.variables.unused_state_variables import UnusedStateVars from slither.detectors.variables.unused_state_variables import UnusedStateVars
from slither.detectors.attributes.incorrect_solc import IncorrectSolc from slither.detectors.attributes.incorrect_solc import IncorrectSolc
from slither.detectors.attributes.constant_pragma import ConstantPragma from slither.detectors.attributes.constant_pragma import ConstantPragma
@ -11,10 +9,10 @@ from slither.detectors.variables.possible_const_state_variables import ConstCand
from slither.detectors.attributes.const_functions import ConstantFunctions from slither.detectors.attributes.const_functions import ConstantFunctions
from .formatters import unused_state, constable_states, pragma, solc_version, external_function, naming_convention from .formatters import unused_state, constable_states, pragma, solc_version, external_function, naming_convention
from .utils.patches import apply_patch, create_diff from .utils.patches import apply_patch, create_diff
from .exceptions import FormatError, FormatImpossible
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('Slither.Format') logger = logging.getLogger('Slither.Format')
set_colorization_enabled(True)
all_detectors = { all_detectors = {
'unused-state': UnusedStateVars, 'unused-state': UnusedStateVars,
@ -99,6 +97,7 @@ def apply_detector_results(slither, detector_results):
Apply slither detector results on contract files to generate patches Apply slither detector results on contract files to generate patches
''' '''
for result in detector_results: for result in detector_results:
try:
if result['check'] == 'unused-state': if result['check'] == 'unused-state':
unused_state.format(slither, result) unused_state.format(slither, result)
elif result['check'] == 'solc-version': elif result['check'] == 'solc-version':
@ -114,8 +113,9 @@ def apply_detector_results(slither, detector_results):
elif result['check'] == 'constant-function': elif result['check'] == 'constant-function':
constable_states.format(slither, result) constable_states.format(slither, result)
else: else:
logger.error(red(result['check'] + "detector not supported yet.")) raise FormatError(result['check'] + "detector not supported yet.")
sys.exit(-1) except FormatImpossible as e:
logger.info(f'Impossible to patch:\n{result["description"]}\nReason: {e}')
# endregion # endregion

Loading…
Cancel
Save