angr 9.2.138__py3-none-manylinux2014_x86_64.whl → 9.2.140__py3-none-manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of angr might be problematic. Click here for more details.

Files changed (100) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/calling_convention/calling_convention.py +48 -21
  3. angr/analyses/calling_convention/fact_collector.py +59 -12
  4. angr/analyses/calling_convention/utils.py +2 -2
  5. angr/analyses/cfg/cfg_base.py +13 -0
  6. angr/analyses/cfg/cfg_fast.py +23 -4
  7. angr/analyses/decompiler/ail_simplifier.py +79 -53
  8. angr/analyses/decompiler/block_simplifier.py +0 -2
  9. angr/analyses/decompiler/callsite_maker.py +80 -14
  10. angr/analyses/decompiler/clinic.py +99 -80
  11. angr/analyses/decompiler/condition_processor.py +2 -2
  12. angr/analyses/decompiler/decompiler.py +19 -7
  13. angr/analyses/decompiler/dephication/rewriting_engine.py +16 -7
  14. angr/analyses/decompiler/expression_narrower.py +1 -1
  15. angr/analyses/decompiler/optimization_passes/__init__.py +3 -0
  16. angr/analyses/decompiler/optimization_passes/condition_constprop.py +149 -0
  17. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
  18. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +12 -3
  19. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +1 -1
  20. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
  21. angr/analyses/decompiler/optimization_passes/optimization_pass.py +21 -12
  22. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +17 -9
  23. angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +7 -10
  24. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +12 -1
  25. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +61 -25
  26. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +50 -1
  27. angr/analyses/decompiler/presets/fast.py +2 -0
  28. angr/analyses/decompiler/presets/full.py +2 -0
  29. angr/analyses/decompiler/region_simplifiers/expr_folding.py +259 -108
  30. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +28 -9
  31. angr/analyses/decompiler/ssailification/rewriting_engine.py +20 -2
  32. angr/analyses/decompiler/ssailification/traversal_engine.py +4 -3
  33. angr/analyses/decompiler/structured_codegen/c.py +10 -3
  34. angr/analyses/decompiler/structuring/dream.py +28 -19
  35. angr/analyses/decompiler/structuring/phoenix.py +253 -89
  36. angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
  37. angr/analyses/decompiler/structuring/structurer_base.py +121 -46
  38. angr/analyses/decompiler/structuring/structurer_nodes.py +6 -1
  39. angr/analyses/decompiler/utils.py +60 -1
  40. angr/analyses/deobfuscator/api_obf_finder.py +13 -5
  41. angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
  42. angr/analyses/deobfuscator/string_obf_finder.py +105 -18
  43. angr/analyses/forward_analysis/forward_analysis.py +1 -1
  44. angr/analyses/propagator/top_checker_mixin.py +6 -6
  45. angr/analyses/reaching_definitions/__init__.py +2 -1
  46. angr/analyses/reaching_definitions/dep_graph.py +1 -12
  47. angr/analyses/reaching_definitions/engine_vex.py +36 -31
  48. angr/analyses/reaching_definitions/function_handler.py +15 -2
  49. angr/analyses/reaching_definitions/rd_state.py +1 -37
  50. angr/analyses/reaching_definitions/reaching_definitions.py +13 -24
  51. angr/analyses/s_propagator.py +129 -87
  52. angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
  53. angr/analyses/s_reaching_definitions/s_rda_view.py +2 -2
  54. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -1
  55. angr/analyses/stack_pointer_tracker.py +36 -22
  56. angr/analyses/typehoon/simple_solver.py +45 -7
  57. angr/analyses/typehoon/typeconsts.py +18 -5
  58. angr/analyses/variable_recovery/engine_ail.py +1 -1
  59. angr/analyses/variable_recovery/engine_base.py +62 -67
  60. angr/analyses/variable_recovery/engine_vex.py +1 -1
  61. angr/analyses/variable_recovery/irsb_scanner.py +2 -2
  62. angr/block.py +69 -107
  63. angr/callable.py +14 -7
  64. angr/calling_conventions.py +81 -10
  65. angr/distributed/__init__.py +1 -1
  66. angr/engines/__init__.py +7 -8
  67. angr/engines/engine.py +3 -138
  68. angr/engines/failure.py +2 -2
  69. angr/engines/hook.py +2 -2
  70. angr/engines/light/engine.py +5 -10
  71. angr/engines/pcode/emulate.py +2 -2
  72. angr/engines/pcode/engine.py +2 -14
  73. angr/engines/pcode/lifter.py +2 -2
  74. angr/engines/procedure.py +2 -2
  75. angr/engines/soot/engine.py +2 -2
  76. angr/engines/soot/statements/switch.py +1 -1
  77. angr/engines/successors.py +123 -17
  78. angr/engines/syscall.py +2 -2
  79. angr/engines/unicorn.py +3 -3
  80. angr/engines/vex/heavy/heavy.py +3 -15
  81. angr/engines/vex/lifter.py +2 -2
  82. angr/engines/vex/light/light.py +2 -2
  83. angr/factory.py +4 -19
  84. angr/knowledge_plugins/cfg/cfg_model.py +3 -2
  85. angr/knowledge_plugins/key_definitions/atoms.py +8 -4
  86. angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
  87. angr/knowledge_plugins/labels.py +2 -2
  88. angr/knowledge_plugins/obfuscations.py +1 -0
  89. angr/knowledge_plugins/xrefs/xref_manager.py +4 -0
  90. angr/sim_type.py +19 -17
  91. angr/state_plugins/plugin.py +19 -4
  92. angr/storage/memory_mixins/memory_mixin.py +1 -1
  93. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +10 -5
  94. angr/utils/ssa/__init__.py +119 -4
  95. {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/METADATA +6 -6
  96. {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/RECORD +100 -98
  97. {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/LICENSE +0 -0
  98. {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/WHEEL +0 -0
  99. {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/entry_points.txt +0 -0
  100. {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/top_level.txt +0 -0
angr/engines/failure.py CHANGED
@@ -3,13 +3,13 @@ from __future__ import annotations
3
3
  import logging
4
4
 
5
5
  from angr.errors import AngrExitError
6
- from .engine import SuccessorsMixin
6
+ from .successors import SuccessorsEngine
7
7
  from .procedure import ProcedureMixin
8
8
 
9
9
  l = logging.getLogger(name=__name__)
10
10
 
11
11
 
12
- class SimEngineFailure(SuccessorsMixin, ProcedureMixin):
12
+ class SimEngineFailure(SuccessorsEngine, ProcedureMixin):
13
13
  def process_successors(self, successors, **kwargs):
14
14
  state = self.state
15
15
  jumpkind = state.history.parent.jumpkind if state.history and state.history.parent else None
angr/engines/hook.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
  import logging
3
3
 
4
- from .engine import SuccessorsMixin
4
+ from .successors import SuccessorsEngine
5
5
  from .procedure import ProcedureMixin
6
6
  from archinfo.arch_soot import SootAddressDescriptor
7
7
 
@@ -9,7 +9,7 @@ l = logging.getLogger(name=__name__)
9
9
 
10
10
 
11
11
  # pylint: disable=abstract-method,unused-argument,arguments-differ
12
- class HooksMixin(SuccessorsMixin, ProcedureMixin):
12
+ class HooksMixin(SuccessorsEngine, ProcedureMixin):
13
13
  """
14
14
  A SimEngine mixin which adds a SimSuccessors handler which will look into the project's hooks and run the hook at
15
15
  the current address.
@@ -64,13 +64,8 @@ class SimEngineLight(Generic[StateType, DataType_co, BlockType, ResultType], Sim
64
64
  self.l = logger or logging.getLogger(self.__module__ + "." + self.__class__.__name__)
65
65
  super().__init__(project)
66
66
 
67
- # there's two of these to support the mixin pattern - mixins can override process while there must be some base
68
- # class that provides _process
69
- def process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType:
70
- return self._process(state, block=block, **kwargs)
71
-
72
67
  @abstractmethod
73
- def _process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType: ...
68
+ def process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType: ...
74
69
 
75
70
  def lift(self, state: StateType) -> BlockType:
76
71
  raise TypeError(f"{type(self)} requires `block` to be passed to `process`")
@@ -164,7 +159,7 @@ class SimEngineLightVEX(
164
159
 
165
160
  @staticmethod
166
161
  def binopv_handler(
167
- f: Callable[[T, int, int, pyvex.expr.Binop], DataType_co]
162
+ f: Callable[[T, int, int, pyvex.expr.Binop], DataType_co],
168
163
  ) -> Callable[[T, int, int, pyvex.expr.Binop], DataType_co]:
169
164
  f.binopv_handler = True
170
165
  return f
@@ -186,7 +181,7 @@ class SimEngineLightVEX(
186
181
 
187
182
  @staticmethod
188
183
  def dirty_handler(
189
- f: Callable[[T, pyvex.stmt.Dirty], StmtDataType]
184
+ f: Callable[[T, pyvex.stmt.Dirty], StmtDataType],
190
185
  ) -> Callable[[T, pyvex.stmt.Dirty], StmtDataType]:
191
186
  f.dirty_handler = True
192
187
  return f
@@ -267,7 +262,7 @@ class SimEngineLightVEX(
267
262
  if name.startswith("_handle_dirty_")
268
263
  }
269
264
 
270
- def _process(
265
+ def process(
271
266
  self, state: StateType, *, block: Block | None = None, whitelist: set[int] | None = None, **kwargs
272
267
  ) -> ResultType:
273
268
  # initialize local variables
@@ -640,7 +635,7 @@ class SimEngineLightAIL(
640
635
  }
641
636
  super().__init__(*args, **kwargs)
642
637
 
643
- def _process(
638
+ def process(
644
639
  self, state: StateType, *, block: ailment.Block | None = None, whitelist: set[int] | None = None, **kwargs
645
640
  ) -> ResultType:
646
641
  self.tmps = {}
@@ -4,7 +4,7 @@ import logging
4
4
  import claripy
5
5
  from claripy.ast.bv import BV
6
6
 
7
- from angr.engines.engine import SimEngineBase
7
+ from angr.engines.engine import SimEngine
8
8
  from angr.utils.constants import DEFAULT_STATEMENT
9
9
  from .lifter import IRSB
10
10
  from .behavior import OpBehavior
@@ -19,7 +19,7 @@ with contextlib.suppress(ImportError):
19
19
  l = logging.getLogger(__name__)
20
20
 
21
21
 
22
- class PcodeEmulatorMixin(SimEngineBase):
22
+ class PcodeEmulatorMixin(SimEngine):
23
23
  """
24
24
  Mixin for p-code execution.
25
25
  """
@@ -5,7 +5,7 @@ import claripy
5
5
  import logging
6
6
 
7
7
  from angr.calling_conventions import DEFAULT_CC, default_cc, SimRegArg
8
- from angr.engines.engine import SuccessorsMixin, SimSuccessors
8
+ from angr.engines.successors import SuccessorsEngine, SimSuccessors
9
9
  from angr.misc.ux import once
10
10
  from angr.utils.constants import DEFAULT_STATEMENT
11
11
  from angr import sim_options as o
@@ -19,7 +19,7 @@ l = logging.getLogger(__name__)
19
19
 
20
20
 
21
21
  class HeavyPcodeMixin(
22
- SuccessorsMixin,
22
+ SuccessorsEngine,
23
23
  PcodeLifterEngineMixin,
24
24
  PcodeEmulatorMixin,
25
25
  ):
@@ -52,7 +52,6 @@ class HeavyPcodeMixin(
52
52
  self,
53
53
  successors: SimSuccessors,
54
54
  irsb: IRSB | None = None,
55
- insn_text: str | None = None,
56
55
  insn_bytes: bytes | None = None,
57
56
  thumb: bool = False,
58
57
  size: int | None = None,
@@ -67,21 +66,10 @@ class HeavyPcodeMixin(
67
66
  extra_stop_points=extra_stop_points,
68
67
  num_inst=num_inst,
69
68
  size=size,
70
- insn_text=insn_text,
71
69
  insn_bytes=insn_bytes,
72
70
  **kwargs,
73
71
  )
74
72
 
75
- if insn_text is not None:
76
- if insn_bytes is not None:
77
- raise errors.SimEngineError("You cannot provide both 'insn_bytes' and 'insn_text'!")
78
-
79
- insn_bytes = self.project.arch.asm(insn_text, addr=successors.addr, thumb=thumb)
80
- if insn_bytes is None:
81
- raise errors.AngrAssemblyError(
82
- "Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
83
- )
84
-
85
73
  successors.sort = "IRSB"
86
74
  successors.description = "IRSB"
87
75
  self.state.history.recent_block_count = 1
@@ -20,7 +20,7 @@ from cachetools import LRUCache
20
20
  from pyvex.errors import PyVEXError, SkipStatementsError, LiftingException
21
21
 
22
22
  from .behavior import BehaviorFactory
23
- from angr.engines.engine import SimEngineBase
23
+ from angr.engines.engine import SimEngine
24
24
  from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
25
25
  from angr.sim_state import SimState
26
26
  from angr.misc.ux import once
@@ -981,7 +981,7 @@ class PcodeLifter(Lifter):
981
981
  raise LiftingException(f"pypcode: could not decode any instructions @ 0x{self.addr:x}")
982
982
 
983
983
 
984
- class PcodeLifterEngineMixin(SimEngineBase):
984
+ class PcodeLifterEngineMixin(SimEngine):
985
985
  """
986
986
  Lifter mixin to lift from machine code to P-Code.
987
987
  """
angr/engines/procedure.py CHANGED
@@ -4,7 +4,7 @@ import logging
4
4
  from angr import sim_options as o
5
5
  from angr import errors
6
6
  from angr.state_plugins.inspect import BP_BEFORE, BP_AFTER
7
- from .engine import SuccessorsMixin
7
+ from .successors import SuccessorsEngine
8
8
 
9
9
 
10
10
  l = logging.getLogger(name=__name__)
@@ -58,7 +58,7 @@ class ProcedureMixin:
58
58
  successors.processed = True
59
59
 
60
60
 
61
- class ProcedureEngine(ProcedureMixin, SuccessorsMixin):
61
+ class ProcedureEngine(ProcedureMixin, SuccessorsEngine):
62
62
  """
63
63
  A SimEngine that you may use if you only care about processing SimProcedures. *Requires* the procedure
64
64
  kwarg to be passed to process.
@@ -15,7 +15,7 @@ from angr.errors import SimEngineError, SimTranslationError
15
15
  from cle import CLEError
16
16
  from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
17
17
  from angr.sim_type import SimTypeFunction, parse_type
18
- from angr.engines.engine import SuccessorsMixin
18
+ from angr.engines.successors import SuccessorsEngine
19
19
  from angr.engines.procedure import ProcedureMixin
20
20
  from .exceptions import BlockTerminationNotice, IncorrectLocationException
21
21
  from .statements import SimSootStmt_Return, SimSootStmt_ReturnVoid, translate_stmt
@@ -26,7 +26,7 @@ l = logging.getLogger("angr.engines.soot.engine")
26
26
  # pylint: disable=arguments-differ
27
27
 
28
28
 
29
- class SootMixin(SuccessorsMixin, ProcedureMixin):
29
+ class SootMixin(SuccessorsEngine, ProcedureMixin):
30
30
  """
31
31
  Execution engine based on Soot.
32
32
  """
@@ -25,7 +25,7 @@ class SwitchBase(SimSootStmt):
25
25
  jmp_condition = lookup_value == key_val
26
26
  self._add_jmp_target(jmp_target, jmp_condition)
27
27
  # add condition for the default target
28
- default_jmp_conditions += [(lookup_value != key_val)]
28
+ default_jmp_conditions += [lookup_value != key_val]
29
29
 
30
30
  # add default target
31
31
  default_jmp_target = self._get_bb_addr_from_instr(self.stmt.default_target)
@@ -1,22 +1,27 @@
1
1
  from __future__ import annotations
2
- from typing import TYPE_CHECKING
2
+
3
3
  import logging
4
4
 
5
5
  import claripy
6
-
7
6
  from archinfo.arch_soot import ArchSoot, SootAddressDescriptor
8
7
 
8
+ import angr
9
9
  from angr import sim_options as o
10
- from angr.errors import SimSolverModeError, AngrUnsupportedSyscallError, AngrSyscallError, SimValueError, SimUnsatError
11
- from angr.storage import DUMMY_SYMBOLIC_READ_VALUE
12
- from angr.state_plugins.inspect import BP_BEFORE, BP_AFTER
10
+ from angr.calling_conventions import SYSCALL_CC
11
+ from angr.engines.engine import SimEngine
12
+ from angr.errors import (
13
+ AngrSyscallError,
14
+ AngrUnsupportedSyscallError,
15
+ SimException,
16
+ SimSolverModeError,
17
+ SimUnsatError,
18
+ SimValueError,
19
+ )
20
+ from angr.sim_state import SimState
13
21
  from angr.state_plugins.callstack import CallStack
22
+ from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
14
23
  from angr.state_plugins.sim_action_object import _raw_ast
15
-
16
-
17
- if TYPE_CHECKING:
18
- from angr import SimState
19
- from angr.engines.engine import HeavyState
24
+ from angr.storage import DUMMY_SYMBOLIC_READ_VALUE
20
25
 
21
26
 
22
27
  l = logging.getLogger(name=__name__)
@@ -66,10 +71,6 @@ class SimSuccessors:
66
71
  self.sort: str | None = None
67
72
  self.artifacts = {}
68
73
 
69
- @classmethod
70
- def failure(cls):
71
- return cls(None, None)
72
-
73
74
  def __repr__(self):
74
75
  if self.processed:
75
76
  successor_strings = []
@@ -303,7 +304,7 @@ class SimSuccessors:
303
304
  else:
304
305
  # The architecture doesn't have an ip_at_syscall register.
305
306
  # Nothing to do but hope vigorously.
306
- l.warning(f"Handling syscall on arch {state.arch.name:s} without ip_at_syscall register")
307
+ l.warning("Handling syscall on arch %s without ip_at_syscall register", state.arch.name)
307
308
 
308
309
  try:
309
310
  symbolic_syscall_num, concrete_syscall_nums = self._resolve_syscall(state)
@@ -544,5 +545,110 @@ class SimSuccessors:
544
545
  return [(ip == addr, addr) for addr in addrs]
545
546
 
546
547
 
547
- # pylint: disable=wrong-import-position
548
- from angr.calling_conventions import SYSCALL_CC
548
+ HeavyState = SimState[int | SootAddressDescriptor, claripy.ast.BV | SootAddressDescriptor]
549
+
550
+
551
+ class SuccessorsEngine(SimEngine[HeavyState, SimSuccessors]):
552
+ """
553
+ A mixin for SimEngine which implements ``process`` to perform common operations related to symbolic execution
554
+ and dispatches to a ``process_successors`` method to fill a SimSuccessors object with the results.
555
+ """
556
+
557
+ def __init__(self, project: angr.Project):
558
+ super().__init__(project)
559
+
560
+ self.successors: SimSuccessors | None = None
561
+
562
+ def process(self, state: HeavyState, **kwargs) -> SimSuccessors: # pylint:disable=unused-argument
563
+ """
564
+ Perform execution with a state.
565
+
566
+ You should only override this method in a subclass in order to provide the correct method signature and
567
+ docstring. You should override the ``_process`` method to do your actual execution.
568
+
569
+ :param state: The state with which to execute. This state will be copied before
570
+ modification.
571
+ :param inline: This is an inline execution. Do not bother copying the state.
572
+ :param force_addr: Force execution to pretend that we're working at this concrete address
573
+ :returns: A SimSuccessors object categorizing the execution's successor states
574
+ """
575
+ inline = kwargs.pop("inline", False)
576
+ force_addr = kwargs.pop("force_addr", None)
577
+
578
+ ip = state._ip
579
+ addr = (
580
+ (ip if isinstance(ip, SootAddressDescriptor) else state.solver.eval(ip))
581
+ if force_addr is None
582
+ else force_addr
583
+ )
584
+
585
+ # make a copy of the initial state for actual processing, if needed
586
+ new_state = state.copy() if not inline and o.COPY_STATES in state.options else state
587
+ # enforce this distinction
588
+ old_state = state
589
+ del state
590
+ self.state = new_state
591
+
592
+ # we have now officially begun the stepping process! now is where we "cycle" a state's
593
+ # data - move the "present" into the "past" by pushing an entry on the history stack.
594
+ # nuance: make sure to copy from the PREVIOUS state to the CURRENT one
595
+ # to avoid creating a dead link in the history, messing up the statehierarchy
596
+ new_state.register_plugin("history", old_state.history.make_child())
597
+ new_state.history.recent_bbl_addrs.append(addr)
598
+ if new_state.arch.unicorn_support:
599
+ assert isinstance(addr, int)
600
+ new_state.scratch.executed_pages_set = {addr & ~0xFFF}
601
+
602
+ self.successors = SimSuccessors(addr, old_state)
603
+
604
+ new_state._inspect(
605
+ "engine_process", when=BP_BEFORE, sim_engine=self, sim_successors=self.successors, address=addr
606
+ )
607
+ self.successors = new_state._inspect_getattr("sim_successors", self.successors)
608
+ try:
609
+ self.process_successors(self.successors, **kwargs)
610
+ except SimException as e:
611
+ if o.EXCEPTION_HANDLING not in old_state.options:
612
+ raise
613
+ assert old_state.project is not None
614
+ old_state.project.simos.handle_exception(self.successors, self, e)
615
+
616
+ new_state._inspect("engine_process", when=BP_AFTER, sim_successors=self.successors, address=addr)
617
+ self.successors = new_state._inspect_getattr("sim_successors", self.successors)
618
+ assert self.successors is not None
619
+
620
+ # downsizing
621
+ if new_state.supports_inspect:
622
+ new_state.inspect.downsize()
623
+ # if not TRACK, clear actions on OLD state
624
+ # if o.TRACK_ACTION_HISTORY not in old_state.options:
625
+ # old_state.history.recent_events = []
626
+
627
+ # fix up the descriptions...
628
+ description = str(self.successors)
629
+ l.info("Ticked state: %s", description)
630
+ for succ in self.successors.all_successors:
631
+ succ.history.recent_description = description
632
+ for succ in self.successors.flat_successors:
633
+ succ.history.recent_description = description
634
+
635
+ return self.successors
636
+
637
+ def process_successors(self, successors, **kwargs): # pylint:disable=unused-argument,no-self-use
638
+ """
639
+ Implement this function to fill out the SimSuccessors object with the results of stepping state.
640
+
641
+ In order to implement a model where multiple mixins can potentially handle a request, a mixin may implement
642
+ this method and then perform a super() call if it wants to pass on handling to the next mixin.
643
+
644
+ Keep in mind python's method resolution order when composing multiple classes implementing this method.
645
+ In short: left-to-right, depth-first, but deferring any base classes which are shared by multiple subclasses
646
+ (the merge point of a diamond pattern in the inheritance graph) until the last point where they would be
647
+ encountered in this depth-first search. For example, if you have classes A, B(A), C(B), D(A), E(C, D), then the
648
+ method resolution order will be E, C, B, D, A.
649
+
650
+ :param state: The state to manipulate
651
+ :param successors: The successors object to fill out
652
+ :param kwargs: Any extra arguments. Do not fail if you are passed unexpected arguments.
653
+ """
654
+ successors.processed = False # mark failure
angr/engines/syscall.py CHANGED
@@ -3,14 +3,14 @@ import logging
3
3
 
4
4
  import angr
5
5
  from angr.errors import AngrUnsupportedSyscallError
6
- from .engine import SuccessorsMixin
6
+ from .successors import SuccessorsEngine
7
7
  from .procedure import ProcedureMixin
8
8
 
9
9
  l = logging.getLogger(name=__name__)
10
10
 
11
11
 
12
12
  # pylint:disable=abstract-method,arguments-differ
13
- class SimEngineSyscall(SuccessorsMixin, ProcedureMixin):
13
+ class SimEngineSyscall(SuccessorsEngine, ProcedureMixin):
14
14
  """
15
15
  A SimEngine mixin which adds a successors handling step that checks if a syscall was just requested and if so
16
16
  handles it as a step.
angr/engines/unicorn.py CHANGED
@@ -8,7 +8,7 @@ import claripy
8
8
 
9
9
  import angr
10
10
  from angr.errors import SimIRSBError, SimIRSBNoDecodeError, SimValueError
11
- from .engine import SuccessorsMixin
11
+ from .successors import SuccessorsEngine
12
12
  from .vex.heavy.heavy import VEXEarlyExit
13
13
  from angr import sim_options as o
14
14
  from angr.misc.ux import once
@@ -21,7 +21,7 @@ from angr.utils.constants import DEFAULT_STATEMENT
21
21
  l = logging.getLogger(name=__name__)
22
22
 
23
23
 
24
- class SimEngineUnicorn(SuccessorsMixin):
24
+ class SimEngineUnicorn(SuccessorsEngine):
25
25
  """
26
26
  Concrete execution in the Unicorn Engine, a fork of qemu.
27
27
 
@@ -281,7 +281,7 @@ class SimEngineUnicorn(SuccessorsMixin):
281
281
  def _get_vex_block_details(self, block_addr, block_size):
282
282
  # Mostly based on the lifting code in HeavyVEXMixin
283
283
  # pylint:disable=no-member
284
- irsb = super().lift_vex(addr=block_addr, state=self.state, size=block_size)
284
+ irsb = self.project.factory.block(addr=block_addr, backup_state=self.state, size=block_size).vex
285
285
  if irsb.size == 0:
286
286
  if irsb.jumpkind == "Ijk_NoDecode":
287
287
  if not self.state.project.is_hooked(irsb.addr):
@@ -3,7 +3,7 @@ import logging
3
3
  import claripy
4
4
  import pyvex
5
5
 
6
- from angr.engines.engine import SuccessorsMixin
6
+ from angr.engines.successors import SuccessorsEngine
7
7
  from angr.engines.vex.light import VEXMixin
8
8
  from angr.engines.vex.lifter import VEXLifter
9
9
  from angr.engines.vex.claripy.datalayer import ClaripyDataMixin, symbol
@@ -57,7 +57,7 @@ class SimStateStorageMixin(VEXMixin):
57
57
 
58
58
 
59
59
  # pylint:disable=arguments-differ
60
- class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEXMixin, VEXLifter):
60
+ class HeavyVEXMixin(SuccessorsEngine, ClaripyDataMixin, SimStateStorageMixin, VEXMixin, VEXLifter):
61
61
  """
62
62
  Execution engine based on VEX, Valgrind's IR.
63
63
 
@@ -83,7 +83,6 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
83
83
  self,
84
84
  successors,
85
85
  irsb=None,
86
- insn_text=None,
87
86
  insn_bytes=None,
88
87
  thumb=False,
89
88
  size=None,
@@ -99,21 +98,10 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
99
98
  extra_stop_points=extra_stop_points,
100
99
  num_inst=num_inst,
101
100
  size=size,
102
- insn_text=insn_text,
103
101
  insn_bytes=insn_bytes,
104
102
  **kwargs,
105
103
  )
106
104
 
107
- if insn_text is not None:
108
- if insn_bytes is not None:
109
- raise errors.SimEngineError("You cannot provide both 'insn_bytes' and 'insn_text'!")
110
-
111
- insn_bytes = self.project.arch.asm(insn_text, addr=successors.addr, thumb=thumb)
112
- if insn_bytes is None:
113
- raise errors.AngrAssemblyError(
114
- "Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
115
- )
116
-
117
105
  successors.sort = "IRSB"
118
106
  successors.description = "IRSB"
119
107
  self.state.history.recent_block_count = 1
@@ -137,9 +125,9 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
137
125
 
138
126
  if irsb is None:
139
127
  irsb = self.lift_vex(
128
+ insn_bytes=insn_bytes,
140
129
  addr=addr,
141
130
  state=self.state,
142
- insn_bytes=insn_bytes,
143
131
  thumb=thumb,
144
132
  size=size,
145
133
  num_inst=num_inst,
@@ -8,7 +8,7 @@ import cle
8
8
  from archinfo import ArchARM
9
9
  import claripy
10
10
 
11
- from angr.engines.engine import SimEngineBase
11
+ from angr.engines.engine import SimEngine
12
12
  from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE, NO_OVERRIDE
13
13
  from angr.misc.ux import once
14
14
  from angr.errors import SimEngineError, SimTranslationError, SimError
@@ -20,7 +20,7 @@ VEX_IRSB_MAX_SIZE = 400
20
20
  VEX_IRSB_MAX_INST = 99
21
21
 
22
22
 
23
- class VEXLifter(SimEngineBase):
23
+ class VEXLifter(SimEngine):
24
24
  """
25
25
  Implements the VEX lifter engine mixin.
26
26
  """
@@ -3,7 +3,7 @@ import logging
3
3
 
4
4
  import pyvex
5
5
 
6
- from angr.engines.engine import SimEngineBase
6
+ from angr.engines.engine import SimEngine
7
7
  from angr.utils.constants import DEFAULT_STATEMENT
8
8
 
9
9
  l = logging.getLogger(name=__name__)
@@ -11,7 +11,7 @@ l = logging.getLogger(name=__name__)
11
11
  # pylint:disable=arguments-differ,unused-argument,no-self-use
12
12
 
13
13
 
14
- class VEXMixin(SimEngineBase):
14
+ class VEXMixin(SimEngine):
15
15
  def __init__(self, project, **kwargs):
16
16
  super().__init__(project, **kwargs)
17
17
  self._vex_expr_handlers = []
angr/factory.py CHANGED
@@ -10,7 +10,7 @@ from archinfo.arch_soot import ArchSoot, SootAddressDescriptor
10
10
  from .sim_state import SimState
11
11
  from .calling_conventions import default_cc, SimRegArg, SimStackArg, PointerWrapper, SimCCUnknown
12
12
  from .callable import Callable
13
- from .errors import AngrAssemblyError, AngrError
13
+ from .errors import AngrError
14
14
  from .engines import UberEngine, ProcedureEngine
15
15
  from .sim_type import SimTypeFunction, SimTypeInt
16
16
  from .codenode import HookNode, SyscallNode
@@ -245,6 +245,7 @@ class AngrObjectFactory:
245
245
  cc=None,
246
246
  add_options=None,
247
247
  remove_options=None,
248
+ step_limit: int | None = None,
248
249
  ):
249
250
  """
250
251
  A Callable is a representation of a function in the binary that can be interacted with like a native python
@@ -257,6 +258,7 @@ class AngrObjectFactory:
257
258
  :param base_state: The state from which to do these runs
258
259
  :param toc: The address of the table of contents for ppc64
259
260
  :param cc: The SimCC to use for a calling convention
261
+ :param step_limit: The maximum number of blocks that Callable will execute before pruning the path.
260
262
  :returns: A Callable object that can be used as a interface for executing guest code like a
261
263
  python function.
262
264
  :rtype: angr.callable.Callable
@@ -272,6 +274,7 @@ class AngrObjectFactory:
272
274
  cc=cc,
273
275
  add_options=add_options,
274
276
  remove_options=remove_options,
277
+ step_limit=step_limit,
275
278
  )
276
279
 
277
280
  def cc(self):
@@ -300,7 +303,6 @@ class AngrObjectFactory:
300
303
  size=None,
301
304
  max_size=None,
302
305
  byte_string=None,
303
- vex=None,
304
306
  thumb=False,
305
307
  backup_state=None,
306
308
  extra_stop_points=None,
@@ -308,7 +310,6 @@ class AngrObjectFactory:
308
310
  num_inst=None,
309
311
  traceflags=0,
310
312
  insn_bytes=None,
311
- insn_text=None, # backward compatibility
312
313
  strict_block_end=None,
313
314
  collect_data_refs=False,
314
315
  cross_insn_opt=True,
@@ -326,7 +327,6 @@ class AngrObjectFactory:
326
327
  size=None,
327
328
  max_size=None,
328
329
  byte_string=None,
329
- vex=None,
330
330
  thumb=False,
331
331
  backup_state=None,
332
332
  extra_stop_points=None,
@@ -334,7 +334,6 @@ class AngrObjectFactory:
334
334
  num_inst=None,
335
335
  traceflags=0,
336
336
  insn_bytes=None,
337
- insn_text=None, # backward compatibility
338
337
  strict_block_end=None,
339
338
  collect_data_refs=False,
340
339
  load_from_ro_regions=False,
@@ -349,7 +348,6 @@ class AngrObjectFactory:
349
348
  size=None,
350
349
  max_size=None,
351
350
  byte_string=None,
352
- vex=None,
353
351
  thumb=False,
354
352
  backup_state=None,
355
353
  extra_stop_points=None,
@@ -357,7 +355,6 @@ class AngrObjectFactory:
357
355
  num_inst=None,
358
356
  traceflags=0,
359
357
  insn_bytes=None,
360
- insn_text=None, # backward compatibility
361
358
  strict_block_end=None,
362
359
  collect_data_refs=False,
363
360
  cross_insn_opt=True,
@@ -369,27 +366,15 @@ class AngrObjectFactory:
369
366
  if isinstance(self.project.arch, ArchSoot) and isinstance(addr, SootAddressDescriptor):
370
367
  return SootBlock(addr, arch=self.project.arch, project=self.project)
371
368
 
372
- if insn_bytes is not None and insn_text is not None:
373
- raise AngrError("You cannot provide both 'insn_bytes' and 'insn_text'!")
374
-
375
369
  if insn_bytes is not None:
376
370
  byte_string = insn_bytes
377
371
 
378
- if insn_text is not None:
379
- byte_string = self.project.arch.asm(insn_text, addr=addr, as_bytes=True, thumb=thumb)
380
- if byte_string is None:
381
- # assembly failed
382
- raise AngrAssemblyError(
383
- "Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
384
- )
385
-
386
372
  return Block(
387
373
  addr,
388
374
  project=self.project,
389
375
  size=size,
390
376
  max_size=max_size,
391
377
  byte_string=byte_string,
392
- vex=vex,
393
378
  extra_stop_points=extra_stop_points,
394
379
  thumb=thumb,
395
380
  backup_state=backup_state,
@@ -631,8 +631,9 @@ class CFGModel(Serializable):
631
631
 
632
632
  if boundary is not None:
633
633
  data.max_size = boundary - data_addr
634
-
635
- assert data.max_size is not None
634
+ else:
635
+ # boundary does not exist, which means the data address is not mapped at all
636
+ data.max_size = 0
636
637
 
637
638
  keys = sorted(self.memory_data.keys())
638
639