diff --git a/manticore/binary/binary.py b/manticore/binary/binary.py index 4376a6fcb..c8a7fffc0 100644 --- a/manticore/binary/binary.py +++ b/manticore/binary/binary.py @@ -29,6 +29,14 @@ def threads(self): pass +class BinaryException(Exception): + """ + Binary file exception + """ + + pass + + class CGCElf(Binary): @staticmethod def _cgc2elf(filename): @@ -51,7 +59,7 @@ def __init__(self, filename): def maps(self): for elf_segment in self.elf.iter_segments(): if elf_segment.header.p_type not in ["PT_LOAD", "PT_NULL", "PT_PHDR", "PT_CGCPOV2"]: - raise Exception("Not Supported Section") + raise BinaryException("Not Supported Section") if elf_segment.header.p_type != "PT_LOAD" or elf_segment.header.p_memsz == 0: continue @@ -60,7 +68,7 @@ def maps(self): # PF_X 0x1 Execute - PF_W 0x2 Write - PF_R 0x4 Read perms = [" ", " x", " w ", " wx", "r ", "r x", "rw ", "rwx"][flags & 7] if "r" not in perms: - raise Exception("Not readable map from cgc elf not supported") + raise BinaryException("Not readable map from cgc elf not supported") # CGCMAP-- assert elf_segment.header.p_filesz != 0 or elf_segment.header.p_memsz != 0 @@ -106,7 +114,7 @@ def maps(self): # PF_X 0x1 Execute - PF_W 0x2 Write - PF_R 0x4 Read perms = [" ", " x", " w ", " wx", "r ", "r x", "rw ", "rwx"][flags & 7] if "r" not in perms: - raise Exception("Not readable map from cgc elf not supported") + raise BinaryException("Not readable map from cgc elf not supported") # CGCMAP-- assert elf_segment.header.p_filesz != 0 or elf_segment.header.p_memsz != 0 diff --git a/manticore/core/manticore.py b/manticore/core/manticore.py index b20241d44..95eff0180 100644 --- a/manticore/core/manticore.py +++ b/manticore/core/manticore.py @@ -74,7 +74,7 @@ def to_class(self): class ManticoreBase(Eventful): def __new__(cls, *args, **kwargs): if cls in (ManticoreBase, ManticoreSingle, ManticoreThreading, ManticoreMultiprocessing): - raise Exception("Should not instantiate this") + raise ManticoreError("Should not instantiate this") cl = consts.mprocessing.to_class() # change ManticoreBase for the more specific class @@ -103,7 +103,7 @@ def at_running(func): @functools.wraps(func) def newFunction(self, *args, **kw): if not self.is_running(): - raise Exception(f"{func.__name__} only allowed while exploring states") + raise ManticoreError(f"{func.__name__} only allowed while exploring states") return func(self, *args, **kw) return newFunction @@ -117,7 +117,7 @@ def at_not_running(func): def newFunction(self, *args, **kw): if self.is_running(): logger.error("Calling at running not allowed") - raise Exception(f"{func.__name__} only allowed while NOT exploring states") + raise ManticoreError(f"{func.__name__} only allowed while NOT exploring states") return func(self, *args, **kw) return newFunction @@ -265,7 +265,7 @@ def __init__(self, initial_state, workspace_url=None, policy="random", **kwargs) "_shared_context", ) ): - raise Exception("Need to instantiate one of: ManticoreNative, ManticoreThreads..") + raise ManticoreError("Need to instantiate one of: ManticoreNative, ManticoreThreads..") # The workspace and the output # Manticore will use the workspace to save and share temporary states. @@ -510,7 +510,7 @@ def _terminate_state(self, state_id, delete=False): """ # wait for a state id to be added to the ready list and remove it if state_id not in self._busy_states: - raise Exception("Can not terminate. State is not being analyzed") + raise ManticoreError("Can not terminate. State is not being analyzed") self._busy_states.remove(state_id) if delete: @@ -537,7 +537,7 @@ def _kill_state(self, state_id, delete=False): """ # wait for a state id to be added to the ready list and remove it if state_id not in self._busy_states: - raise Exception("Can not even kill it. State is not being analyzed") + raise ManticoreError("Can not even kill it. State is not being analyzed") self._busy_states.remove(state_id) if delete: diff --git a/manticore/core/parser/parser.py b/manticore/core/parser/parser.py index ef60cad1c..9a96a0474 100644 --- a/manticore/core/parser/parser.py +++ b/manticore/core/parser/parser.py @@ -13,6 +13,15 @@ import ply.lex as lex import re + +class ParserException(Exception): + """ + Parser exception + """ + + pass + + # List of token names. This is always required tokens = ( "NUMBER", @@ -100,7 +109,7 @@ def t_TOKEN(t): elif re_SEGMENT.match(t.value): t.type = "SEGMENT" else: - raise Exception(f"Unknown:<{t.value}>") + raise ParserException(f"Unknown:<{t.value}>") return t @@ -326,7 +335,7 @@ def parse(expression, read_memory=None, read_register=None, get_descriptor=None, elif word_size == 64: sizes = copy.copy(default_sizes_64) else: - raise Exception("Not Supported") + raise ParserException("Got unsupported word size") result = parser.parse(expression, tracking=True) del functions["read_memory"] del functions["read_register"] diff --git a/manticore/core/smtlib/constraints.py b/manticore/core/smtlib/constraints.py index f46185b07..511a10185 100644 --- a/manticore/core/smtlib/constraints.py +++ b/manticore/core/smtlib/constraints.py @@ -2,6 +2,7 @@ import sys from ...utils.helpers import PickleSerializer +from ...exceptions import SmtlibError from .expression import ( BitVecVariable, BoolVariable, @@ -21,6 +22,14 @@ logger = logging.getLogger(__name__) +class ConstraintException(SmtlibError): + """ + Constraint exception + """ + + pass + + class ConstraintSet: """ Constraint Sets @@ -81,7 +90,7 @@ def add(self, constraint, check=False): # constraints to this one. After the child constraintSet is deleted # we regain the ability to add constraints. if self._child is not None: - raise Exception("ConstraintSet is frozen") + raise ConstraintException("ConstraintSet is frozen") if isinstance(constraint, BoolConstant): if not constraint.value: @@ -186,7 +195,7 @@ def to_string(self, related_to=None, replace_constants=True): elif isinstance(exp, Array): result += f"(declare-fun {name} () (Array (_ BitVec {exp.index_bits}) (_ BitVec {exp.value_bits})))" else: - raise Exception(f"Type not supported {exp!r}") + raise ConstraintException(f"Type not supported {exp!r}") result += f"(assert (= {name} {smtlib}))\n" constraint_str = translator.pop() @@ -221,7 +230,7 @@ def declarations(self): except RuntimeError: # TODO: (defunct) move recursion management out of PickleSerializer if sys.getrecursionlimit() >= PickleSerializer.MAX_RECURSION: - raise Exception( + raise ConstraintException( f"declarations recursion limit surpassed {PickleSerializer.MAX_RECURSION}, aborting" ) new_limit = sys.getrecursionlimit() + PickleSerializer.DEFAULT_RECURSION diff --git a/manticore/core/smtlib/expression.py b/manticore/core/smtlib/expression.py index bca3b5f52..a4df7bdc8 100644 --- a/manticore/core/smtlib/expression.py +++ b/manticore/core/smtlib/expression.py @@ -1,10 +1,19 @@ from functools import reduce +from ...exceptions import SmtlibError import uuid import re import copy +class ExpressionException(SmtlibError): + """ + Expression exception + """ + + pass + + class Expression: """ Abstract taintable Expression. """ @@ -118,10 +127,10 @@ def name(self): return self._name def __copy__(self, memo): - raise Exception("Copying of Variables is not allowed.") + raise ExpressionException("Copying of Variables is not allowed.") def __deepcopy__(self, memo): - raise Exception("Copying of Variables is not allowed.") + raise ExpressionException("Copying of Variables is not allowed.") def __repr__(self): return "<{:s}({:s}) at {:x}>".format(type(self).__name__, self.name, id(self)) @@ -697,7 +706,7 @@ def cast_value(self, value): def __len__(self): if self.index_max is None: - raise Exception("Array max index not set") + raise ExpressionException("Array max index not set") return self.index_max @property diff --git a/manticore/core/smtlib/solver.py b/manticore/core/smtlib/solver.py index 285eb6efa..1701f677f 100644 --- a/manticore/core/smtlib/solver.py +++ b/manticore/core/smtlib/solver.py @@ -24,7 +24,7 @@ from . import operators as Operators from .constraints import * from .visitors import * -from ...exceptions import Z3NotFoundError, SolverError, SolverUnknown, TooManySolutions +from ...exceptions import Z3NotFoundError, SolverError, SolverUnknown, TooManySolutions, SmtlibError from ...utils import config from . import issymbolic import time @@ -62,6 +62,14 @@ def instance(cls): return cls.__singleton_instances[(pid, tid)] +class SolverException(SmtlibError): + """ + Solver exception + """ + + pass + + class Solver(SingletonMixin): def __init__(self): pass @@ -75,7 +83,7 @@ def optimize(self, constraints, X, operation, M=10000): :param X: a symbol or expression :param M: maximum number of iterations allowed """ - raise Exception("Abstract method not implemented") + raise SmtlibError("Abstract method not implemented") def check(self, constraints) -> bool: """Check if given constraints can be valid""" @@ -83,7 +91,7 @@ def check(self, constraints) -> bool: def can_be_true(self, constraints, expression) -> bool: """Check if given expression could be valid""" - raise Exception("Abstract method not implemented") + raise SolverException("Abstract method not implemented") def must_be_true(self, constraints, expression) -> bool: """Check if expression is True and that it can not be False with current constraints""" @@ -92,11 +100,11 @@ def must_be_true(self, constraints, expression) -> bool: def get_all_values(self, constraints, x, maxcnt=10000, silent=False): """Returns a list with all the possible values for the symbol x""" - raise Exception("Abstract method not implemented") + raise SolverException("Abstract method not implemented") def get_value(self, constraints, expression): """Ask the solver for one possible result of given expression using given set of constraints.""" - raise Exception("Abstract method not implemented") + raise SolverException("Abstract method not implemented") def max(self, constraints, X: BitVec, M=10000): """ @@ -246,10 +254,10 @@ def _stop_proc(self): # marshaling/pickle def __getstate__(self): - raise Exception() + raise SolverException() def __setstate__(self, state): - raise Exception() + raise SolverException() def __del__(self): try: @@ -306,7 +314,7 @@ def _recv(self) -> str: # logger.debug('<%s', buf) if "(error" in bufl[0]: - raise Exception(f"Error in smtlib: {bufl[0]}") + raise SolverException(f"Error in smtlib: {bufl[0]}") return buf def __readline_and_count(self): diff --git a/manticore/core/smtlib/visitors.py b/manticore/core/smtlib/visitors.py index 36fbc5253..bbeed5094 100644 --- a/manticore/core/smtlib/visitors.py +++ b/manticore/core/smtlib/visitors.py @@ -1,4 +1,5 @@ from ...utils.helpers import CacheDict +from ...exceptions import SmtlibError from .expression import * from functools import lru_cache import logging @@ -136,7 +137,7 @@ def _method(self, expression, *args): value = getattr(self, methodname)(expression, *args) if value is not None: return value - raise Exception(f"No translation for this {expression}") + raise SmtlibError(f"No translation for this {expression}") class GetDeclarations(Visitor): @@ -749,7 +750,7 @@ def visit_Operation(self, expression, *operands): @property def results(self): - raise Exception("NOOO") + raise SmtlibError("NOOO") @property def result(self): diff --git a/manticore/core/state.py b/manticore/core/state.py index 5b03105f0..25c8bda9f 100644 --- a/manticore/core/state.py +++ b/manticore/core/state.py @@ -44,7 +44,9 @@ def __init__(self, message, expression, setstate=None, policy=None, **kwargs): if policy is None: policy = "ALL" if policy not in self._ValidPolicies: - raise Exception(f'Policy ({policy}) must be one of: {", ".join(self._ValidPolicies)}') + raise StateException( + f'Policy ({policy}) must be one of: {", ".join(self._ValidPolicies)}' + ) self.expression = expression self.setstate = setstate self.policy = policy diff --git a/manticore/core/workspace.py b/manticore/core/workspace.py index e1ecaa1b0..508a21f1a 100644 --- a/manticore/core/workspace.py +++ b/manticore/core/workspace.py @@ -31,6 +31,7 @@ def __exit__(self, *excinfo): from ..utils.helpers import PickleSerializer from .smtlib.solver import Z3Solver from .state import StateBase +from ..exceptions import ManticoreError logger = logging.getLogger(__name__) @@ -342,7 +343,7 @@ def lock(self): @contextmanager def stream(self, key, mode="r", lock=False): if lock: - raise Exception("mem: does not support concurrency") + raise ManticoreError("mem: does not support concurrency") if "b" in mode: s = io.BytesIO(self._data.get(key, b"")) else: diff --git a/manticore/ethereum/abitypes.py b/manticore/ethereum/abitypes.py index c31d33636..4751602f9 100644 --- a/manticore/ethereum/abitypes.py +++ b/manticore/ethereum/abitypes.py @@ -1,7 +1,7 @@ # Minimal ethereum type signature parser. # This parses the signature and types used to calculate the function hash import warnings - +from ..exceptions import EthereumError import ply.yacc as yacc # Lexer @@ -141,7 +141,7 @@ def t_FUNCTION(t): # Error handling rule def t_error(t): - raise Exception("Illegal character '%s'" % t.value[0]) + raise EthereumError("Illegal character '%s'" % t.value[0]) # Build the lexer @@ -217,7 +217,7 @@ def p_dynamic_fixed_type(p): def p_error(p): - raise Exception("Syntax Error at abitypes") + raise EthereumError("Syntax Error at abitypes") # print(f"Syntax error at offset {lexer.lexpos:d}") diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index 267abaa67..07a1986d7 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -634,7 +634,7 @@ def json_create_contract( ) if "signature" in item: if item["signature"] != f"0x{hashes[signature]}": - raise Exception( + raise EthereumError( f"Something wrong with the sha3 of the method {signature} signature (a.k.a. the hash)" ) @@ -643,7 +643,7 @@ def json_create_contract( if network_id is None: if len(truffle["networks"]) > 1: - raise Exception("Network id not specified") + raise EthereumError("Network id not specified") if len(truffle["networks"]) == 1: network_id = list(truffle["networks"].keys())[0] if network_id in truffle["networks"]: @@ -1261,7 +1261,7 @@ def run(self, **kwargs): # At the begining of a human tx/run it should not be any saved state with self.locked_context("ethereum.saved_states", list) as saved_states: if saved_states: - raise Exception("ethereum.saved_states should be empty") + raise EthereumError("ethereum.saved_states should be empty") # Every state.world has its pending_transaction filled. The run will # process it and potentially generate several READY and.or TERMINATED states. diff --git a/manticore/native/cpu/x86.py b/manticore/native/cpu/x86.py index 0f13766ee..8292fbc8c 100644 --- a/manticore/native/cpu/x86.py +++ b/manticore/native/cpu/x86.py @@ -9,6 +9,7 @@ Abi, SyscallAbi, Cpu, + CpuException, RegisterFile, Operand, instruction, @@ -5895,7 +5896,7 @@ def MOVQ(cpu, dest, src): else: msg = "Invalid size in MOVQ" logger.error(msg) - raise Exception(msg) + raise CpuException(msg) @instruction def MOVSD(cpu, dest, src): diff --git a/manticore/native/manticore.py b/manticore/native/manticore.py index 1cc2dbf94..52a67a2be 100644 --- a/manticore/native/manticore.py +++ b/manticore/native/manticore.py @@ -137,7 +137,7 @@ def linux( **kwargs, ) except elftools.common.exceptions.ELFError: - raise Exception(f"Invalid binary: {path}") + raise ManticoreError(f"Invalid binary: {path}") @classmethod def decree(cls, path, concrete_start="", **kwargs): @@ -153,7 +153,7 @@ def decree(cls, path, concrete_start="", **kwargs): try: return cls(_make_decree(path, concrete_start), **kwargs) except KeyError: # FIXME(mark) magic parsing for DECREE should raise better error - raise Exception(f"Invalid binary: {path}") + raise ManticoreError(f"Invalid binary: {path}") @property def binary_path(self): @@ -386,7 +386,7 @@ def _make_linux( entry_pc = platform._find_symbol(entry_symbol) if entry_pc is None: logger.error("No symbol for '%s' in %s", entry_symbol, program) - raise Exception("Symbol not found") + raise ManticoreError("Symbol not found") else: logger.info("Found symbol '%s' (%x)", entry_symbol, entry_pc) # TODO: use argv as arguments for function diff --git a/manticore/platforms/evm.py b/manticore/platforms/evm.py index ade47b71b..d838844cd 100644 --- a/manticore/platforms/evm.py +++ b/manticore/platforms/evm.py @@ -1024,7 +1024,7 @@ def _consume(self, fee): raise NotEnoughGas() else: if consts.oog != "ignore": - raise Exception("Wrong oog config variable") + raise EVMException("Wrong oog config variable") # do nothing. gas is not even changed return self._gas = simplify(self._gas - fee) diff --git a/manticore/platforms/linux.py b/manticore/platforms/linux.py index 41a829103..1301f9ca3 100644 --- a/manticore/platforms/linux.py +++ b/manticore/platforms/linux.py @@ -2249,7 +2249,7 @@ def syscall(self): if name is not None: raise SyscallNotImplemented(index, name) else: - raise Exception(f"Bad syscall index, {index}") + raise EnvironmentError(f"Bad syscall index, {index}") return self._syscall_abi.invoke(implementation) diff --git a/manticore/utils/fallback_emulator.py b/manticore/utils/fallback_emulator.py index 237059a87..8bf091116 100644 --- a/manticore/utils/fallback_emulator.py +++ b/manticore/utils/fallback_emulator.py @@ -17,6 +17,14 @@ logger = logging.getLogger(__name__) +class EmulatorException(Exception): + """ + Emulator exception + """ + + pass + + class UnicornEmulator: """ Helper class to emulate a single instruction via Unicorn. @@ -41,7 +49,7 @@ def __init__(self, cpu): self._uc_arch = UC_ARCH_ARM64 self._uc_mode = UC_MODE_ARM if self._cpu.mode != UC_MODE_ARM: - raise Exception("Aarch64/Arm64 cannot have different uc mode than ARM.") + raise EmulatorException("Aarch64/Arm64 cannot have different uc mode than ARM.") elif self._cpu.arch == CS_ARCH_X86: self._uc_arch = UC_ARCH_X86 @@ -89,7 +97,7 @@ def get_unicorn_pc(self): elif self._cpu.mode == CS_MODE_64: return self._emu.reg_read(UC_X86_REG_RIP) else: - raise Exception( + raise EmulatorException( f"Getting PC after unicorn emulation for {self._cpu.arch} architecture is not implemented" )