Merge pull request #229 from crytic/dev-exception

Improve Exception handling
pull/222/head
Feist Josselin 6 years ago committed by GitHub
commit 7752999de6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      slither/__main__.py
  2. 7
      slither/all_exceptions.py
  3. 3
      slither/core/exceptions.py
  4. 8
      slither/core/expressions/assignment_operation.py
  5. 8
      slither/core/expressions/binary_operation.py
  6. 11
      slither/core/expressions/unary_operation.py
  7. 3
      slither/exceptions.py
  8. 19
      slither/slither.py
  9. 7
      slither/slithir/convert.py
  10. 3
      slither/slithir/exceptions.py
  11. 7
      slither/slithir/operations/binary.py
  12. 9
      slither/slithir/operations/unary.py
  13. 4
      slither/slithir/utils/ssa.py
  14. 4
      slither/solc_parsing/declarations/contract.py
  15. 10
      slither/solc_parsing/declarations/function.py
  16. 7
      slither/solc_parsing/exceptions.py
  17. 12
      slither/solc_parsing/expressions/expression_parsing.py
  18. 14
      slither/solc_parsing/slitherSolc.py
  19. 10
      slither/solc_parsing/solidity_types/type_parsing.py
  20. 11
      slither/solc_parsing/variables/variable_declaration.py
  21. 10
      slither/visitors/expression/expression.py
  22. 6
      slither/visitors/slithir/expression_to_slithir.py

@ -24,6 +24,7 @@ from slither.utils.command_line import (output_detectors, output_results_to_mark
output_detectors_json, output_printers,
output_to_markdown, output_wiki)
from crytic_compile import is_supported
from slither.exceptions import SlitherException
logging.basicConfig()
logger = logging.getLogger("Slither")
@ -551,6 +552,12 @@ def main_impl(all_detector_classes, all_printer_classes):
return
exit(results)
except SlitherException as e:
logging.error(red('Error:'))
logging.error(red(e))
logging.error('Please report an issue to https://github.com/crytic/slither/issues')
sys.exit(-1)
except Exception:
logging.error('Error in %s' % args.filename)
logging.error(traceback.format_exc())

@ -0,0 +1,7 @@
"""
This module import all slither exceptions
"""
from slither.slithir.exceptions import SlithIRError
from slither.solc_parsing.exceptions import ParsingError, ParsingContractNotFound, ParsingNameReuse
from slither.core.exceptions import SlitherCoreError
from slither.exceptions import SlitherException

@ -0,0 +1,3 @@
from slither.exceptions import SlitherException
class SlitherCoreError(SlitherException): pass

@ -1,7 +1,7 @@
import logging
from slither.core.expressions.expression_typed import ExpressionTyped
from slither.core.expressions.expression import Expression
from slither.core.exceptions import SlitherCoreError
logger = logging.getLogger("AssignmentOperation")
@ -43,8 +43,7 @@ class AssignmentOperationType:
if operation_type == '%=':
return AssignmentOperationType.ASSIGN_MODULO
logger.error('get_type: Unknown operation type {})'.format(operation_type))
exit(-1)
raise SlitherCoreError('get_type: Unknown operation type {})'.format(operation_type))
@staticmethod
def str(operation_type):
@ -71,8 +70,7 @@ class AssignmentOperationType:
if operation_type == AssignmentOperationType.ASSIGN_MODULO:
return '%='
logger.error('str: Unknown operation type {})'.format(operation_type))
exit(-1)
raise SlitherCoreError('str: Unknown operation type {})'.format(operation_type))
class AssignmentOperation(ExpressionTyped):

@ -1,7 +1,7 @@
import logging
from slither.core.expressions.expression_typed import ExpressionTyped
from slither.core.expressions.expression import Expression
from slither.core.exceptions import SlitherCoreError
logger = logging.getLogger("BinaryOperation")
@ -67,8 +67,7 @@ class BinaryOperationType:
if operation_type == '||':
return BinaryOperationType.OROR
logger.error('get_type: Unknown operation type {})'.format(operation_type))
exit(-1)
raise SlitherCoreError('get_type: Unknown operation type {})'.format(operation_type))
@staticmethod
def str(operation_type):
@ -110,8 +109,7 @@ class BinaryOperationType:
return '&&'
if operation_type == BinaryOperationType.OROR:
return '||'
logger.error('str: Unknown operation type {})'.format(operation_type))
exit(-1)
raise SlitherCoreError('str: Unknown operation type {})'.format(operation_type))
class BinaryOperation(ExpressionTyped):

@ -1,7 +1,7 @@
import logging
from slither.core.expressions.expression_typed import ExpressionTyped
from slither.core.expressions.expression import Expression
from slither.core.solidity_types.type import Type
from slither.core.exceptions import SlitherCoreError
logger = logging.getLogger("UnaryOperation")
@ -38,8 +38,7 @@ class UnaryOperationType:
return UnaryOperationType.PLUSPLUS_POST
if operation_type == '--':
return UnaryOperationType.MINUSMINUS_POST
logger.error('get_type: Unknown operation type {}'.format(operation_type))
exit(-1)
raise SlitherCoreError('get_type: Unknown operation type {}'.format(operation_type))
@staticmethod
def str(operation_type):
@ -58,8 +57,7 @@ class UnaryOperationType:
if operation_type in [UnaryOperationType.MINUSMINUS_PRE, UnaryOperationType.MINUSMINUS_POST]:
return '--'
logger.error('str: Unknown operation type {}'.format(operation_type))
exit(-1)
raise SlitherCoreError('str: Unknown operation type {}'.format(operation_type))
@staticmethod
def is_prefix(operation_type):
@ -74,8 +72,7 @@ class UnaryOperationType:
elif operation_type in [UnaryOperationType.PLUSPLUS_POST, UnaryOperationType.MINUSMINUS_POST]:
return False
logger.error('is_prefix: Unknown operation type {}'.format(operation_type))
exit(-1)
raise SlitherCoreError('is_prefix: Unknown operation type {}'.format(operation_type))
class UnaryOperation(ExpressionTyped):

@ -0,0 +1,3 @@
class SlitherException(Exception): pass
class SlitherError(SlitherException): pass

@ -11,7 +11,7 @@ from crytic_compile import CryticCompile, InvalidCompilation
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.printers.abstract_printer import AbstractPrinter
from .solc_parsing.slitherSolc import SlitherSolc
from .utils.colors import red
from .exceptions import SlitherError
logger = logging.getLogger("Slither")
logging.basicConfig()
@ -56,11 +56,8 @@ class Slither(SlitherSolc):
crytic_compile = CryticCompile(contract, **kwargs)
self._crytic_compile = crytic_compile
except InvalidCompilation as e:
logger.error('Invalid compilation')
logger.error(e)
exit(-1)
raise SlitherError('Invalid compilation: '+e)
for path, ast in crytic_compile.asts.items():
self._parse_contracts_from_loaded_json(ast, path)
self._add_source_code(path)
@ -78,14 +75,12 @@ class Slither(SlitherSolc):
def _init_from_raw_json(self, filename):
if not os.path.isfile(filename):
logger.error('{} does not exist (are you in the correct directory?)'.format(filename))
exit(-1)
raise SlitherError('{} does not exist (are you in the correct directory?)'.format(filename))
assert filename.endswith('json')
with open(filename, encoding='utf8') as astFile:
stdout = astFile.read()
if not stdout:
logger.info('Empty AST file: %s', filename)
sys.exit(-1)
raise SlitherError('Empty AST file: %s', filename)
contracts_json = stdout.split('\n=')
super(Slither, self).__init__(filename)
@ -173,14 +168,12 @@ class Slither(SlitherSolc):
def _run_solc(self, filename, solc, disable_solc_warnings, solc_arguments, ast_format):
if not os.path.isfile(filename):
logger.error('{} does not exist (are you in the correct directory?)'.format(filename))
exit(-1)
raise SlitherError('{} does not exist (are you in the correct directory?)'.format(filename))
assert filename.endswith('json')
with open(filename, encoding='utf8') as astFile:
stdout = astFile.read()
if not stdout:
logger.info('Empty AST file: %s', filename)
sys.exit(-1)
raise SlitherError('Empty AST file: %s', filename)
stdout = stdout.split('\n=')
return stdout

@ -33,6 +33,7 @@ from slither.slithir.variables import (Constant, ReferenceVariable,
from slither.visitors.slithir.expression_to_slithir import ExpressionToSlithIR
from slither.utils.function import get_function_id
from slither.utils.type import export_nested_types_from_variable
from slither.slithir.exceptions import SlithIRError
logger = logging.getLogger('ConvertToIR')
@ -457,8 +458,7 @@ def propagate_types(ir, node):
# temporary operation; they will be removed
pass
else:
logger.error('Not handling {} during type propgation'.format(type(ir)))
exit(-1)
raise SlithIRError('Not handling {} during type propgation'.format(type(ir)))
def extract_tmp_call(ins, contract):
assert isinstance(ins, TmpCall)
@ -577,8 +577,7 @@ def convert_to_low_level(ir):
new_ir.arguments = ir.arguments
new_ir.lvalue.set_type(ElementaryType('bool'))
return new_ir
logger.error('Incorrect conversion to low level {}'.format(ir))
exit(-1)
raise SlithIRError('Incorrect conversion to low level {}'.format(ir))
def convert_to_push(ir, node):
"""

@ -0,0 +1,3 @@
from slither.exceptions import SlitherException
class SlithIRError(SlitherException): pass

@ -4,6 +4,7 @@ from slither.core.variables.variable import Variable
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
from slither.core.solidity_types import ElementaryType
from slither.slithir.variables import ReferenceVariable
from slither.slithir.exceptions import SlithIRError
logger = logging.getLogger("BinaryOperationIR")
@ -80,8 +81,7 @@ class BinaryType(object):
if operation_type == '||':
return BinaryType.OROR
logger.error('get_type: Unknown operation type {})'.format(operation_type))
exit(-1)
raise SlithIRError('get_type: Unknown operation type {})'.format(operation_type))
@staticmethod
def str(operation_type):
@ -123,8 +123,7 @@ class BinaryType(object):
return '&&'
if operation_type == BinaryType.OROR:
return '||'
logger.error('str: Unknown operation type {})'.format(operation_type))
exit(-1)
raise SlithIRError('str: Unknown operation type {})'.format(operation_type))
class Binary(OperationWithLValue):

@ -1,8 +1,7 @@
import logging
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.core.variables.variable import Variable
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
from slither.slithir.exceptions import SlithIRError
logger = logging.getLogger("BinaryOperationIR")
@ -17,8 +16,7 @@ class UnaryType:
return UnaryType.BANG
if operation_type == '~':
return UnaryType.TILD
logger.error('get_type: Unknown operation type {}'.format(operation_type))
exit(-1)
raise SlithIRError('get_type: Unknown operation type {}'.format(operation_type))
@staticmethod
def str(operation_type):
@ -27,8 +25,7 @@ class UnaryType:
if operation_type == UnaryType.TILD:
return '~'
logger.error('str: Unknown operation type {}'.format(operation_type))
exit(-1)
raise SlithIRError('str: Unknown operation type {}'.format(operation_type))
class Unary(OperationWithLValue):

@ -22,6 +22,7 @@ from slither.slithir.variables import (Constant, LocalIRVariable,
ReferenceVariable, ReferenceVariableSSA,
StateIRVariable, TemporaryVariable,
TemporaryVariableSSA, TupleVariable, TupleVariableSSA)
from slither.slithir.exceptions import SlithIRError
logger = logging.getLogger('SSA_Conversion')
@ -662,7 +663,6 @@ def copy_ir(ir, *instances):
return Length(value, lvalue)
logger.error('Impossible ir copy on {} ({})'.format(ir, type(ir)))
exit(-1)
raise SlithIRError('Impossible ir copy on {} ({})'.format(ir, type(ir)))
# endregion

@ -9,6 +9,7 @@ from slither.solc_parsing.declarations.modifier import ModifierSolc
from slither.solc_parsing.declarations.structure import StructureSolc
from slither.solc_parsing.solidity_types.type_parsing import parse_type
from slither.solc_parsing.variables.state_variable import StateVariableSolc
from slither.solc_parsing.exceptions import ParsingError
logger = logging.getLogger("ContractSolcParsing")
@ -186,8 +187,7 @@ class ContractSolc04(Contract):
elif item[self.get_key()] == 'UsingForDirective':
self._usingForNotParsed.append(item)
else:
logger.error('Unknown contract item: '+item[self.get_key()])
exit(-1)
raise ParsingError('Unknown contract item: '+item[self.get_key()])
return
def _parse_struct(self, struct):

@ -26,6 +26,7 @@ from slither.utils.expression_manipulations import SplitTernaryExpression
from slither.utils.utils import unroll
from slither.visitors.expression.export_values import ExportValues
from slither.visitors.expression.has_conditional import HasConditional
from slither.solc_parsing.exceptions import ParsingError
logger = logging.getLogger("FunctionSolc")
@ -725,8 +726,7 @@ class FunctionSolc(Function):
link_nodes(node, new_node)
node = new_node
else:
logger.error('Statement not parsed %s'%name)
exit(-1)
raise ParsingError('Statement not parsed %s'%name)
return node
@ -814,8 +814,7 @@ class FunctionSolc(Function):
end_node = self._find_end_loop(node, [], 0)
if not end_node:
logger.error('Break in no-loop context {}'.format(node))
exit(-1)
raise ParsingError('Break in no-loop context {}'.format(node))
for son in node.sons:
son.remove_father(node)
@ -826,8 +825,7 @@ class FunctionSolc(Function):
start_node = self._find_start_loop(node, [])
if not start_node:
logger.error('Continue in no-loop context {}'.format(node.nodeId()))
exit(-1)
raise ParsingError('Continue in no-loop context {}'.format(node.nodeId()))
for son in node.sons:
son.remove_father(node)

@ -0,0 +1,7 @@
from slither.exceptions import SlitherException
class ParsingError(SlitherException): pass
class ParsingNameReuse(SlitherException): pass
class ParsingContractNotFound(SlitherException): pass

@ -35,7 +35,7 @@ from slither.core.solidity_types import (ArrayType, ElementaryType,
FunctionType, MappingType)
from slither.solc_parsing.solidity_types.type_parsing import (UnknownType,
parse_type)
from slither.solc_parsing.exceptions import ParsingError
logger = logging.getLogger("ExpressionParsing")
@ -78,8 +78,7 @@ def find_variable(var_name, caller_context, referenced_declaration=None):
function = caller_context
contract = function.contract
else:
logger.error('Incorrect caller context')
exit(-1)
raise ParsingError('Incorrect caller context')
if function:
# We look for variable declared with the referencedDeclaration attr
@ -627,8 +626,7 @@ def parse_expression(expression, caller_context):
elif type_name[caller_context.get_key()] == 'FunctionTypeName':
array_type = parse_type(type_name, caller_context)
else:
logger.error('Incorrect type array {}'.format(type_name))
exit(-1)
raise ParsingError('Incorrect type array {}'.format(type_name))
array = NewArray(depth, array_type)
return array
@ -664,5 +662,5 @@ def parse_expression(expression, caller_context):
call = CallExpression(called, arguments, 'Modifier')
return call
logger.error('Expression not parsed %s'%name)
exit(-1)
raise ParsingError('Expression not parsed %s'%name)

@ -14,6 +14,7 @@ from slither.core.declarations.import_directive import Import
from slither.analyses.data_dependency.data_dependency import compute_dependency
from slither.utils.colors import red
from .exceptions import ParsingNameReuse, ParsingContractNotFound
class SlitherSolc(Slither):
@ -182,8 +183,7 @@ class SlitherSolc(Slither):
info += '\n{} is defined in:'.format(contract.name)
info += '\n- {}\n- {}'.format(contract.source_mapping_str,
self._contracts[contract.name].source_mapping_str)
logger.error(info)
exit(-1)
raise ParsingNameReuse(info)
else:
self._contracts_by_id[contract.id] = contract
self._contracts[contract.name] = contract
@ -217,11 +217,11 @@ class SlitherSolc(Slither):
father_constructors.append(self._contracts_by_id[i])
except KeyError:
logger.error(red('A contract was not found, it is likely that your codebase contains muliple contracts with the same name'))
logger.error(red('Truffle does not handle this case during compilation'))
logger.error(red('Please read https://github.com/trailofbits/slither/wiki#keyerror-or-nonetype-error'))
logger.error(red('And update your code to remove the duplicate'))
exit(-1)
txt = 'A contract was not found, it is likely that your codebase contains muliple contracts with the same name'
txt += 'Truffle does not handle this case during compilation'
txt += 'Please read https://github.com/trailofbits/slither/wiki#keyerror-or-nonetype-error'
txt += 'And update your code to remove the duplicate'
raise ParsingContractNotFound(txt)
contract.setInheritance(ancestors, fathers, father_constructors)
contracts_to_be_analyzed = self.contracts

@ -13,6 +13,7 @@ from slither.core.declarations.function import Function
from slither.core.expressions.literal import Literal
from slither.solc_parsing.exceptions import ParsingError
import re
logger = logging.getLogger('TypeParsing')
@ -118,8 +119,7 @@ def _find_from_type_name(name, contract, contracts, structures, enums):
return MappingType(from_type, to_type)
if not var_type:
logger.error('Type not found '+str(name))
exit(-1)
raise ParsingError('Type not found '+str(name))
return UserDefinedType(var_type)
@ -134,8 +134,7 @@ def parse_type(t, caller_context):
elif isinstance(caller_context, Function):
contract = caller_context.contract
else:
logger.error('Incorrect caller context')
exit(-1)
raise ParsingError('Incorrect caller context')
is_compact_ast = caller_context.is_compact_ast
@ -223,5 +222,4 @@ def parse_type(t, caller_context):
return FunctionType(params_vars, return_values_vars)
logger.error('Type name not found '+str(t))
exit(-1)
raise ParsingError('Type name not found '+str(t))

@ -6,7 +6,7 @@ from slither.core.variables.variable import Variable
from slither.solc_parsing.solidity_types.type_parsing import parse_type, UnknownType
from slither.core.solidity_types.elementary_type import ElementaryType, NonElementaryType
from slither.solc_parsing.exceptions import ParsingError
logger = logging.getLogger("VariableDeclarationSolcParsing")
class MultipleVariablesDeclaration(Exception):
@ -51,8 +51,7 @@ class VariableDeclarationSolc(Variable):
elif nodeType == 'VariableDeclaration':
self._init_from_declaration(var, var['value'])
else:
logger.error('Incorrect variable declaration type {}'.format(nodeType))
exit(-1)
raise ParsingError('Incorrect variable declaration type {}'.format(nodeType))
else:
nodeType = var['name']
@ -65,15 +64,13 @@ class VariableDeclarationSolc(Variable):
elif len(var['children']) > 2:
raise MultipleVariablesDeclaration
else:
logger.error('Variable declaration without children?'+var)
exit(-1)
raise ParsingError('Variable declaration without children?'+var)
declaration = var['children'][0]
self._init_from_declaration(declaration, init)
elif nodeType == 'VariableDeclaration':
self._init_from_declaration(var, None)
else:
logger.error('Incorrect variable declaration type {}'.format(nodeType))
exit(-1)
raise ParsingError('Incorrect variable declaration type {}'.format(nodeType))
@property
def initialized(self):

@ -15,6 +15,7 @@ from slither.core.expressions.new_elementary_type import NewElementaryType
from slither.core.expressions.tuple_expression import TupleExpression
from slither.core.expressions.type_conversion import TypeConversion
from slither.core.expressions.unary_operation import UnaryOperation
from slither.exceptions import SlitherError
logger = logging.getLogger("ExpressionVisitor")
@ -86,8 +87,7 @@ class ExpressionVisitor:
pass
else:
logger.error('Expression not handled: {}'.format(expression))
exit(-1)
raise SlitherError('Expression not handled: {}'.format(expression))
self._post_visit(expression)
@ -200,8 +200,7 @@ class ExpressionVisitor:
pass
else:
logger.error('Expression not handled: {}'.format(expression))
exit(-1)
raise SlitherError('Expression not handled: {}'.format(expression))
# pre_expression_name
@ -302,8 +301,7 @@ class ExpressionVisitor:
pass
else:
logger.error('Expression not handled: {}'.format(expression))
exit(-1)
raise SlitherError('Expression not handled: {}'.format(expression))
# post_expression_name

@ -17,8 +17,7 @@ from slither.slithir.variables import (Constant, ReferenceVariable,
TemporaryVariable, TupleVariable)
from slither.visitors.expression.expression import ExpressionVisitor
#from slither.slithir.variables.state_variable import StateIRVariable
#from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.exceptions import SlithIRError
logger = logging.getLogger("VISTIOR:ExpressionToSlithIR")
@ -57,8 +56,7 @@ def convert_assignment(left, right, t, return_type):
elif t == AssignmentOperationType.ASSIGN_MODULO:
return Binary(left, left, right, BinaryType.MODULO)
logger.error('Missing type during assignment conversion')
exit(-1)
raise SlithIRError('Missing type during assignment conversion')
class ExpressionToSlithIR(ExpressionVisitor):

Loading…
Cancel
Save