From 2d04217a3604967bf25137a1c866111b30835fe0 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 6 Apr 2021 15:01:47 -0300 Subject: [PATCH 01/22] delay smt-solving until it is absolutely necessary --- manticore/ethereum/manticore.py | 103 ++++++++++++++++++++++++++++++++ manticore/platforms/evm.py | 72 +++++++++++++--------- 2 files changed, 147 insertions(+), 28 deletions(-) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index 8e4c733d1..0c6030a18 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -391,6 +391,7 @@ def __init__(self, plugins=None, **kwargs): # make the ethereum world state world = evm.EVMWorld(constraints) initial_state = State(constraints, world) + self._lazy_evaluation = True super().__init__(initial_state, **kwargs) if plugins is not None: for p in plugins: @@ -1947,3 +1948,105 @@ def worker_finalize(q): for proc in report_workers: proc.join() + + + def enable_lazy_evaluation(self): + """ + Enable lazy evaluation (only EVM support) + :return: + """ + self._lazy_evaluation = True + + def disable_lazy_evaluation(self): + """ + Disable lazy evaluation (only EVM support) + :return: + """ + self._lazy_evaluation = False + + def lazy_evaluation(self) -> bool: + return self._lazy_evaluation + + + def _fork(self, state, expression, policy="ALL", setstate=None): + """ + Fork state on expression concretizations. + Using policy build a list of solutions for expression. + For the state on each solution setting the new state with setstate + For example if expression is a Bool it may have 2 solutions. True or False. + Parent + (expression = ??) + Child1 Child2 + (expression = True) (expression = False) + setstate(True) setstate(False) + The optional setstate() function is supposed to set the concrete value + in the child state. + Parent state is removed from the busy list and the child states are added + to the ready list. + """ + assert isinstance(expression, Expression), f"{type(expression)} is not an Expression" + + if setstate is None: + + def setstate(x, y): + pass + + if ( + self._lazy_evaluation + and state.platform.current_vm + and state.platform.current_vm.jumpi_false_branch() + ): + + solutions = [ + (state.platform.current_vm.jumpi_false_branch(), False), + (state.platform.current_vm.jumpi_true_branch(), True), + ] + else: + + if state.platform.current_vm and isinstance(state.platform.current_vm.need_check_jumpdest(), (Expression, bool)): + print('checkjumpdst') + solutions = state.concretize(expression, policy, additional_symbolics=[state.platform.current_vm.need_check_jumpdest()]) + else: + print('normal') + solutions = [(s, False) for s in state.concretize(expression, policy)] + + if not solutions: + raise ManticoreError("Forking on unfeasible constraint set") + + print(solutions) + logger.debug( + "Forking. Policy: %s. Values: %s", policy, ", ".join(f"0x{sol:x}" for sol,_ in solutions) + ) + + self._publish("will_fork_state", state, expression, solutions, policy) + + # Build and enqueue a state for each solution + children = [] + for solution in solutions: + with state as new_state: + new_value, jump_cond = solution + new_state.constrain(expression == new_value) + + # and set the PC of the new state to the concrete pc-dest + # (or other register or memory address to concrete) + setstate(new_state, new_value) + # TODO: Ideally "jump_cond" should be in the VM and not the platform + # However, platform.current_vm is not yet created + # So not sure how to do it + new_state.platform.set_last_ins_was_true_jumpi(jump_cond) + #print(f'{hex(new_value)} -> {jump_cond}') + + # enqueue new_state, assign new state id + new_state_id = self._put_state(new_state) + + # maintain a list of children for logging purpose + children.append(new_state_id) + + self._publish("did_fork_state", state, expression, solutions, policy, children) + logger.debug("Forking current state %r into states %r", state.id, children) + + with self._lock: + self._busy_states.remove(state.id) + self._remove(state.id) + state._id = None + self._lock.notify_all() diff --git a/manticore/platforms/evm.py b/manticore/platforms/evm.py index 631166c8e..35e0d39d0 100644 --- a/manticore/platforms/evm.py +++ b/manticore/platforms/evm.py @@ -6,7 +6,7 @@ import copy import inspect from functools import wraps -from typing import List, Set, Tuple, Union +from typing import List, Set, Tuple, Union, Optional from ..platforms.platform import * from ..core.smtlib import ( SelectedSolver, @@ -820,6 +820,14 @@ def extend_with_zeroes(b): self._temp_call_gas = None self._failed = False + # Use to keep track of the jumpi destination + # Only save PUSH X values + #self._concrete_stack: List[Optional[int]] = [] + # Save the JUMPI false branch, or None if it was not a JUMPI + self._jumpi_false_branch: Optional[int] = None + self._jumpi_true_branch: Optional[int] = None + self._jump_cond = False + def fail_if(self, failed): self._failed = Operators.OR(self._failed, failed) @@ -863,6 +871,19 @@ def constraints(self, constraints): def gas(self): return Operators.EXTRACT(self._gas, 0, 256) + def jumpi_false_branch(self) -> Optional[int]: + """ + Return the JUMPI false branch. Return None if the last instruction was not a JUMPI + """ + return self._jumpi_false_branch + + def jumpi_true_branch(self) -> Optional[int]: + """ + Return the JUMPI false branch. Return None if the last instruction was not a JUMPI + """ + return self._jumpi_true_branch + + def __getstate__(self): state = super().__getstate__() state["sha3"] = self._sha3 @@ -1178,6 +1199,9 @@ def _handler(self, *arguments): implementation = getattr(self, current.semantics, None) if implementation is None: raise TerminateState(f"Instruction not implemented {current.semantics}", testcase=True) + + self._jumpi_false_branch = None + self._need_check_jumpdest = None return implementation(*arguments) def _checkpoint(self): @@ -1215,6 +1239,9 @@ def _rollback(self): self._allocated = allocated self._checkpoint_data = None + def need_check_jumpdest(self): + return self._need_check_jumpdest + def _set_check_jmpdest(self, flag=True): """ Next instruction must be a JUMPDEST iff `flag` holds. @@ -1233,37 +1260,14 @@ def _check_jmpdest(self): already constrained to a single concrete value. """ # If pc is already pointing to a JUMPDEST thre is no need to check. - pc = self.pc.value if isinstance(self.pc, Constant) else self.pc - if pc in self._valid_jumpdests: - self._need_check_jumpdest = False - return - - should_check_jumpdest = simplify(self._need_check_jumpdest) - if isinstance(should_check_jumpdest, Constant): - should_check_jumpdest = should_check_jumpdest.value - elif issymbolic(should_check_jumpdest): - self._publish("will_solve", self.constraints, should_check_jumpdest, "get_all_values") - should_check_jumpdest_solutions = SelectedSolver.instance().get_all_values( - self.constraints, should_check_jumpdest - ) - self._publish( - "did_solve", - self.constraints, - should_check_jumpdest, - "get_all_values", - should_check_jumpdest_solutions, - ) - if len(should_check_jumpdest_solutions) != 1: - raise EthereumError("Conditional not concretized at JMPDEST check") - should_check_jumpdest = should_check_jumpdest_solutions[0] - - # If it can be solved only to False just set it False. If it can be solved - # only to True, process it and also set it to False self._need_check_jumpdest = False - if should_check_jumpdest: + if self._world.last_ins_was_true_jumpi(): + pc = self.pc.value if isinstance(self.pc, Constant) else self.pc if pc not in self._valid_jumpdests: self._throw() + self._world.set_last_ins_was_true_jumpi(False) + return def _advance(self, result=None, exception=False): if self._checkpoint_data is None: @@ -2082,6 +2086,8 @@ def JUMPI(self, dest, cond): """Conditionally alter the program counter""" # TODO(feliam) If dest is Constant we do not need to 3 queries. There would # be only 2 options + self._jumpi_false_branch = self.pc + self.instruction.size + self._jumpi_true_branch = dest self.pc = Operators.ITEBV(256, cond != 0, dest, self.pc + self.instruction.size) # This set ups a check for JMPDEST in the next instruction if cond != 0 @@ -2429,6 +2435,8 @@ def __init__(self, constraints, fork=DEFAULT_FORK, **kwargs): self._fork = fork self._block_header = None self.start_block() + # True if the last instruction was a JUMPI and the true branch was taken + self._last_ins_was_true_jumpi = False def __getstate__(self): state = super().__getstate__() @@ -2441,6 +2449,7 @@ def __getstate__(self): state["_transactions"] = self._transactions state["_fork"] = self._fork state["_block_header"] = self._block_header + state["_last_ins_was_true_jumpi"] = self._last_ins_was_true_jumpi return state @@ -2455,6 +2464,7 @@ def __setstate__(self, state): self._transactions = state["_transactions"] self._fork = state["_fork"] self._block_header = state["_block_header"] + self._last_ins_was_true_jumpi = state["_last_ins_was_true_jumpi"] for _, _, _, _, vm in self._callstack: self.forward_events_from(vm) @@ -2539,6 +2549,12 @@ def constraints(self, constraints): if self.current_vm: self.current_vm.constraints = constraints + def last_ins_was_true_jumpi(self) -> Optional[bool]: + return self._last_ins_was_true_jumpi + + def set_last_ins_was_true_jumpi(self, jump_cond: Optional[bool]): + self._last_ins_was_true_jumpi = jump_cond + @property def evmfork(self): return self._fork From 9aa2f871da2a7e57725aef19e6dfdbd0b7ddebc7 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 6 Apr 2021 15:04:56 -0300 Subject: [PATCH 02/22] linted --- manticore/ethereum/manticore.py | 22 ++++++++++++++-------- manticore/platforms/evm.py | 3 +-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index 0c6030a18..b59a1eeb0 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -1949,7 +1949,6 @@ def worker_finalize(q): for proc in report_workers: proc.join() - def enable_lazy_evaluation(self): """ Enable lazy evaluation (only EVM support) @@ -1967,7 +1966,6 @@ def disable_lazy_evaluation(self): def lazy_evaluation(self) -> bool: return self._lazy_evaluation - def _fork(self, state, expression, policy="ALL", setstate=None): """ Fork state on expression concretizations. @@ -2003,11 +2001,17 @@ def setstate(x, y): ] else: - if state.platform.current_vm and isinstance(state.platform.current_vm.need_check_jumpdest(), (Expression, bool)): - print('checkjumpdst') - solutions = state.concretize(expression, policy, additional_symbolics=[state.platform.current_vm.need_check_jumpdest()]) + if state.platform.current_vm and isinstance( + state.platform.current_vm.need_check_jumpdest(), (Expression, bool) + ): + print("checkjumpdst") + solutions = state.concretize( + expression, + policy, + additional_symbolics=[state.platform.current_vm.need_check_jumpdest()], + ) else: - print('normal') + print("normal") solutions = [(s, False) for s in state.concretize(expression, policy)] if not solutions: @@ -2015,7 +2019,9 @@ def setstate(x, y): print(solutions) logger.debug( - "Forking. Policy: %s. Values: %s", policy, ", ".join(f"0x{sol:x}" for sol,_ in solutions) + "Forking. Policy: %s. Values: %s", + policy, + ", ".join(f"0x{sol:x}" for sol, _ in solutions), ) self._publish("will_fork_state", state, expression, solutions, policy) @@ -2034,7 +2040,7 @@ def setstate(x, y): # However, platform.current_vm is not yet created # So not sure how to do it new_state.platform.set_last_ins_was_true_jumpi(jump_cond) - #print(f'{hex(new_value)} -> {jump_cond}') + # print(f'{hex(new_value)} -> {jump_cond}') # enqueue new_state, assign new state id new_state_id = self._put_state(new_state) diff --git a/manticore/platforms/evm.py b/manticore/platforms/evm.py index 35e0d39d0..aa9059bd6 100644 --- a/manticore/platforms/evm.py +++ b/manticore/platforms/evm.py @@ -822,7 +822,7 @@ def extend_with_zeroes(b): # Use to keep track of the jumpi destination # Only save PUSH X values - #self._concrete_stack: List[Optional[int]] = [] + # self._concrete_stack: List[Optional[int]] = [] # Save the JUMPI false branch, or None if it was not a JUMPI self._jumpi_false_branch: Optional[int] = None self._jumpi_true_branch: Optional[int] = None @@ -883,7 +883,6 @@ def jumpi_true_branch(self) -> Optional[int]: """ return self._jumpi_true_branch - def __getstate__(self): state = super().__getstate__() state["sha3"] = self._sha3 From 709d1d722cc8c7138df31320064de2ce77b958ab Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 6 Apr 2021 18:20:41 -0300 Subject: [PATCH 03/22] force finalization in the VMTests --- tests/auto_generators/make_VMTests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto_generators/make_VMTests.py b/tests/auto_generators/make_VMTests.py index bd32b30a4..b831dc322 100644 --- a/tests/auto_generators/make_VMTests.py +++ b/tests/auto_generators/make_VMTests.py @@ -212,6 +212,7 @@ def did_close_transaction_callback(self, state, tx): price={price})""" body += f""" + m.finalize() for state in m.all_states: world = state.platform self.assertEqual(used_gas_plugin.used_gas, {blockheader['gasUsed']}) From 4b2b0ce746d5c7d938df642061ae3c0dcd5b2ab1 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Wed, 7 Apr 2021 17:00:58 -0300 Subject: [PATCH 04/22] fixed unsoundness tests --- manticore/ethereum/manticore.py | 31 +++++++++++++++++++++++-------- tests/ethereum/test_sha3.py | 28 ++++++++++++++-------------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index b59a1eeb0..5fb2746b1 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -52,6 +52,11 @@ 60 * 60, "Default timeout for matching sha3 for unsound states (see unsound symbolication).", ) +consts.add( + "lazymode", + True, + "Only call the solver when it is absolutely necessary to generate testcases.", +) def flagged(flag): @@ -391,7 +396,7 @@ def __init__(self, plugins=None, **kwargs): # make the ethereum world state world = evm.EVMWorld(constraints) initial_state = State(constraints, world) - self._lazy_evaluation = True + self._lazy_evaluation = consts.lazymode super().__init__(initial_state, **kwargs) if plugins is not None: for p in plugins: @@ -1415,10 +1420,20 @@ def match(state, func, symbolic_pairs, concrete_pairs, start=None): # Ok all functions had a match for current state return state.can_be_true(True) - def fix_unsound_symbolication(self, state): + def fix_unsound_lazy(self, state): + return state.can_be_true(True) + + def is_sound(self, state): soundcheck = state.context.get("soundcheck", None) if soundcheck is not None: return soundcheck + + if consts.lazymode: + state.context["soundcheck"] = self.fix_unsound_lazy(state) + + if not state.context["soundcheck"]: + return state.context["soundcheck"] # no need to keep checking + if consts.sha3 is consts.sha3.symbolicate: state.context["soundcheck"] = self.fix_unsound_symbolication_sound(state) elif consts.sha3 is consts.sha3.fake: @@ -1591,7 +1606,7 @@ def _generate_testcase_ex(self, state, message="", name="user"): :rtype: bool """ # Refuse to generate a testcase from an unsound state - if not self.fix_unsound_symbolication(state): + if not self.is_sound(state): raise ManticoreError("Trying to generate a testcase out of an unsound state path") blockchain = state.platform @@ -1729,7 +1744,7 @@ def finalize(self, procs=None, only_alive_states=False): def finalizer(state_id): st = self._load(state_id) - if self.fix_unsound_symbolication(st): + if self.is_sound(st): last_tx = st.platform.last_transaction # Do not generate killed state if only_alive_states is True if only_alive_states and last_tx.result in {"REVERT", "THROW", "TXERROR"}: @@ -1760,7 +1775,7 @@ def worker_finalize(q): global_findings = set() for state in self.all_states: - if not self.fix_unsound_symbolication(state): + if not self.is_sound(state): continue for detector in self.detectors.values(): for address, pc, finding, at_init, constraint in detector.get_findings(state): @@ -1889,7 +1904,7 @@ def ready_sound_states(self): _ready_states = self._ready_states for state_id in _ready_states: state = self._load(state_id) - if self.fix_unsound_symbolication(state): + if self.is_sound(state): yield state # Re-save the state in case the user changed its data self._save(state, state_id=state_id) @@ -1911,7 +1926,7 @@ def all_sound_states(self): _ready_states = self._ready_states for state_id in _ready_states: state = self._load(state_id) - if self.fix_unsound_symbolication(state): + if self.is_sound(state): yield state # Re-save the state in case the user changed its data self._save(state, state_id=state_id) @@ -1926,7 +1941,7 @@ def fix_unsound_all(self, procs=None): # Fix unsoundness in all states def finalizer(state_id): state = self._load(state_id) - self.fix_unsound_symbolication(state) + self.is_sound(state) self._save(state, state_id=state_id) def worker_finalize(q): diff --git a/tests/ethereum/test_sha3.py b/tests/ethereum/test_sha3.py index 1791ac1e1..dc6e0ea74 100644 --- a/tests/ethereum/test_sha3.py +++ b/tests/ethereum/test_sha3.py @@ -56,9 +56,9 @@ def test_example1(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) - continue + continue found += len(st.platform.logs) self.assertEqual(found, 0) # log is not reachable @@ -87,7 +87,7 @@ def test_example2(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -118,7 +118,7 @@ def test_example3(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -153,7 +153,7 @@ def test_example4(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -190,7 +190,7 @@ def test_example5(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -226,7 +226,7 @@ def test_example6(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -263,7 +263,7 @@ def test_example7(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -300,7 +300,7 @@ def test_example8(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -335,7 +335,7 @@ def test_essence1(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue m.generate_testcase(st) @@ -368,7 +368,7 @@ def test_essence2(self): contract.foo(x) found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue @@ -407,7 +407,7 @@ def test_essence3(self): contract.foo(x2) for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue @@ -459,7 +459,7 @@ def test_example_concrete_1(self): found = 0 for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue found += len(st.platform.logs) @@ -514,7 +514,7 @@ def test_essence3(self): contract.foo(x2) for st in m.all_states: - if not m.fix_unsound_symbolication(st): + if not m.is_sound(st): m.kill_state(st) continue From 8c082d94a6cfb6b057a9756a0baf2ff03a4dff2a Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Wed, 7 Apr 2021 17:15:49 -0300 Subject: [PATCH 05/22] fix --- manticore/ethereum/manticore.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index 5fb2746b1..56d26ecc1 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -1421,7 +1421,7 @@ def match(state, func, symbolic_pairs, concrete_pairs, start=None): return state.can_be_true(True) def fix_unsound_lazy(self, state): - return state.can_be_true(True) + return state.can_be_true(True) def is_sound(self, state): soundcheck = state.context.get("soundcheck", None) @@ -1432,7 +1432,7 @@ def is_sound(self, state): state.context["soundcheck"] = self.fix_unsound_lazy(state) if not state.context["soundcheck"]: - return state.context["soundcheck"] # no need to keep checking + return state.context["soundcheck"] # no need to keep checking if consts.sha3 is consts.sha3.symbolicate: state.context["soundcheck"] = self.fix_unsound_symbolication_sound(state) From 8aa776e4622abc1850200b2bdfa3c5bf0383f3ab Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Wed, 7 Apr 2021 17:41:13 -0300 Subject: [PATCH 06/22] lint --- tests/ethereum/test_sha3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ethereum/test_sha3.py b/tests/ethereum/test_sha3.py index dc6e0ea74..b91bf59e8 100644 --- a/tests/ethereum/test_sha3.py +++ b/tests/ethereum/test_sha3.py @@ -58,7 +58,7 @@ def test_example1(self): for st in m.all_states: if not m.is_sound(st): m.kill_state(st) - continue + continue found += len(st.platform.logs) self.assertEqual(found, 0) # log is not reachable From d2dfcc49a5e9fbef74ef5d7c25fdec1376697572 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Wed, 7 Apr 2021 23:03:51 -0300 Subject: [PATCH 07/22] fixes --- manticore/core/state.py | 18 ++++++++++++++---- manticore/ethereum/manticore.py | 17 +++++------------ tests/ethereum/test_general.py | 5 +++-- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/manticore/core/state.py b/manticore/core/state.py index d6ae24608..8c21e5559 100644 --- a/manticore/core/state.py +++ b/manticore/core/state.py @@ -360,7 +360,7 @@ def new_symbolic_value(self, nbits, label=None, taint=frozenset()): self._input_symbols.append(expr) return expr - def concretize(self, symbolic, policy, maxcount=7): + def concretize(self, symbolic, policy, maxcount=7, additional_symbolics=None): """This finds a set of solutions for symbolic using policy. This limits the number of solutions returned to `maxcount` to avoid @@ -412,9 +412,19 @@ def concretize(self, symbolic, policy, maxcount=7): vals = (True,) else: assert policy == "ALL" - vals = self._solver.get_all_values( - self._constraints, symbolic, maxcnt=maxcount, silent=True - ) + if additional_symbolics is not None: + print(symbolic, additional_symbolics) + val_1 = self._solver.get_all_values( + self._constraints, symbolic, maxcnt=maxcount, silent=True + ) + val_2 = self._solver.get_all_values( + self._constraints, additional_symbolics, maxcnt=maxcount, silent=True + ) + return [val_1 + val_2] + else: + vals = self._solver.get_all_values( + self._constraints, symbolic, maxcnt=maxcount, silent=True + ) return tuple(set(vals)) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index e75b05420..ac8e44af1 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -1970,21 +1970,14 @@ def worker_finalize(q): for proc in report_workers: proc.join() - def enable_lazy_evaluation(self): + def set_lazy_evaluation(self, flag): """ - Enable lazy evaluation (only EVM support) + Set lazy evaluation flag (only EVM support) :return: """ - self._lazy_evaluation = True + self._lazy_evaluation = flag - def disable_lazy_evaluation(self): - """ - Disable lazy evaluation (only EVM support) - :return: - """ - self._lazy_evaluation = False - - def lazy_evaluation(self) -> bool: + def get_lazy_evaluation(self) -> bool: return self._lazy_evaluation def _fork(self, state, expression, policy="ALL", setstate=None): @@ -2029,7 +2022,7 @@ def setstate(x, y): solutions = state.concretize( expression, policy, - additional_symbolics=[state.platform.current_vm.need_check_jumpdest()], + additional_symbolics=state.platform.current_vm.need_check_jumpdest(), ) else: print("normal") diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index 72264c741..8391bf33e 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -73,7 +73,7 @@ class EthVerifierIntegrationTest(unittest.TestCase): def test_propverif(self): smtcfg = config.get_group("smt") with smtcfg.temp_vals(): - smtcfg.solver = smtcfg.solver.yices + smtcfg.solver = smtcfg.solver.cvc4 filename = os.path.join(THIS_DIR, "contracts/prop_verifier.sol") f = io.StringIO() @@ -726,6 +726,7 @@ def test_check_jumpdest_symbolic_pc(self): This test checks the fix for this issue. """ + self.mevm.set_lazy_evaluation(False) self.mevm.register_detector(DetectIntegerOverflow()) c = self.mevm.solidity_create_contract( """ @@ -819,7 +820,7 @@ def test_function_name_with_signature(self): self.mevm.make_symbolic_value(), signature="(uint256,uint256)", ) - for st in self.mevm.all_states: + for st in self.mevm.all_sound_states: z = st.solve_one(st.platform.transactions[1].return_data) break self.assertEqual(ABI.deserialize("(uint256)", z)[0], 2) From 830fe62c921418bfad74d09f431e415644108302 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Thu, 8 Apr 2021 14:11:49 -0300 Subject: [PATCH 08/22] fixes --- manticore/core/state.py | 2 +- tests/ethereum/test_general.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/manticore/core/state.py b/manticore/core/state.py index 8c21e5559..7ebaf97bd 100644 --- a/manticore/core/state.py +++ b/manticore/core/state.py @@ -420,7 +420,7 @@ def concretize(self, symbolic, policy, maxcount=7, additional_symbolics=None): val_2 = self._solver.get_all_values( self._constraints, additional_symbolics, maxcnt=maxcount, silent=True ) - return [val_1 + val_2] + return list(zip(val_1, val_2)) else: vals = self._solver.get_all_values( self._constraints, symbolic, maxcnt=maxcount, silent=True diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index 8391bf33e..724699d7f 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -753,6 +753,7 @@ def test_gen_testcase_only_if(self): } } """ + self.mevm.set_lazy_evaluation(False) consts = config.get_group("evm") consts.events = True user_account = self.mevm.create_account(balance=10 ** 10) @@ -1341,7 +1342,7 @@ def test_preconstraints(self): ) m.transaction(caller=creator_account, address=contract_account, data=data, value=value) - results = [state.platform.all_transactions[-1].result for state in m.all_states] + results = [state.platform.all_transactions[-1].result for state in m.all_sound_states] self.assertListEqual(sorted(results), ["STOP", "STOP"]) def test_plugins_enable(self): @@ -1364,6 +1365,7 @@ def will_evm_execute_instruction_callback(self, state, i, *args, **kwargs): aplug = examplePlugin() m: ManticoreEVM = ManticoreEVM() + m.set_lazy_evaluation(False) m.register_plugin(aplug) creator_account = m.create_account(balance=10000000000) From 2a307d71e74134511b6ef285d263001156ee9e27 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Fri, 9 Apr 2021 15:16:22 -0300 Subject: [PATCH 09/22] disable lazy evaluation for verifier --- manticore/ethereum/verifier.py | 1 + 1 file changed, 1 insertion(+) diff --git a/manticore/ethereum/verifier.py b/manticore/ethereum/verifier.py index c4ce7a075..fddaaded0 100644 --- a/manticore/ethereum/verifier.py +++ b/manticore/ethereum/verifier.py @@ -123,6 +123,7 @@ def manticore_verifier( print("# Welcome to manticore-verifier") # Main manticore manager object m = ManticoreEVM() + m.set_lazy_evaluation(False) # avoid all human level tx that are marked as constant (have no effect on the storage) filter_out_human_constants = FilterFunctions( regexp=r".*", depth="human", mutability="constant", include=False From 834da35659f5acf8ed959bb63af42828f19e804e Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Fri, 9 Apr 2021 17:33:31 -0300 Subject: [PATCH 10/22] fixed more tests --- tests/ethereum/test_general.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index 724699d7f..bcd61520c 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -1629,6 +1629,7 @@ def test_overloaded_functions_and_events(self): class EthSpecificTxIntructionTests(unittest.TestCase): + @unittest.skip("reason") def test_jmpdest_check(self): """ This test that jumping to a JUMPDEST in the operand of a PUSH should @@ -1966,6 +1967,7 @@ def test_FilterFunctions_fallback_function_matching(self): regexp=r"^$", fallback=True ) # Only matches the fallback function. m.register_plugin(plugin) + m.set_lazy_evaluation(False) creator_account = m.create_account(balance=10000000000000) contract_account = m.solidity_create_contract( From 2b13cc5df2fc4b9bf42ff9876949a692359f3565 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Fri, 9 Apr 2021 18:36:18 -0300 Subject: [PATCH 11/22] more fixes --- manticore/ethereum/manticore.py | 4 ---- tests/auto_generators/make_VMTests.py | 3 +-- tests/ethereum/test_general.py | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index ac8e44af1..f36659470 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -2018,20 +2018,17 @@ def setstate(x, y): if state.platform.current_vm and isinstance( state.platform.current_vm.need_check_jumpdest(), (Expression, bool) ): - print("checkjumpdst") solutions = state.concretize( expression, policy, additional_symbolics=state.platform.current_vm.need_check_jumpdest(), ) else: - print("normal") solutions = [(s, False) for s in state.concretize(expression, policy)] if not solutions: raise ManticoreError("Forking on unfeasible constraint set") - print(solutions) logger.debug( "Forking. Policy: %s. Values: %s", policy, @@ -2054,7 +2051,6 @@ def setstate(x, y): # However, platform.current_vm is not yet created # So not sure how to do it new_state.platform.set_last_ins_was_true_jumpi(jump_cond) - # print(f'{hex(new_value)} -> {jump_cond}') # enqueue new_state, assign new state id new_state_id = self._put_state(new_state) diff --git a/tests/auto_generators/make_VMTests.py b/tests/auto_generators/make_VMTests.py index b831dc322..bbe86bed3 100644 --- a/tests/auto_generators/make_VMTests.py +++ b/tests/auto_generators/make_VMTests.py @@ -212,8 +212,7 @@ def did_close_transaction_callback(self, state, tx): price={price})""" body += f""" - m.finalize() - for state in m.all_states: + for state in m.all_sound_states: world = state.platform self.assertEqual(used_gas_plugin.used_gas, {blockheader['gasUsed']}) diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index bcd61520c..95bf9bcf4 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -73,7 +73,7 @@ class EthVerifierIntegrationTest(unittest.TestCase): def test_propverif(self): smtcfg = config.get_group("smt") with smtcfg.temp_vals(): - smtcfg.solver = smtcfg.solver.cvc4 + smtcfg.solver = smtcfg.solver.yices filename = os.path.join(THIS_DIR, "contracts/prop_verifier.sol") f = io.StringIO() From df9db1d067724651bc32e3cf5b0c4d91cdfe6e10 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Fri, 9 Apr 2021 19:28:50 -0300 Subject: [PATCH 12/22] fix --- tests/auto_generators/make_VMTests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto_generators/make_VMTests.py b/tests/auto_generators/make_VMTests.py index bbe86bed3..b831dc322 100644 --- a/tests/auto_generators/make_VMTests.py +++ b/tests/auto_generators/make_VMTests.py @@ -212,7 +212,8 @@ def did_close_transaction_callback(self, state, tx): price={price})""" body += f""" - for state in m.all_sound_states: + m.finalize() + for state in m.all_states: world = state.platform self.assertEqual(used_gas_plugin.used_gas, {blockheader['gasUsed']}) From 705c87770fd3a3b3b1e481682cc0f1d4625bd54f Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 4 May 2021 09:40:37 -0300 Subject: [PATCH 13/22] fixes --- manticore/core/state.py | 4 +++- manticore/ethereum/manticore.py | 19 +++++++++++++------ manticore/platforms/evm.py | 2 ++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/manticore/core/state.py b/manticore/core/state.py index 7ebaf97bd..ebcacf32f 100644 --- a/manticore/core/state.py +++ b/manticore/core/state.py @@ -413,7 +413,9 @@ def concretize(self, symbolic, policy, maxcount=7, additional_symbolics=None): else: assert policy == "ALL" if additional_symbolics is not None: - print(symbolic, additional_symbolics) + logger.debug( + "Additinal symbolics", additional_symbolics, "used with expression", symbolic + ) val_1 = self._solver.get_all_values( self._constraints, symbolic, maxcnt=maxcount, silent=True ) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index f36659470..435db13fd 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -1970,12 +1970,19 @@ def worker_finalize(q): for proc in report_workers: proc.join() - def set_lazy_evaluation(self, flag): + def enable_lazy_evaluation(self): """ - Set lazy evaluation flag (only EVM support) + Enable lazy evaluation :return: """ - self._lazy_evaluation = flag + self._lazy_evaluation = True + + def disable_lazy_evaluation(self): + """ + Enable lazy evaluation + :return: + """ + self._lazy_evaluation = False def get_lazy_evaluation(self) -> bool: return self._lazy_evaluation @@ -2006,12 +2013,12 @@ def setstate(x, y): if ( self._lazy_evaluation and state.platform.current_vm - and state.platform.current_vm.jumpi_false_branch() + and state.platform.current_vm.jumpi_false_branch ): solutions = [ - (state.platform.current_vm.jumpi_false_branch(), False), - (state.platform.current_vm.jumpi_true_branch(), True), + (state.platform.current_vm.jumpi_false_branch, False), + (state.platform.current_vm.jumpi_true_branch, True), ] else: diff --git a/manticore/platforms/evm.py b/manticore/platforms/evm.py index aa9059bd6..38027cf29 100644 --- a/manticore/platforms/evm.py +++ b/manticore/platforms/evm.py @@ -871,12 +871,14 @@ def constraints(self, constraints): def gas(self): return Operators.EXTRACT(self._gas, 0, 256) + @property def jumpi_false_branch(self) -> Optional[int]: """ Return the JUMPI false branch. Return None if the last instruction was not a JUMPI """ return self._jumpi_false_branch + @property def jumpi_true_branch(self) -> Optional[int]: """ Return the JUMPI false branch. Return None if the last instruction was not a JUMPI From fe62c970f2723726fc4ea497efdf4cab0c563d9d Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 4 May 2021 09:58:06 -0300 Subject: [PATCH 14/22] fixes --- manticore/ethereum/manticore.py | 2 +- manticore/platforms/evm.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index 435db13fd..d11c23062 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -2057,7 +2057,7 @@ def setstate(x, y): # TODO: Ideally "jump_cond" should be in the VM and not the platform # However, platform.current_vm is not yet created # So not sure how to do it - new_state.platform.set_last_ins_was_true_jumpi(jump_cond) + new_state.platform.last_ins_was_true_jumpi = jump_cond # enqueue new_state, assign new state id new_state_id = self._put_state(new_state) diff --git a/manticore/platforms/evm.py b/manticore/platforms/evm.py index 38027cf29..603b37cad 100644 --- a/manticore/platforms/evm.py +++ b/manticore/platforms/evm.py @@ -1263,11 +1263,11 @@ def _check_jmpdest(self): # If pc is already pointing to a JUMPDEST thre is no need to check. self._need_check_jumpdest = False - if self._world.last_ins_was_true_jumpi(): + if self._world.last_ins_was_true_jumpi: pc = self.pc.value if isinstance(self.pc, Constant) else self.pc if pc not in self._valid_jumpdests: self._throw() - self._world.set_last_ins_was_true_jumpi(False) + self._world.last_ins_was_true_jumpi = False return def _advance(self, result=None, exception=False): @@ -2550,11 +2550,13 @@ def constraints(self, constraints): if self.current_vm: self.current_vm.constraints = constraints + @property def last_ins_was_true_jumpi(self) -> Optional[bool]: return self._last_ins_was_true_jumpi - def set_last_ins_was_true_jumpi(self, jump_cond: Optional[bool]): - self._last_ins_was_true_jumpi = jump_cond + @last_ins_was_true_jumpi.setter + def last_ins_was_true_jumpi(self, value): + self._last_ins_was_true_jumpi = value @property def evmfork(self): From 9cba8ce4dfada509523ff16e339e511d8210d507 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 4 May 2021 12:44:26 -0300 Subject: [PATCH 15/22] more fixes --- tests/ethereum/test_general.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index 95bf9bcf4..ced45df42 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -726,7 +726,7 @@ def test_check_jumpdest_symbolic_pc(self): This test checks the fix for this issue. """ - self.mevm.set_lazy_evaluation(False) + self.mevm.disable_lazy_evaluation() self.mevm.register_detector(DetectIntegerOverflow()) c = self.mevm.solidity_create_contract( """ @@ -753,7 +753,7 @@ def test_gen_testcase_only_if(self): } } """ - self.mevm.set_lazy_evaluation(False) + self.mevm.disable_lazy_evaluation() consts = config.get_group("evm") consts.events = True user_account = self.mevm.create_account(balance=10 ** 10) @@ -1365,7 +1365,7 @@ def will_evm_execute_instruction_callback(self, state, i, *args, **kwargs): aplug = examplePlugin() m: ManticoreEVM = ManticoreEVM() - m.set_lazy_evaluation(False) + m.disable_lazy_evaluation() m.register_plugin(aplug) creator_account = m.create_account(balance=10000000000) @@ -1967,7 +1967,7 @@ def test_FilterFunctions_fallback_function_matching(self): regexp=r"^$", fallback=True ) # Only matches the fallback function. m.register_plugin(plugin) - m.set_lazy_evaluation(False) + m.disable_lazy_evaluation() creator_account = m.create_account(balance=10000000000000) contract_account = m.solidity_create_contract( From f257187260be5a6c0ab83f8a5c19d0f83aeb9fb0 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 4 May 2021 13:26:03 -0300 Subject: [PATCH 16/22] fix --- manticore/ethereum/verifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manticore/ethereum/verifier.py b/manticore/ethereum/verifier.py index fddaaded0..3e9ae88bd 100644 --- a/manticore/ethereum/verifier.py +++ b/manticore/ethereum/verifier.py @@ -123,7 +123,7 @@ def manticore_verifier( print("# Welcome to manticore-verifier") # Main manticore manager object m = ManticoreEVM() - m.set_lazy_evaluation(False) + m.disable_lazy_evaluation() # avoid all human level tx that are marked as constant (have no effect on the storage) filter_out_human_constants = FilterFunctions( regexp=r".*", depth="human", mutability="constant", include=False From 6049aa085db0c844e4d07d15d94d242048cc7fc1 Mon Sep 17 00:00:00 2001 From: Eric Hennenfent Date: Fri, 21 May 2021 10:37:57 -0700 Subject: [PATCH 17/22] Tweak typing --- manticore/core/state.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/manticore/core/state.py b/manticore/core/state.py index ebcacf32f..3fbf85515 100644 --- a/manticore/core/state.py +++ b/manticore/core/state.py @@ -1,7 +1,8 @@ import copy import logging +import typing -from .smtlib import solver, Bool, issymbolic, BitVecConstant +from .smtlib import solver, Bool, issymbolic, BitVecConstant, Expression from ..utils.event import Eventful from ..utils.helpers import PickleSerializer from ..utils import config @@ -360,7 +361,14 @@ def new_symbolic_value(self, nbits, label=None, taint=frozenset()): self._input_symbols.append(expr) return expr - def concretize(self, symbolic, policy, maxcount=7, additional_symbolics=None): + def concretize( + self, + symbolic: Expression, + policy: str, + maxcount: int = 7, + *, + additional_symbolics: typing.Optional[typing.List[Expression]] = None, + ): """This finds a set of solutions for symbolic using policy. This limits the number of solutions returned to `maxcount` to avoid @@ -375,9 +383,9 @@ def concretize(self, symbolic, policy, maxcount=7, additional_symbolics=None): if policy == "MINMAX": vals = self._solver.minmax(self._constraints, symbolic) elif policy == "MAX": - vals = (self._solver.max(self._constraints, symbolic),) + vals = [self._solver.max(self._constraints, symbolic)] elif policy == "MIN": - vals = (self._solver.min(self._constraints, symbolic),) + vals = [self._solver.min(self._constraints, symbolic)] elif policy == "SAMPLED": m, M = self._solver.minmax(self._constraints, symbolic) vals += [m, M] @@ -399,17 +407,17 @@ def concretize(self, symbolic, policy, maxcount=7, additional_symbolics=None): elif policy == "OPTIMISTIC": logger.info("Optimistic case when forking") if self._solver.can_be_true(self._constraints, symbolic): - vals = (True,) + vals = [True] else: # We assume the path constraint was feasible to begin with - vals = (False,) + vals = [False] elif policy == "PESSIMISTIC": logger.info("Pessimistic case when forking") if self._solver.can_be_true(self._constraints, symbolic == False): - vals = (False,) + vals = [False] else: # We assume the path constraint was feasible to begin with - vals = (True,) + vals = [True] else: assert policy == "ALL" if additional_symbolics is not None: From 007649752cbc4584c6a5684cf9b29366ecb17084 Mon Sep 17 00:00:00 2001 From: Eric Hennenfent Date: Wed, 26 May 2021 13:34:56 -0700 Subject: [PATCH 18/22] Disable lazy evaluation by default --- manticore/ethereum/manticore.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index d11c23062..576bfd4ff 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -54,7 +54,7 @@ ) consts.add( "lazymode", - True, + False, # Experimental, so disabled by default for now "Only call the solver when it is absolutely necessary to generate testcases.", ) consts.add( @@ -1984,7 +1984,8 @@ def disable_lazy_evaluation(self): """ self._lazy_evaluation = False - def get_lazy_evaluation(self) -> bool: + @property + def lazy_evaluation(self) -> bool: return self._lazy_evaluation def _fork(self, state, expression, policy="ALL", setstate=None): From d04aea3776ca5108ade9fe0ba80b968ef8d435a6 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 8 Jun 2021 14:32:04 +0200 Subject: [PATCH 19/22] fix --- manticore/ethereum/manticore.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manticore/ethereum/manticore.py b/manticore/ethereum/manticore.py index 22942192f..0941cf975 100644 --- a/manticore/ethereum/manticore.py +++ b/manticore/ethereum/manticore.py @@ -1442,6 +1442,8 @@ def is_sound(self, state): if consts.lazymode: state.context["soundcheck"] = self.fix_unsound_lazy(state) + else: + state.context["soundcheck"] = True if not state.context["soundcheck"]: return state.context["soundcheck"] # no need to keep checking From 181aea847307f8bc6e189cb328b0c44c4c224c07 Mon Sep 17 00:00:00 2001 From: ggrieco-tob Date: Tue, 8 Jun 2021 16:34:32 +0200 Subject: [PATCH 20/22] test fix --- tests/ethereum/test_general.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index ced45df42..4bb8c4bf3 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -946,6 +946,7 @@ def did_evm_execute_instruction_callback(self, state, instruction, arguments, re d.add(instruction.name) mevm = self.mevm + mevm.disable_lazy_evaluation() p = TestDetector() mevm.register_detector(p) From 88950288b9328c545fb49c382b7b9dacc36262c6 Mon Sep 17 00:00:00 2001 From: Eric Hennenfent Date: Wed, 9 Jun 2021 13:08:51 -0700 Subject: [PATCH 21/22] Remove disable_lazy_evaluation calls It's already disabled and we want to look at these tests again if we enable it by default in the future. --- tests/ethereum/test_general.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index 4bb8c4bf3..81c59e213 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -726,7 +726,6 @@ def test_check_jumpdest_symbolic_pc(self): This test checks the fix for this issue. """ - self.mevm.disable_lazy_evaluation() self.mevm.register_detector(DetectIntegerOverflow()) c = self.mevm.solidity_create_contract( """ @@ -753,7 +752,6 @@ def test_gen_testcase_only_if(self): } } """ - self.mevm.disable_lazy_evaluation() consts = config.get_group("evm") consts.events = True user_account = self.mevm.create_account(balance=10 ** 10) @@ -946,7 +944,6 @@ def did_evm_execute_instruction_callback(self, state, instruction, arguments, re d.add(instruction.name) mevm = self.mevm - mevm.disable_lazy_evaluation() p = TestDetector() mevm.register_detector(p) @@ -1366,7 +1363,6 @@ def will_evm_execute_instruction_callback(self, state, i, *args, **kwargs): aplug = examplePlugin() m: ManticoreEVM = ManticoreEVM() - m.disable_lazy_evaluation() m.register_plugin(aplug) creator_account = m.create_account(balance=10000000000) @@ -1968,7 +1964,6 @@ def test_FilterFunctions_fallback_function_matching(self): regexp=r"^$", fallback=True ) # Only matches the fallback function. m.register_plugin(plugin) - m.disable_lazy_evaluation() creator_account = m.create_account(balance=10000000000000) contract_account = m.solidity_create_contract( From 97d95f2a5ce5f567fd4c999e515c01ad062388aa Mon Sep 17 00:00:00 2001 From: Eric Hennenfent Date: Wed, 9 Jun 2021 14:07:54 -0700 Subject: [PATCH 22/22] Re-enable jumpdest check --- tests/ethereum/test_general.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ethereum/test_general.py b/tests/ethereum/test_general.py index 81c59e213..80cdb0024 100644 --- a/tests/ethereum/test_general.py +++ b/tests/ethereum/test_general.py @@ -1626,7 +1626,6 @@ def test_overloaded_functions_and_events(self): class EthSpecificTxIntructionTests(unittest.TestCase): - @unittest.skip("reason") def test_jmpdest_check(self): """ This test that jumping to a JUMPDEST in the operand of a PUSH should