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. 40
      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
from slither.exceptions import SlitherException
from ..exceptions import FormatError
from ..utils.patches import create_patch
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)
else:
raise SlitherException("State variable not found?!")
raise FormatError("State variable not found?!")

@ -1,5 +1,5 @@
import re
from slither.exceptions import SlitherException
from ..exceptions import FormatError
from ..utils.patches import create_patch
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
"")
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 logging
from collections import namedtuple
from slither.exceptions import SlitherException
from slither.core.expressions.identifier import Identifier
from slither.slithir.operations import NewContract
from slither.slithir.operations import Member
from ..exceptions import FormatError
from ..utils.patches import create_patch
logging.basicConfig(level=logging.INFO)
@ -102,7 +101,7 @@ def _patch(slither, result, element, _target):
_create_patch_modifier_uses(slither, result, element)
else:
raise SlitherException("Unknown naming convention! " + _target)
raise FormatError("Unknown naming convention! " + _target)
# endregion
###################################################################################
@ -127,7 +126,7 @@ def _create_patch_contract_definition(slither, result, element):
old_str_of_interest.decode('utf-8'), 1)
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')
@ -206,7 +205,7 @@ def _create_patch_enum_declaration(slither, result, element):
old_str_of_interest.decode('utf-8'), 1)
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')
@ -234,7 +233,7 @@ def _create_patch_struct_definition(slither, result, element):
old_str_of_interest.decode('utf-8'), 1)
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')
@ -266,7 +265,7 @@ def _create_patch_modifier_definition(slither, result, element):
old_str_of_interest.decode('utf-8'),
new_str_of_interest)
else:
raise SlitherException("Could not find modifier?!")
raise FormatError(f"Could not find modifier {name}")
def _create_patch_function_definition(slither, result, element):
@ -290,7 +289,7 @@ def _create_patch_function_definition(slither, result, element):
new_str_of_interest)
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):
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)
if not target_contract:
raise SlitherException("Contract not found?!")
raise FormatError(f"Contract not found {contract_name}")
for event in target_contract.events:
if event.name == name:
# 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'),
new_str_of_interest)
else:
raise SlitherException("Could not find event?!")
raise FormatError(f"Could not find event {name}")
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)
@ -343,7 +342,7 @@ def _create_patch_parameter_declaration(slither, result, element):
old_str_of_interest.decode('utf-8'),
new_str_of_interest)
else:
raise SlitherException("Could not find parameter declaration?!")
raise FormatError(f"Could not find parameter declaration {name}")
# endregion
###################################################################################
@ -359,7 +358,7 @@ def _create_patch_contract_uses(slither, result, element):
target_contract = slither.get_contract_from_name(name)
if not target_contract:
raise SlitherException(f"Contract not found {name}")
raise FormatError(f"Contract not found {name}")
# Check state variables of contract type
# 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,
new_str_of_interest)
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):
@ -433,7 +432,7 @@ def _create_patch_modifier_uses(slither, result, element):
target_contract = slither.get_contract_from_name(contract_name)
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)
@ -458,7 +457,7 @@ def _create_patch_modifier_uses(slither, result, element):
old_str_of_interest.decode('utf-8'),
new_str_of_interest)
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]
target_contract = slither.get_contract_from_name(contract_name)
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 function in contract.functions:
for node in function.nodes:
@ -602,7 +601,7 @@ def _create_patch_parameter_uses(slither, result, element):
old_str_of_interest.decode('utf-8'),
new_str_of_interest)
else:
raise SlitherException("Could not find parameter use?!")
raise FormatError(f"Could not find parameter use {name}")
# Process function parameters passed to modifiers
# _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,
new_str_of_interest)
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):
in_file, in_file_str, old_str_of_interest, loc_start, loc_end = _unpack_info(slither, element)
name = get_name(element)
contract_name = get_contract_name(element)
# To-do: Check cross-contract state variable uses
target_contract = slither.get_contract_from_name(contract_name)
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
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)
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')
# Check state variable declarations of enum type
@ -771,7 +768,7 @@ def _create_patch_enum_uses(slither, result, element):
new_str_of_interest)
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
@ -786,7 +783,7 @@ def _create_patch_struct_uses(slither, result, element):
target_contract = slither.get_contract_from_name(contract_name)
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:
f_contract = contract.source_mapping['filename_absolute']

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

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

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

Loading…
Cancel
Save