angr 9.2.130__py3-none-macosx_11_0_arm64.whl → 9.2.132__py3-none-macosx_11_0_arm64.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 (128) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/analysis.py +6 -2
  3. angr/analyses/cfg/cfg_emulated.py +5 -5
  4. angr/analyses/cfg/cfg_fast.py +2 -2
  5. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +139 -94
  6. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
  7. angr/analyses/ddg.py +14 -11
  8. angr/analyses/decompiler/ail_simplifier.py +3 -2
  9. angr/analyses/decompiler/block_simplifier.py +10 -21
  10. angr/analyses/decompiler/clinic.py +361 -8
  11. angr/analyses/decompiler/condition_processor.py +12 -10
  12. angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
  13. angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
  14. angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
  15. angr/analyses/decompiler/optimization_passes/__init__.py +0 -3
  16. angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
  17. angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
  18. angr/analyses/decompiler/optimization_passes/engine_base.py +261 -83
  19. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +173 -35
  20. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +5 -2
  21. angr/analyses/decompiler/optimization_passes/optimization_pass.py +39 -19
  22. angr/analyses/decompiler/peephole_optimizations/__init__.py +5 -1
  23. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
  24. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +3 -1
  25. angr/analyses/decompiler/peephole_optimizations/bswap.py +10 -6
  26. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +100 -19
  27. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +17 -0
  28. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +42 -3
  29. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +4 -2
  30. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +37 -10
  31. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
  32. angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
  33. angr/analyses/decompiler/presets/fast.py +0 -2
  34. angr/analyses/decompiler/presets/full.py +0 -2
  35. angr/analyses/decompiler/ssailification/rewriting.py +1 -2
  36. angr/analyses/decompiler/ssailification/rewriting_engine.py +140 -57
  37. angr/analyses/decompiler/ssailification/ssailification.py +2 -1
  38. angr/analyses/decompiler/ssailification/traversal.py +4 -6
  39. angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
  40. angr/analyses/decompiler/structured_codegen/c.py +79 -16
  41. angr/analyses/decompiler/structuring/phoenix.py +40 -14
  42. angr/analyses/decompiler/structuring/structurer_nodes.py +9 -0
  43. angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
  44. angr/analyses/deobfuscator/string_obf_finder.py +2 -2
  45. angr/analyses/init_finder.py +47 -22
  46. angr/analyses/propagator/engine_base.py +21 -14
  47. angr/analyses/propagator/engine_vex.py +149 -179
  48. angr/analyses/propagator/propagator.py +10 -28
  49. angr/analyses/propagator/top_checker_mixin.py +211 -5
  50. angr/analyses/propagator/vex_vars.py +1 -1
  51. angr/analyses/reaching_definitions/dep_graph.py +1 -1
  52. angr/analyses/reaching_definitions/engine_ail.py +304 -329
  53. angr/analyses/reaching_definitions/engine_vex.py +243 -229
  54. angr/analyses/reaching_definitions/function_handler.py +3 -3
  55. angr/analyses/reaching_definitions/rd_state.py +37 -32
  56. angr/analyses/s_propagator.py +38 -5
  57. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
  58. angr/analyses/typehoon/simple_solver.py +16 -7
  59. angr/analyses/typehoon/translator.py +8 -0
  60. angr/analyses/typehoon/typeconsts.py +10 -2
  61. angr/analyses/typehoon/typehoon.py +4 -1
  62. angr/analyses/typehoon/typevars.py +9 -7
  63. angr/analyses/variable_recovery/engine_ail.py +296 -256
  64. angr/analyses/variable_recovery/engine_base.py +137 -116
  65. angr/analyses/variable_recovery/engine_vex.py +175 -185
  66. angr/analyses/variable_recovery/irsb_scanner.py +49 -38
  67. angr/analyses/variable_recovery/variable_recovery.py +28 -5
  68. angr/analyses/variable_recovery/variable_recovery_base.py +32 -33
  69. angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
  70. angr/analyses/xrefs.py +46 -19
  71. angr/annocfg.py +19 -14
  72. angr/block.py +4 -9
  73. angr/calling_conventions.py +1 -1
  74. angr/engines/engine.py +30 -14
  75. angr/engines/light/__init__.py +11 -3
  76. angr/engines/light/engine.py +1003 -1185
  77. angr/engines/pcode/cc.py +2 -0
  78. angr/engines/successors.py +13 -9
  79. angr/engines/vex/claripy/datalayer.py +1 -1
  80. angr/engines/vex/claripy/irop.py +14 -3
  81. angr/engines/vex/light/slicing.py +2 -2
  82. angr/exploration_techniques/__init__.py +1 -124
  83. angr/exploration_techniques/base.py +126 -0
  84. angr/exploration_techniques/bucketizer.py +1 -1
  85. angr/exploration_techniques/dfs.py +3 -1
  86. angr/exploration_techniques/director.py +2 -3
  87. angr/exploration_techniques/driller_core.py +1 -1
  88. angr/exploration_techniques/explorer.py +4 -2
  89. angr/exploration_techniques/lengthlimiter.py +2 -1
  90. angr/exploration_techniques/local_loop_seer.py +2 -1
  91. angr/exploration_techniques/loop_seer.py +5 -5
  92. angr/exploration_techniques/manual_mergepoint.py +2 -1
  93. angr/exploration_techniques/memory_watcher.py +3 -1
  94. angr/exploration_techniques/oppologist.py +4 -5
  95. angr/exploration_techniques/slicecutor.py +4 -2
  96. angr/exploration_techniques/spiller.py +1 -1
  97. angr/exploration_techniques/stochastic.py +2 -1
  98. angr/exploration_techniques/stub_stasher.py +2 -1
  99. angr/exploration_techniques/suggestions.py +3 -1
  100. angr/exploration_techniques/symbion.py +3 -1
  101. angr/exploration_techniques/tech_builder.py +2 -1
  102. angr/exploration_techniques/threading.py +4 -7
  103. angr/exploration_techniques/timeout.py +4 -2
  104. angr/exploration_techniques/tracer.py +4 -3
  105. angr/exploration_techniques/unique.py +3 -2
  106. angr/exploration_techniques/veritesting.py +1 -1
  107. angr/knowledge_plugins/key_definitions/atoms.py +2 -2
  108. angr/knowledge_plugins/key_definitions/live_definitions.py +16 -13
  109. angr/knowledge_plugins/propagations/states.py +13 -8
  110. angr/knowledge_plugins/variables/variable_manager.py +23 -9
  111. angr/lib/angr_native.dylib +0 -0
  112. angr/sim_manager.py +1 -3
  113. angr/sim_state.py +39 -41
  114. angr/sim_type.py +5 -0
  115. angr/sim_variable.py +29 -28
  116. angr/utils/bits.py +17 -0
  117. angr/utils/formatting.py +4 -1
  118. angr/utils/orderedset.py +4 -1
  119. angr/utils/ssa/__init__.py +21 -3
  120. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/METADATA +6 -6
  121. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/RECORD +125 -124
  122. angr/analyses/decompiler/optimization_passes/multi_simplifier.py +0 -223
  123. angr/analyses/propagator/engine_ail.py +0 -1562
  124. angr/storage/memory_mixins/__init__.pyi +0 -48
  125. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/LICENSE +0 -0
  126. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/WHEEL +0 -0
  127. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/entry_points.txt +0 -0
  128. {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/top_level.txt +0 -0
@@ -1,21 +1,22 @@
1
1
  from __future__ import annotations
2
- from typing import Any, TYPE_CHECKING
2
+ from typing import Any, TYPE_CHECKING, Generic, TypeVar, cast
3
3
  import contextlib
4
4
  import logging
5
5
 
6
6
  import ailment
7
7
  import claripy
8
8
 
9
+ from angr.analyses.variable_recovery.variable_recovery_base import VariableRecoveryStateBase
10
+ from angr.engines.light.engine import BlockType
9
11
  from angr.storage.memory_mixins.paged_memory.pages.multi_values import MultiValues
10
12
  from angr.engines.light import SimEngineLight, ArithmeticExpression
11
- from angr.errors import SimEngineError, SimMemoryMissingError
13
+ from angr.errors import SimMemoryMissingError
12
14
  from angr.sim_variable import SimVariable, SimStackVariable, SimRegisterVariable, SimMemoryVariable
13
15
  from angr.code_location import CodeLocation
14
16
  from angr.analyses.typehoon import typevars, typeconsts
15
17
  from angr.analyses.typehoon.typevars import TypeVariable, DerivedTypeVariable, AddN, SubN, Load, Store
16
18
 
17
19
  if TYPE_CHECKING:
18
- from .variable_recovery_base import VariableRecoveryStateBase
19
20
  from angr.knowledge_plugins.variables.variable_manager import VariableManager
20
21
 
21
22
  #
@@ -24,8 +25,10 @@ if TYPE_CHECKING:
24
25
 
25
26
  l = logging.getLogger(name=__name__)
26
27
 
28
+ RichRT_co = TypeVar("RichRT_co", bound=claripy.ast.Bits, covariant=True)
27
29
 
28
- class RichR:
30
+
31
+ class RichR(Generic[RichRT_co]):
29
32
  """
30
33
  A rich representation of calculation results. The variable recovery data domain.
31
34
  """
@@ -39,44 +42,42 @@ class RichR:
39
42
 
40
43
  def __init__(
41
44
  self,
42
- data: claripy.ast.Base,
45
+ data: RichRT_co,
43
46
  variable=None,
44
- typevar: typevars.TypeVariable | None = None,
45
- type_constraints=None,
47
+ typevar: typeconsts.TypeConstant | typevars.TypeVariable | None = None,
48
+ type_constraints: set[typevars.TypeConstraint] | None = None,
46
49
  ):
47
- self.data: claripy.ast.Base = data
50
+ self.data = data
48
51
  self.variable = variable
49
52
  self.typevar = typevar
50
53
  self.type_constraints = type_constraints
51
54
 
52
55
  @property
53
- def bits(self):
54
- if self.data is not None and not isinstance(self.data, (int, float)):
55
- if isinstance(self.data, claripy.ast.Base):
56
- return self.data.size()
57
- return self.data.bits
58
- if self.variable is not None:
59
- return self.variable.bits
60
- return None
56
+ def bits(self) -> int:
57
+ return self.data.size()
61
58
 
62
59
  def __repr__(self):
63
60
  return f"R{{{self.data!r}}}"
64
61
 
65
62
 
66
- class SimEngineVRBase(SimEngineLight):
63
+ VRStateType = TypeVar("VRStateType", bound=VariableRecoveryStateBase)
64
+
65
+
66
+ class SimEngineVRBase(
67
+ Generic[VRStateType, BlockType],
68
+ SimEngineLight[VRStateType, RichR[claripy.ast.BV | claripy.ast.FP], BlockType, None],
69
+ ):
67
70
  """
68
71
  The base class for variable recovery analyses. Contains methods for basic interactions with the state, like loading
69
72
  and storing data.
70
73
  """
71
74
 
72
- state: VariableRecoveryStateBase
75
+ variable_manager: VariableManager
73
76
 
74
77
  def __init__(self, project, kb):
75
- super().__init__()
78
+ super().__init__(project)
76
79
 
77
- self.project = project
78
80
  self.kb = kb
79
- self.variable_manager: VariableManager | None = None
80
81
  self.vvar_region: dict[int, Any] = {}
81
82
 
82
83
  @property
@@ -85,41 +86,37 @@ class SimEngineVRBase(SimEngineLight):
85
86
  return None
86
87
  return self.state.function.addr
87
88
 
88
- def process(self, state, *args, **kwargs): # pylint:disable=unused-argument
89
+ def process(self, state, *args, **kwargs):
89
90
  self.variable_manager = state.variable_manager
91
+ super().process(state, *args, **kwargs)
90
92
 
91
- try:
92
- self._process(state, None, block=kwargs.pop("block", None))
93
- except SimEngineError as e:
94
- if kwargs.pop("fail_fast", False) is True:
95
- raise e
93
+ def _top(self, bits):
94
+ return RichR(self.state.top(bits))
96
95
 
97
- def _process(
98
- self, state, successors, block=None, func_addr=None
99
- ): # pylint:disable=unused-argument,arguments-differ,arguments-renamed
100
- super()._process(state, successors, block=block)
96
+ def _is_top(self, expr):
97
+ return self.state.is_top(expr.data)
101
98
 
102
99
  #
103
100
  # Address parsing
104
101
  #
105
102
 
106
103
  @staticmethod
107
- def _addr_has_concrete_base(addr: claripy.ast.BV) -> bool:
104
+ def _addr_has_concrete_base(addr: claripy.ast.Bits) -> bool:
108
105
  if addr.op == "__add__" and len(addr.args) == 2:
109
- if addr.args[0].concrete:
106
+ if cast(claripy.ast.BV, addr.args[0]).concrete:
110
107
  return True
111
- if addr.args[1].concrete:
108
+ if cast(claripy.ast.BV, addr.args[1]).concrete:
112
109
  return True
113
110
  return False
114
111
 
115
112
  @staticmethod
116
- def _parse_offsetted_addr(addr: claripy.ast.BV) -> tuple[claripy.ast.BV, claripy.ast.BV, claripy.ast.BV] | None:
113
+ def _parse_offsetted_addr(addr: claripy.ast.Bits) -> tuple[claripy.ast.BV, claripy.ast.BV, int] | None:
117
114
  if addr.op == "__add__" and len(addr.args) == 2:
118
115
  concrete_base, byte_offset = None, None
119
- if addr.args[0].concrete:
120
- concrete_base, byte_offset = addr.args
121
- elif addr.args[1].concrete:
122
- concrete_base, byte_offset = addr.args[1], addr.args[0]
116
+ if cast(claripy.ast.BV, addr.args[0]).concrete:
117
+ concrete_base, byte_offset = cast(tuple[claripy.ast.BV, claripy.ast.BV], addr.args)
118
+ elif cast(claripy.ast.BV, addr.args[1]).concrete:
119
+ concrete_base, byte_offset = cast(tuple[claripy.ast.BV, claripy.ast.BV], (addr.args[1], addr.args[0]))
123
120
  if concrete_base is None or byte_offset is None:
124
121
  return None
125
122
  base_addr = concrete_base
@@ -130,9 +127,12 @@ class SimEngineVRBase(SimEngineLight):
130
127
  elem_size = 1
131
128
  else:
132
129
  abs_offset = byte_offset
133
- if abs_offset.op == "__lshift__" and abs_offset.args[1].concrete:
130
+ if abs_offset.op == "__lshift__" and cast(claripy.ast.BV, abs_offset.args[1]).concrete:
131
+ offset = cast(claripy.ast.BV, abs_offset.args[0])
132
+ elem_size = 2 ** cast(claripy.ast.BV, abs_offset.args[1]).concrete_value
133
+ elif abs_offset.op == "__mul__" and abs_offset.args[1].concrete:
134
134
  offset = abs_offset.args[0]
135
- elem_size = 2 ** abs_offset.args[1].concrete_value
135
+ elem_size = abs_offset.args[1].concrete_value
136
136
 
137
137
  if base_addr is not None and offset is not None and elem_size is not None:
138
138
  return base_addr, offset, elem_size
@@ -143,12 +143,9 @@ class SimEngineVRBase(SimEngineLight):
143
143
  #
144
144
 
145
145
  def _ensure_variable_existence(
146
- self, richr_addr: RichR, codeloc: CodeLocation, src_expr=None
147
- ) -> list[tuple[SimVariable, int]] | None:
148
- data: claripy.ast.Base = richr_addr.data
149
-
150
- if data is None:
151
- return None
146
+ self, richr_addr: RichR[claripy.ast.BV | claripy.ast.FP], codeloc: CodeLocation, src_expr=None
147
+ ) -> list[tuple[SimVariable, int]]:
148
+ data = richr_addr.data
152
149
 
153
150
  if self.state.is_stack_address(data):
154
151
  # this is a stack address
@@ -206,7 +203,7 @@ class SimEngineVRBase(SimEngineLight):
206
203
 
207
204
  # write the variable back to stack
208
205
  if vs is None:
209
- top = self.state.top(self.arch.byte_width)
206
+ top = self.state.top(self.project.arch.byte_width)
210
207
  top = self.state.annotate_with_variables(top, [(0, variable)])
211
208
  vs = MultiValues(top)
212
209
  self.state.stack_region.store(stack_addr, vs)
@@ -231,7 +228,7 @@ class SimEngineVRBase(SimEngineLight):
231
228
  existing_vars = [(variable, 0)]
232
229
 
233
230
  else:
234
- return None
231
+ return []
235
232
 
236
233
  # record all variables
237
234
  for var, offset in existing_vars:
@@ -241,8 +238,8 @@ class SimEngineVRBase(SimEngineLight):
241
238
 
242
239
  return existing_vars
243
240
 
244
- def _reference(self, richr: RichR, codeloc: CodeLocation, src=None):
245
- data: claripy.ast.Base = richr.data
241
+ def _reference(self, richr: RichR[claripy.ast.BV | claripy.ast.FP], codeloc: CodeLocation, src=None):
242
+ data = richr.data
246
243
 
247
244
  if data is None:
248
245
  return
@@ -257,7 +254,7 @@ class SimEngineVRBase(SimEngineLight):
257
254
  self.block.addr,
258
255
  self.stmt_idx,
259
256
  "memory",
260
- block_idx=self.block.idx if isinstance(self.block, ailment.Block) else None,
257
+ block_idx=cast(ailment.Block, self.block).idx if isinstance(self.block, ailment.Block) else None,
261
258
  )
262
259
 
263
260
  # find the correct variable
@@ -303,14 +300,17 @@ class SimEngineVRBase(SimEngineLight):
303
300
  :return:
304
301
  """
305
302
 
306
- if offset in (self.arch.ip_offset, self.arch.sp_offset, self.arch.lr_offset) or not create_variable:
303
+ if (
304
+ offset in (self.project.arch.ip_offset, self.project.arch.sp_offset, self.project.arch.lr_offset)
305
+ or not create_variable
306
+ ):
307
307
  # only store the value. don't worry about variables.
308
308
  v = MultiValues(richr.data)
309
309
  self.state.register_region.store(offset, v)
310
310
  return
311
311
 
312
312
  codeloc: CodeLocation = self._codeloc()
313
- data: claripy.ast.Base = richr.data
313
+ data = richr.data
314
314
 
315
315
  # lea
316
316
  self._ensure_variable_existence(richr, codeloc)
@@ -326,7 +326,9 @@ class SimEngineVRBase(SimEngineLight):
326
326
  # next check if we are overwriting *part* of an existing variable that is not an input variable
327
327
  addr_and_variables = set()
328
328
  try:
329
- vs: MultiValues = self.state.register_region.load(offset, size=size, endness=self.arch.register_endness)
329
+ vs: MultiValues = self.state.register_region.load(
330
+ offset, size=size, endness=self.project.arch.register_endness
331
+ )
330
332
  for values in vs.values():
331
333
  for value in values:
332
334
  addr_and_variables.update(self.state.extract_variables(value))
@@ -368,8 +370,8 @@ class SimEngineVRBase(SimEngineLight):
368
370
 
369
371
  def _assign_to_vvar(
370
372
  self,
371
- vvar: ailment.Expr.VirtualVariable,
372
- richr,
373
+ vvar: ailment.expression.VirtualVariable,
374
+ richr: RichR[claripy.ast.BV | claripy.ast.FP],
373
375
  src=None,
374
376
  dst=None,
375
377
  create_variable: bool = True,
@@ -380,8 +382,8 @@ class SimEngineVRBase(SimEngineLight):
380
382
  vvar_id = vvar.varid
381
383
 
382
384
  if (
383
- vvar.category == ailment.Expr.VirtualVariableCategory.REGISTER
384
- and vvar.oident in (self.arch.ip_offset, self.arch.sp_offset, self.arch.lr_offset)
385
+ vvar.category == ailment.expression.VirtualVariableCategory.REGISTER
386
+ and vvar.oident in (self.project.arch.ip_offset, self.project.arch.sp_offset, self.project.arch.lr_offset)
385
387
  or not create_variable
386
388
  ):
387
389
  # only store the value. don't worry about variables.
@@ -389,7 +391,7 @@ class SimEngineVRBase(SimEngineLight):
389
391
  return
390
392
 
391
393
  codeloc: CodeLocation = self._codeloc()
392
- data: claripy.ast.Base = richr.data
394
+ data = richr.data
393
395
 
394
396
  # lea
395
397
  self._ensure_variable_existence(richr, codeloc)
@@ -464,7 +466,9 @@ class SimEngineVRBase(SimEngineLight):
464
466
  self.state.add_type_constraint(typevars.Subtype(richr.typevar, typevar))
465
467
  self.state.add_type_constraint(typevars.Subtype(typevar, typeconsts.int_type(variable.size * 8)))
466
468
 
467
- def _store(self, richr_addr: RichR, data: RichR, size, stmt=None): # pylint:disable=unused-argument
469
+ def _store(
470
+ self, richr_addr: RichR[claripy.ast.BV], data: RichR[claripy.ast.BV | claripy.ast.FP], size, stmt=None
471
+ ): # pylint:disable=unused-argument
468
472
  """
469
473
 
470
474
  :param RichR addr:
@@ -473,16 +477,16 @@ class SimEngineVRBase(SimEngineLight):
473
477
  :return:
474
478
  """
475
479
 
476
- addr: claripy.ast.Base = richr_addr.data
480
+ addr = richr_addr.data
477
481
  stored = False
478
482
 
479
483
  if addr.concrete:
480
484
  # fully concrete. this is a global address
481
485
  self._store_to_global(addr.concrete_value, data, size, stmt=stmt)
482
486
  stored = True
483
- elif self._addr_has_concrete_base(addr) and self._parse_offsetted_addr(addr) is not None:
487
+ elif self._addr_has_concrete_base(addr) and (parsed := self._parse_offsetted_addr(addr)) is not None:
484
488
  # we are storing to a concrete global address with an offset
485
- base_addr, offset, elem_size = self._parse_offsetted_addr(addr)
489
+ base_addr, offset, elem_size = parsed
486
490
  self._store_to_global(base_addr.concrete_value, data, size, stmt=stmt, offset=offset, elem_size=elem_size)
487
491
  stored = True
488
492
  else:
@@ -506,7 +510,9 @@ class SimEngineVRBase(SimEngineLight):
506
510
  # storing to a location specified by a pointer whose value cannot be determined at this point
507
511
  self._store_to_variable(richr_addr, size, stmt=stmt)
508
512
 
509
- def _store_to_stack(self, stack_offset, data: RichR, size, offset=0, stmt=None, endness=None):
513
+ def _store_to_stack(
514
+ self, stack_offset, data: RichR[claripy.ast.BV | claripy.ast.FP], size, offset=0, stmt=None, endness=None
515
+ ):
510
516
  if stmt is None:
511
517
  existing_vars = self.variable_manager[self.func_addr].find_variables_by_stmt(
512
518
  self.block.addr, self.stmt_idx, "memory"
@@ -578,7 +584,7 @@ class SimEngineVRBase(SimEngineLight):
578
584
  size: int,
579
585
  stmt=None,
580
586
  offset: claripy.ast.BV | None = None,
581
- elem_size: claripy.ast.BV | None = None,
587
+ elem_size: int | None = None,
582
588
  ):
583
589
  variable_manager = self.variable_manager["global"]
584
590
  if stmt is None:
@@ -589,8 +595,8 @@ class SimEngineVRBase(SimEngineLight):
589
595
  if offset is None or elem_size is None:
590
596
  # trivial case
591
597
  abs_addr = addr
592
- elif offset.concrete and elem_size.concrete:
593
- abs_addr = addr + offset.concrete_value * elem_size.concrete_value
598
+ elif offset.concrete:
599
+ abs_addr = addr + offset.concrete_value * elem_size
594
600
  else:
595
601
  abs_addr = None
596
602
 
@@ -615,17 +621,17 @@ class SimEngineVRBase(SimEngineLight):
615
621
 
616
622
  if abs_addr is not None:
617
623
  self.state.global_region.store(
618
- addr, data_expr, endness=self.state.arch.memory_endness if stmt is None else stmt.endness
624
+ addr, data_expr, endness=self.project.arch.memory_endness if stmt is None else stmt.endness
619
625
  )
620
626
 
621
627
  codeloc = CodeLocation(
622
628
  self.block.addr, self.stmt_idx, ins_addr=self.ins_addr, block_idx=getattr(self.block, "idx", None)
623
629
  )
624
- values = None
630
+ values: MultiValues | None = None
625
631
  if abs_addr is not None:
626
632
  with contextlib.suppress(SimMemoryMissingError):
627
- values: MultiValues = self.state.global_region.load(
628
- abs_addr, size=size, endness=self.state.arch.memory_endness if stmt is None else stmt.endness
633
+ values = self.state.global_region.load(
634
+ abs_addr, size=size, endness=self.project.arch.memory_endness if stmt is None else stmt.endness
629
635
  )
630
636
 
631
637
  if values is not None:
@@ -646,8 +652,8 @@ class SimEngineVRBase(SimEngineLight):
646
652
 
647
653
  if offset is not None and elem_size is not None:
648
654
  # it's an array!
649
- if offset.concrete and elem_size.concrete:
650
- concrete_offset = offset.concrete_value * elem_size.concrete_value
655
+ if offset.concrete:
656
+ concrete_offset = offset.concrete_value * elem_size
651
657
  store_typevar = self._create_access_typevar(typevar, True, size, concrete_offset)
652
658
  self.state.add_type_constraint(typevars.Subtype(store_typevar, typeconsts.TopType()))
653
659
  else:
@@ -668,7 +674,9 @@ class SimEngineVRBase(SimEngineLight):
668
674
  self.state.add_type_constraint(typevars.Subtype(store_typevar, typeconsts.TopType()))
669
675
  self.state.add_type_constraint(typevars.Subtype(data.typevar, store_typevar))
670
676
 
671
- def _store_to_variable(self, richr_addr: RichR, size: int, stmt=None): # pylint:disable=unused-argument
677
+ def _store_to_variable(
678
+ self, richr_addr: RichR[claripy.ast.BV], size: int, stmt=None
679
+ ): # pylint:disable=unused-argument
672
680
  addr_variable = richr_addr.variable
673
681
  codeloc = self._codeloc()
674
682
 
@@ -695,7 +703,7 @@ class SimEngineVRBase(SimEngineLight):
695
703
  self.state.typevars.add_type_variable(addr_variable, codeloc, typevar)
696
704
  self.state.add_type_constraint(typevars.Subtype(store_typevar, typeconsts.TopType()))
697
705
 
698
- def _load(self, richr_addr: RichR, size: int, expr=None):
706
+ def _load(self, richr_addr: RichR[claripy.ast.BV], size: int, expr=None):
699
707
  """
700
708
 
701
709
  :param RichR richr_addr:
@@ -703,7 +711,7 @@ class SimEngineVRBase(SimEngineLight):
703
711
  :return:
704
712
  """
705
713
 
706
- addr: claripy.ast.Base = richr_addr.data
714
+ addr = cast(claripy.ast.BV, richr_addr.data)
707
715
  codeloc = CodeLocation(
708
716
  self.block.addr, self.stmt_idx, ins_addr=self.ins_addr, block_idx=getattr(self.block, "idx", None)
709
717
  )
@@ -734,14 +742,17 @@ class SimEngineVRBase(SimEngineLight):
734
742
  concrete_offset = stack_offset
735
743
  dynamic_offset = None
736
744
 
737
- try:
738
- values: MultiValues | None = self.state.stack_region.load(
739
- self.state.stack_addr_from_offset(concrete_offset),
740
- size=size,
741
- endness=self.state.arch.memory_endness,
742
- )
745
+ if concrete_offset is not None:
746
+ try:
747
+ values: MultiValues | None = self.state.stack_region.load(
748
+ self.state.stack_addr_from_offset(concrete_offset),
749
+ size=size,
750
+ endness=self.project.arch.memory_endness,
751
+ )
743
752
 
744
- except SimMemoryMissingError:
753
+ except SimMemoryMissingError:
754
+ values = None
755
+ else:
745
756
  values = None
746
757
 
747
758
  all_vars: set[tuple[int, SimVariable]] = set()
@@ -753,7 +764,7 @@ class SimEngineVRBase(SimEngineLight):
753
764
  var_offset = stack_offset - var_.offset
754
765
  all_vars.add((var_offset, var_))
755
766
 
756
- if not all_vars:
767
+ if not all_vars and concrete_offset is not None:
757
768
  variables = self.variable_manager[self.func_addr].find_variables_by_stack_offset(concrete_offset)
758
769
  if not variables:
759
770
  variable = SimStackVariable(
@@ -767,28 +778,27 @@ class SimEngineVRBase(SimEngineLight):
767
778
  variables = {variable}
768
779
  l.debug("Identified a new stack variable %s at %#x.", variable, self.ins_addr)
769
780
  for variable in variables:
770
- v = self.state.top(size * self.state.arch.byte_width)
781
+ v = self.state.top(size * self.project.arch.byte_width)
771
782
  v = self.state.annotate_with_variables(v, [(0, variable)])
772
783
  stack_addr = self.state.stack_addr_from_offset(concrete_offset)
773
- self.state.stack_region.store(stack_addr, v, endness=self.state.arch.memory_endness)
784
+ self.state.stack_region.store(stack_addr, v, endness=self.project.arch.memory_endness)
774
785
 
775
786
  all_vars = {(0, variable) for variable in variables}
776
787
 
777
- if len(all_vars) > 1:
778
- # overlapping variables
779
- all_vars = list(all_vars)
788
+ all_vars_list = list(all_vars)
780
789
 
790
+ if len(all_vars_list) > 1:
781
791
  # sort by some value so that the outcome here isn't random
782
- all_vars.sort(
792
+ cast(list[tuple[int, SimStackVariable]], all_vars_list).sort(
783
793
  reverse=True,
784
794
  key=lambda val: (val[0], val[1].offset, val[1].base, val[1].base_addr, val[1].size),
785
795
  )
786
796
 
787
797
  l.warning(
788
- "Reading memory with overlapping variables: %s. Ignoring all but the first one.", all_vars
798
+ "Reading memory with overlapping variables: %s. Ignoring all but the first one.", all_vars_list
789
799
  )
790
800
 
791
- var_offset, var = next(iter(all_vars)) # won't fail
801
+ var_offset, var = next(iter(all_vars_list)) # won't fail
792
802
  # calculate variable_offset
793
803
  if dynamic_offset is None:
794
804
  offset_into_variable = var_offset
@@ -835,8 +845,8 @@ class SimEngineVRBase(SimEngineLight):
835
845
  # | typevars.HasField(size * 8, 0)
836
846
  # | )
837
847
 
838
- r = self.state.top(size * self.state.arch.byte_width)
839
- r = self.state.annotate_with_variables(r, list(all_vars))
848
+ r = self.state.top(size * self.project.arch.byte_width)
849
+ r = self.state.annotate_with_variables(r, all_vars_list)
840
850
  return RichR(r, variable=var, typevar=typevar)
841
851
 
842
852
  elif addr.concrete:
@@ -844,9 +854,9 @@ class SimEngineVRBase(SimEngineLight):
844
854
  v = self._load_from_global(addr.concrete_value, size, expr=expr)
845
855
  typevar = v.typevar
846
856
 
847
- elif self._addr_has_concrete_base(addr) and self._parse_offsetted_addr(addr) is not None:
857
+ elif self._addr_has_concrete_base(addr) and (parsed := self._parse_offsetted_addr(addr)) is not None:
848
858
  # Loading data from a memory address with an offset
849
- base_addr, offset, elem_size = self._parse_offsetted_addr(addr)
859
+ base_addr, offset, elem_size = parsed
850
860
  v = self._load_from_global(base_addr.concrete_value, size, expr=expr, offset=offset, elem_size=elem_size)
851
861
  typevar = v.typevar
852
862
 
@@ -880,7 +890,7 @@ class SimEngineVRBase(SimEngineLight):
880
890
  typevar = self._create_access_typevar(richr_addr_typevar, False, size, offset)
881
891
  self.state.add_type_constraint(typevars.Subtype(typevar, typeconsts.TopType()))
882
892
 
883
- return RichR(self.state.top(size * self.state.arch.byte_width), typevar=typevar)
893
+ return RichR(self.state.top(size * self.project.arch.byte_width), typevar=typevar)
884
894
 
885
895
  def _load_from_global(
886
896
  self,
@@ -888,8 +898,8 @@ class SimEngineVRBase(SimEngineLight):
888
898
  size,
889
899
  expr=None,
890
900
  offset: claripy.ast.BV | None = None,
891
- elem_size: claripy.ast.BV | None = None,
892
- ) -> RichR:
901
+ elem_size: int | None = None,
902
+ ) -> RichR[claripy.ast.BV]:
893
903
  variable_manager = self.variable_manager["global"]
894
904
  if expr is None:
895
905
  existing_vars = variable_manager.find_variables_by_stmt(self.block.addr, self.stmt_idx, "memory")
@@ -911,7 +921,7 @@ class SimEngineVRBase(SimEngineLight):
911
921
  if not existing_vars:
912
922
  # is this address mapped?
913
923
  if self.project.loader.find_object_containing(addr) is None:
914
- return RichR(self.state.top(size * self.state.arch.byte_width))
924
+ return RichR(self.state.top(size * self.project.arch.byte_width))
915
925
  variable = SimMemoryVariable(
916
926
  addr,
917
927
  size,
@@ -937,8 +947,8 @@ class SimEngineVRBase(SimEngineLight):
937
947
 
938
948
  if offset is not None and elem_size is not None:
939
949
  # it's an array!
940
- if offset.concrete and elem_size.concrete:
941
- concrete_offset = offset.concrete_value * elem_size.concrete_value
950
+ if offset.concrete:
951
+ concrete_offset = offset.concrete_value * elem_size
942
952
  load_typevar = self._create_access_typevar(typevar, True, size, concrete_offset)
943
953
  self.state.add_type_constraint(typevars.Subtype(load_typevar, typeconsts.TopType()))
944
954
  else:
@@ -948,7 +958,7 @@ class SimEngineVRBase(SimEngineLight):
948
958
  load_typevar = self._create_access_typevar(typevar, True, size, concrete_offset)
949
959
  self.state.add_type_constraint(typevars.Subtype(load_typevar, typeconsts.TopType()))
950
960
 
951
- return RichR(self.state.top(size * self.state.arch.byte_width), typevar=typevar)
961
+ return RichR(self.state.top(size * self.project.arch.byte_width), typevar=typevar)
952
962
 
953
963
  def _read_from_register(self, offset, size, expr=None, force_variable_size=None, create_variable: bool = True):
954
964
  """
@@ -965,17 +975,17 @@ class SimEngineVRBase(SimEngineLight):
965
975
  except SimMemoryMissingError:
966
976
  values = None
967
977
 
968
- if offset in (self.arch.sp_offset, self.arch.ip_offset):
978
+ if offset in (self.project.arch.sp_offset, self.project.arch.ip_offset):
969
979
  # load values. don't worry about variables
970
980
  if values is None:
971
- r_value = self.state.top(size * self.arch.byte_width)
981
+ r_value = self.state.top(size * self.project.arch.byte_width)
972
982
  else:
973
983
  r_value = next(iter(next(iter(values.values()))))
974
984
  return RichR(r_value, variable=None, typevar=None)
975
985
 
976
986
  if not values:
977
987
  # the value does not exist.
978
- value = self.state.top(size * self.state.arch.byte_width)
988
+ value = self.state.top(size * self.project.arch.byte_width)
979
989
  if create_variable:
980
990
  # create a new variable if necessary
981
991
  variable = SimRegisterVariable(
@@ -998,7 +1008,7 @@ class SimEngineVRBase(SimEngineLight):
998
1008
  self.variable_manager[self.func_addr].read_from(var, None, codeloc, atom=expr, overwrite=False)
999
1009
  variable_set.add(var)
1000
1010
 
1001
- if offset == self.arch.sp_offset:
1011
+ if offset == self.project.arch.sp_offset:
1002
1012
  # ignore sp
1003
1013
  typevar = None
1004
1014
  var = None
@@ -1025,7 +1035,7 @@ class SimEngineVRBase(SimEngineLight):
1025
1035
  typevar = self.state.typevars[var]
1026
1036
 
1027
1037
  r_value = (
1028
- next(iter(value_list[0])) if len(value_list) == 1 else self.state.top(size * self.arch.byte_width)
1038
+ next(iter(value_list[0])) if len(value_list) == 1 else self.state.top(size * self.project.arch.byte_width)
1029
1039
  ) # fall back to top
1030
1040
  if var is not None and var.size != size:
1031
1041
  # ignore the variable and the associated type if we are only reading part of the variable
@@ -1033,22 +1043,26 @@ class SimEngineVRBase(SimEngineLight):
1033
1043
  return RichR(r_value, variable=var, typevar=typevar)
1034
1044
 
1035
1045
  def _read_from_vvar(
1036
- self, vvar: ailment.Expr.VirtualVariable, expr=None, create_variable: bool = True, vvar_id: int | None = None
1046
+ self,
1047
+ vvar: ailment.expression.VirtualVariable,
1048
+ expr=None,
1049
+ create_variable: bool = True,
1050
+ vvar_id: int | None = None,
1037
1051
  ):
1038
1052
  codeloc = self._codeloc()
1039
1053
 
1040
1054
  if vvar_id is None:
1041
1055
  vvar_id = vvar.varid
1042
1056
 
1043
- value: claripy.ast.Base | None = self.vvar_region.get(vvar_id, None)
1057
+ value: claripy.ast.BV | None = self.vvar_region.get(vvar_id, None)
1044
1058
 
1045
1059
  # fallback for register arguments
1046
1060
  if value is None and vvar.was_reg:
1047
1061
  return self._read_from_register(vvar.reg_offset, vvar.size, expr=vvar, create_variable=True)
1048
1062
 
1049
1063
  if vvar.category == ailment.Expr.VirtualVariableCategory.REGISTER and vvar.oident in (
1050
- self.arch.sp_offset,
1051
- self.arch.ip_offset,
1064
+ self.project.arch.sp_offset,
1065
+ self.project.arch.ip_offset,
1052
1066
  ):
1053
1067
  # load values. don't worry about variables
1054
1068
  r_value = self.state.top(vvar.size) if value is None else value
@@ -1092,7 +1106,10 @@ class SimEngineVRBase(SimEngineLight):
1092
1106
  self.variable_manager[self.func_addr].read_from(var, None, codeloc, atom=expr, overwrite=False)
1093
1107
  variable_set.add(var)
1094
1108
 
1095
- if vvar.category == ailment.Expr.VirtualVariableCategory.REGISTER and vvar.oident == self.arch.sp_offset:
1109
+ if (
1110
+ vvar.category == ailment.Expr.VirtualVariableCategory.REGISTER
1111
+ and vvar.oident == self.project.arch.sp_offset
1112
+ ):
1096
1113
  # ignore sp
1097
1114
  typevar = None
1098
1115
  var = None
@@ -1124,7 +1141,11 @@ class SimEngineVRBase(SimEngineLight):
1124
1141
  return RichR(value, variable=var, typevar=typevar)
1125
1142
 
1126
1143
  def _create_access_typevar(
1127
- self, typevar: TypeVariable | DerivedTypeVariable, is_store: bool, size: int, offset: int
1144
+ self,
1145
+ typevar: typeconsts.TypeConstant | TypeVariable | DerivedTypeVariable,
1146
+ is_store: bool,
1147
+ size: int,
1148
+ offset: int,
1128
1149
  ) -> DerivedTypeVariable:
1129
1150
  if isinstance(typevar, DerivedTypeVariable):
1130
1151
  if isinstance(typevar.labels[-1], AddN):
@@ -1143,5 +1164,5 @@ class SimEngineVRBase(SimEngineLight):
1143
1164
  return DerivedTypeVariable(
1144
1165
  typevar,
1145
1166
  None,
1146
- labels=(lbl, typevars.HasField(size * self.state.arch.byte_width, offset)),
1167
+ labels=(lbl, typevars.HasField(size * self.project.arch.byte_width, offset)),
1147
1168
  )