angr 9.2.101__py3-none-manylinux2014_x86_64.whl → 9.2.103__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 (239) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/analysis.py +7 -6
  3. angr/analyses/calling_convention.py +33 -35
  4. angr/analyses/cdg.py +2 -4
  5. angr/analyses/cfg/cfb.py +4 -3
  6. angr/analyses/cfg/cfg_base.py +14 -14
  7. angr/analyses/cfg/cfg_emulated.py +3 -4
  8. angr/analyses/cfg/cfg_fast.py +46 -46
  9. angr/analyses/cfg/cfg_fast_soot.py +1 -2
  10. angr/analyses/cfg/cfg_job_base.py +2 -2
  11. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +14 -13
  12. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +5 -5
  13. angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +3 -3
  14. angr/analyses/complete_calling_conventions.py +13 -12
  15. angr/analyses/data_dep/data_dependency_analysis.py +24 -24
  16. angr/analyses/data_dep/dep_nodes.py +3 -3
  17. angr/analyses/ddg.py +1 -2
  18. angr/analyses/decompiler/ail_simplifier.py +35 -34
  19. angr/analyses/decompiler/block_io_finder.py +20 -20
  20. angr/analyses/decompiler/block_similarity.py +4 -6
  21. angr/analyses/decompiler/block_simplifier.py +17 -16
  22. angr/analyses/decompiler/callsite_maker.py +25 -10
  23. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -3
  24. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +2 -4
  25. angr/analyses/decompiler/clinic.py +250 -45
  26. angr/analyses/decompiler/condition_processor.py +15 -8
  27. angr/analyses/decompiler/decompilation_cache.py +7 -7
  28. angr/analyses/decompiler/decompilation_options.py +4 -4
  29. angr/analyses/decompiler/decompiler.py +19 -15
  30. angr/analyses/decompiler/expression_counters.py +10 -9
  31. angr/analyses/decompiler/goto_manager.py +2 -4
  32. angr/analyses/decompiler/graph_region.py +9 -9
  33. angr/analyses/decompiler/jump_target_collector.py +1 -2
  34. angr/analyses/decompiler/optimization_passes/__init__.py +4 -3
  35. angr/analyses/decompiler/optimization_passes/code_motion.py +5 -6
  36. angr/analyses/decompiler/optimization_passes/const_derefs.py +4 -4
  37. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +73 -0
  38. angr/analyses/decompiler/optimization_passes/engine_base.py +25 -3
  39. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +6 -5
  40. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
  41. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +3 -0
  42. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +2 -2
  43. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +17 -17
  44. angr/analyses/decompiler/optimization_passes/optimization_pass.py +12 -13
  45. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +25 -21
  46. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +3 -3
  47. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +1 -2
  48. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +7 -7
  49. angr/analyses/decompiler/optimization_passes/spilled_register_finder.py +18 -0
  50. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +2 -3
  51. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -2
  52. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +2 -2
  53. angr/analyses/decompiler/peephole_optimizations/__init__.py +4 -3
  54. angr/analyses/decompiler/peephole_optimizations/base.py +13 -15
  55. angr/analyses/decompiler/peephole_optimizations/bswap.py +1 -3
  56. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +72 -0
  57. angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -2
  58. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
  59. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +5 -10
  60. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +3 -4
  61. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +7 -10
  62. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +2 -3
  63. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -2
  64. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +4 -4
  65. angr/analyses/decompiler/redundant_label_remover.py +4 -5
  66. angr/analyses/decompiler/region_identifier.py +4 -5
  67. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -2
  68. angr/analyses/decompiler/region_simplifiers/expr_folding.py +19 -20
  69. angr/analyses/decompiler/region_simplifiers/goto.py +2 -3
  70. angr/analyses/decompiler/region_simplifiers/loop.py +1 -2
  71. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -2
  72. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +1 -3
  73. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +19 -19
  74. angr/analyses/decompiler/return_maker.py +1 -2
  75. angr/analyses/decompiler/structured_codegen/base.py +5 -6
  76. angr/analyses/decompiler/structured_codegen/c.py +39 -38
  77. angr/analyses/decompiler/structuring/__init__.py +1 -1
  78. angr/analyses/decompiler/structuring/dream.py +17 -16
  79. angr/analyses/decompiler/structuring/phoenix.py +45 -46
  80. angr/analyses/decompiler/structuring/recursive_structurer.py +4 -4
  81. angr/analyses/decompiler/structuring/structurer_base.py +16 -15
  82. angr/analyses/decompiler/structuring/structurer_nodes.py +10 -9
  83. angr/analyses/decompiler/utils.py +17 -16
  84. angr/analyses/disassembly.py +7 -6
  85. angr/analyses/flirt.py +9 -9
  86. angr/analyses/forward_analysis/forward_analysis.py +15 -14
  87. angr/analyses/forward_analysis/visitors/function_graph.py +1 -2
  88. angr/analyses/forward_analysis/visitors/graph.py +16 -15
  89. angr/analyses/propagator/engine_ail.py +30 -26
  90. angr/analyses/propagator/outdated_definition_walker.py +8 -7
  91. angr/analyses/propagator/propagator.py +11 -13
  92. angr/analyses/proximity_graph.py +21 -21
  93. angr/analyses/reaching_definitions/__init__.py +3 -3
  94. angr/analyses/reaching_definitions/call_trace.py +3 -6
  95. angr/analyses/reaching_definitions/dep_graph.py +41 -48
  96. angr/analyses/reaching_definitions/engine_ail.py +11 -5
  97. angr/analyses/reaching_definitions/engine_vex.py +9 -8
  98. angr/analyses/reaching_definitions/function_handler.py +51 -34
  99. angr/analyses/reaching_definitions/heap_allocator.py +3 -4
  100. angr/analyses/reaching_definitions/rd_initializer.py +8 -8
  101. angr/analyses/reaching_definitions/rd_state.py +57 -58
  102. angr/analyses/reaching_definitions/reaching_definitions.py +18 -17
  103. angr/analyses/reaching_definitions/subject.py +2 -3
  104. angr/analyses/stack_pointer_tracker.py +15 -6
  105. angr/analyses/typehoon/dfa.py +4 -4
  106. angr/analyses/typehoon/simple_solver.py +48 -52
  107. angr/analyses/typehoon/translator.py +3 -6
  108. angr/analyses/typehoon/typeconsts.py +13 -14
  109. angr/analyses/typehoon/typehoon.py +9 -9
  110. angr/analyses/typehoon/typevars.py +18 -17
  111. angr/analyses/variable_recovery/engine_ail.py +5 -5
  112. angr/analyses/variable_recovery/engine_base.py +25 -21
  113. angr/analyses/variable_recovery/irsb_scanner.py +8 -9
  114. angr/analyses/variable_recovery/variable_recovery.py +1 -2
  115. angr/analyses/variable_recovery/variable_recovery_base.py +14 -13
  116. angr/analyses/variable_recovery/variable_recovery_fast.py +8 -8
  117. angr/analyses/veritesting.py +1 -2
  118. angr/analyses/vfg.py +57 -56
  119. angr/analyses/xrefs.py +1 -2
  120. angr/angrdb/db.py +7 -7
  121. angr/angrdb/serializers/kb.py +16 -13
  122. angr/angrdb/serializers/loader.py +1 -2
  123. angr/angrdb/serializers/structured_code.py +2 -2
  124. angr/annocfg.py +1 -2
  125. angr/block.py +16 -6
  126. angr/calling_conventions.py +27 -27
  127. angr/code_location.py +8 -8
  128. angr/codenode.py +1 -2
  129. angr/concretization_strategies/max.py +1 -3
  130. angr/distributed/server.py +1 -3
  131. angr/distributed/worker.py +1 -2
  132. angr/engines/engine.py +2 -3
  133. angr/engines/light/engine.py +4 -4
  134. angr/engines/pcode/behavior.py +20 -2
  135. angr/engines/pcode/emulate.py +1 -1
  136. angr/engines/pcode/engine.py +7 -7
  137. angr/engines/pcode/lifter.py +78 -77
  138. angr/engines/vex/claripy/ccall.py +1 -2
  139. angr/engines/vex/claripy/datalayer.py +1 -2
  140. angr/engines/vex/light/light.py +1 -2
  141. angr/exploration_techniques/tracer.py +4 -4
  142. angr/factory.py +12 -15
  143. angr/flirt/__init__.py +8 -8
  144. angr/flirt/build_sig.py +2 -3
  145. angr/keyed_region.py +2 -2
  146. angr/knowledge_base/knowledge_base.py +3 -3
  147. angr/knowledge_plugins/callsite_prototypes.py +4 -6
  148. angr/knowledge_plugins/cfg/cfg_manager.py +19 -6
  149. angr/knowledge_plugins/cfg/cfg_model.py +26 -27
  150. angr/knowledge_plugins/cfg/cfg_node.py +2 -2
  151. angr/knowledge_plugins/cfg/indirect_jump.py +6 -8
  152. angr/knowledge_plugins/cfg/memory_data.py +8 -9
  153. angr/knowledge_plugins/custom_strings.py +1 -3
  154. angr/knowledge_plugins/debug_variables.py +2 -2
  155. angr/knowledge_plugins/functions/function.py +21 -22
  156. angr/knowledge_plugins/functions/function_manager.py +5 -5
  157. angr/knowledge_plugins/indirect_jumps.py +1 -3
  158. angr/knowledge_plugins/key_definitions/atoms.py +7 -7
  159. angr/knowledge_plugins/key_definitions/definition.py +14 -14
  160. angr/knowledge_plugins/key_definitions/environment.py +5 -7
  161. angr/knowledge_plugins/key_definitions/heap_address.py +1 -3
  162. angr/knowledge_plugins/key_definitions/key_definition_manager.py +3 -2
  163. angr/knowledge_plugins/key_definitions/live_definitions.py +60 -59
  164. angr/knowledge_plugins/key_definitions/liveness.py +16 -16
  165. angr/knowledge_plugins/key_definitions/rd_model.py +15 -15
  166. angr/knowledge_plugins/key_definitions/uses.py +11 -11
  167. angr/knowledge_plugins/patches.py +4 -8
  168. angr/knowledge_plugins/propagations/prop_value.py +10 -9
  169. angr/knowledge_plugins/propagations/propagation_manager.py +3 -5
  170. angr/knowledge_plugins/propagations/propagation_model.py +9 -9
  171. angr/knowledge_plugins/propagations/states.py +52 -22
  172. angr/knowledge_plugins/structured_code/manager.py +2 -2
  173. angr/knowledge_plugins/sync/sync_controller.py +3 -3
  174. angr/knowledge_plugins/variables/variable_access.py +4 -4
  175. angr/knowledge_plugins/variables/variable_manager.py +56 -39
  176. angr/knowledge_plugins/xrefs/xref.py +9 -11
  177. angr/knowledge_plugins/xrefs/xref_manager.py +3 -4
  178. angr/misc/ansi.py +1 -2
  179. angr/misc/autoimport.py +3 -3
  180. angr/misc/plugins.py +9 -9
  181. angr/procedures/definitions/__init__.py +16 -16
  182. angr/procedures/definitions/linux_kernel.py +1 -1
  183. angr/procedures/definitions/parse_win32json.py +1 -1
  184. angr/procedures/java_jni/__init__.py +1 -1
  185. angr/procedures/java_jni/array_operations.py +1 -2
  186. angr/procedures/java_jni/method_calls.py +1 -2
  187. angr/procedures/posix/inet_ntoa.py +1 -2
  188. angr/procedures/stubs/format_parser.py +3 -3
  189. angr/project.py +13 -11
  190. angr/sim_manager.py +12 -12
  191. angr/sim_procedure.py +7 -3
  192. angr/sim_state.py +2 -2
  193. angr/sim_type.py +60 -45
  194. angr/sim_variable.py +5 -5
  195. angr/simos/simos.py +1 -2
  196. angr/simos/userland.py +1 -2
  197. angr/state_plugins/callstack.py +3 -2
  198. angr/state_plugins/history.py +1 -2
  199. angr/state_plugins/solver.py +34 -34
  200. angr/storage/memory_mixins/__init__.py +4 -3
  201. angr/storage/memory_mixins/actions_mixin.py +1 -3
  202. angr/storage/memory_mixins/address_concretization_mixin.py +1 -3
  203. angr/storage/memory_mixins/convenient_mappings_mixin.py +3 -4
  204. angr/storage/memory_mixins/default_filler_mixin.py +1 -1
  205. angr/storage/memory_mixins/label_merger_mixin.py +2 -2
  206. angr/storage/memory_mixins/multi_value_merger_mixin.py +4 -3
  207. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +9 -8
  208. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +12 -11
  209. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +8 -8
  210. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +2 -3
  211. angr/storage/memory_mixins/paged_memory/pages/list_page.py +10 -11
  212. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +11 -10
  213. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +18 -17
  214. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +12 -11
  215. angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +3 -3
  216. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +3 -2
  217. angr/storage/memory_mixins/regioned_memory/region_data.py +1 -2
  218. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +2 -2
  219. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +3 -3
  220. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +18 -21
  221. angr/storage/memory_mixins/size_resolution_mixin.py +1 -2
  222. angr/storage/memory_mixins/symbolic_merger_mixin.py +3 -2
  223. angr/storage/memory_mixins/top_merger_mixin.py +3 -2
  224. angr/storage/memory_object.py +2 -4
  225. angr/utils/algo.py +3 -2
  226. angr/utils/dynamic_dictlist.py +5 -5
  227. angr/utils/formatting.py +4 -4
  228. angr/utils/funcid.py +1 -2
  229. angr/utils/graph.py +5 -6
  230. angr/utils/library.py +5 -5
  231. angr/utils/mp.py +5 -4
  232. angr/utils/segment_list.py +3 -4
  233. angr/utils/typing.py +3 -2
  234. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/METADATA +9 -11
  235. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/RECORD +239 -236
  236. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/LICENSE +0 -0
  237. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/WHEEL +0 -0
  238. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/entry_points.txt +0 -0
  239. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  import logging
2
- from typing import Optional, DefaultDict, Dict, Tuple, Set, Any, Union, TYPE_CHECKING, Iterable
2
+ from typing import Optional, DefaultDict, Any, Union, TYPE_CHECKING
3
+ from collections.abc import Iterable
3
4
  from collections import defaultdict
4
5
 
5
6
  import ailment
@@ -28,8 +29,8 @@ from .dep_graph import DepGraph
28
29
  if TYPE_CHECKING:
29
30
  from typing import Literal
30
31
 
31
- ObservationPoint = Tuple[
32
- Literal["insn", "node", "stmt", "exit"], Union[int, Tuple[int, int], Tuple[int, int, int]], ObservationPointType
32
+ ObservationPoint = tuple[
33
+ Literal["insn", "node", "stmt", "exit"], Union[int, tuple[int, int], tuple[int, int, int]], ObservationPointType
33
34
  ]
34
35
 
35
36
  l = logging.getLogger(name=__name__)
@@ -53,7 +54,7 @@ class ReachingDefinitionsAnalysis(
53
54
 
54
55
  def __init__(
55
56
  self,
56
- subject: Union[Subject, ailment.Block, Block, Function, str] = None,
57
+ subject: Subject | ailment.Block | Block | Function | str = None,
57
58
  func_graph=None,
58
59
  max_iterations=30,
59
60
  track_tmps=False,
@@ -66,14 +67,14 @@ class ReachingDefinitionsAnalysis(
66
67
  function_handler: "Optional[FunctionHandler]" = None,
67
68
  observe_all=False,
68
69
  visited_blocks=None,
69
- dep_graph: Union[DepGraph, bool, None] = True,
70
+ dep_graph: DepGraph | bool | None = True,
70
71
  observe_callback=None,
71
72
  canonical_size=8,
72
73
  stack_pointer_tracker=None,
73
74
  use_callee_saved_regs_at_return=True,
74
75
  interfunction_level: int = 0,
75
76
  track_liveness: bool = True,
76
- func_addr: Optional[int] = None,
77
+ func_addr: int | None = None,
77
78
  element_limit: int = 5,
78
79
  ):
79
80
  """
@@ -198,13 +199,13 @@ class ReachingDefinitionsAnalysis(
198
199
  bp_as_gpr=bp_as_gpr,
199
200
  )
200
201
 
201
- self._visited_blocks: Set[Any] = visited_blocks or set()
202
- self.function_calls: Dict[CodeLocation, FunctionCallRelationships] = {}
202
+ self._visited_blocks: set[Any] = visited_blocks or set()
203
+ self.function_calls: dict[CodeLocation, FunctionCallRelationships] = {}
203
204
 
204
205
  self._analyze()
205
206
 
206
207
  @property
207
- def observed_results(self) -> Dict[Tuple[str, int, int], LiveDefinitions]:
208
+ def observed_results(self) -> dict[tuple[str, int, int], LiveDefinitions]:
208
209
  return self.model.observed_results
209
210
 
210
211
  @property
@@ -270,7 +271,7 @@ class ReachingDefinitionsAnalysis(
270
271
  node_addr: int,
271
272
  state: ReachingDefinitionsState,
272
273
  op_type: ObservationPointType,
273
- node_idx: Optional[int] = None,
274
+ node_idx: int | None = None,
274
275
  ) -> None:
275
276
  """
276
277
  :param node_addr: Address of the node.
@@ -307,8 +308,8 @@ class ReachingDefinitionsAnalysis(
307
308
  def insn_observe(
308
309
  self,
309
310
  insn_addr: int,
310
- stmt: Union[ailment.Stmt.Statement, pyvex.stmt.IRStmt],
311
- block: Union[Block, ailment.Block],
311
+ stmt: ailment.Stmt.Statement | pyvex.stmt.IRStmt,
312
+ block: Block | ailment.Block,
312
313
  state: ReachingDefinitionsState,
313
314
  op_type: ObservationPointType,
314
315
  ) -> None:
@@ -358,8 +359,8 @@ class ReachingDefinitionsAnalysis(
358
359
  def stmt_observe(
359
360
  self,
360
361
  stmt_idx: int,
361
- stmt: Union[ailment.Stmt.Statement, pyvex.stmt.IRStmt],
362
- block: Union[Block, ailment.Block],
362
+ stmt: ailment.Stmt.Statement | pyvex.stmt.IRStmt,
363
+ block: Block | ailment.Block,
363
364
  state: ReachingDefinitionsState,
364
365
  op_type: ObservationPointType,
365
366
  ) -> None:
@@ -405,9 +406,9 @@ class ReachingDefinitionsAnalysis(
405
406
  self,
406
407
  node_addr: int,
407
408
  exit_stmt_idx: int,
408
- block: Union[Block, ailment.Block],
409
+ block: Block | ailment.Block,
409
410
  state: ReachingDefinitionsState,
410
- node_idx: Optional[int] = None,
411
+ node_idx: int | None = None,
411
412
  ):
412
413
  observe = False
413
414
  key = None
@@ -577,7 +578,7 @@ class ReachingDefinitionsAnalysis(
577
578
  def _post_analysis(self):
578
579
  pass
579
580
 
580
- def callsites_to(self, target: Union[int, str, Function]) -> Iterable[FunctionCallRelationships]:
581
+ def callsites_to(self, target: int | str | Function) -> Iterable[FunctionCallRelationships]:
581
582
  if isinstance(target, (str, int)):
582
583
  try:
583
584
  func_addr = self.project.kb.functions[target].addr
@@ -1,5 +1,4 @@
1
1
  from enum import Enum
2
- from typing import Union
3
2
 
4
3
  import ailment
5
4
 
@@ -15,7 +14,7 @@ class SubjectType(Enum):
15
14
 
16
15
 
17
16
  class Subject:
18
- _visitor: Union[FunctionGraphVisitor, SingleNodeGraphVisitor]
17
+ _visitor: FunctionGraphVisitor | SingleNodeGraphVisitor
19
18
 
20
19
  def __init__(self, content, func_graph=None, cc=None):
21
20
  """
@@ -61,5 +60,5 @@ class Subject:
61
60
  return self._type
62
61
 
63
62
  @property
64
- def visitor(self) -> Union[FunctionGraphVisitor, SingleNodeGraphVisitor]:
63
+ def visitor(self) -> FunctionGraphVisitor | SingleNodeGraphVisitor:
65
64
  return self._visitor
@@ -1,6 +1,6 @@
1
1
  # pylint:disable=abstract-method,ungrouped-imports
2
2
 
3
- from typing import Set, List, Optional, TYPE_CHECKING
3
+ from typing import Optional, TYPE_CHECKING
4
4
  import re
5
5
  import logging
6
6
  from collections import defaultdict
@@ -69,7 +69,7 @@ class Constant:
69
69
 
70
70
  def __sub__(self, other):
71
71
  if type(self) is type(other):
72
- return Constant(self.val + other.val)
72
+ return Constant(self.val - other.val)
73
73
  else:
74
74
  raise CouldNotResolveException
75
75
 
@@ -313,11 +313,12 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
313
313
 
314
314
  def __init__(
315
315
  self,
316
- func: Optional[Function],
317
- reg_offsets: Set[int],
316
+ func: Function | None,
317
+ reg_offsets: set[int],
318
318
  block: Optional["Block"] = None,
319
319
  track_memory=True,
320
320
  cross_insn_opt=True,
321
+ initial_reg_values=None,
321
322
  ):
322
323
  if func is not None:
323
324
  if not func.normalized:
@@ -340,6 +341,9 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
340
341
  self._reg_value_at_block_start = defaultdict(dict)
341
342
  self.cross_insn_opt = cross_insn_opt
342
343
 
344
+ if initial_reg_values:
345
+ self._reg_value_at_block_start[func.addr if func is not None else block.addr] = initial_reg_values
346
+
343
347
  _l.debug("Running on function %r", self._func)
344
348
  self._analyze()
345
349
 
@@ -439,6 +443,11 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
439
443
  return True
440
444
  return False
441
445
 
446
+ def offsets_for(self, reg):
447
+ return [
448
+ o for block in self._func.blocks if (o := self.offset_after_block(block.addr, reg)) not in (TOP, BOTTOM)
449
+ ]
450
+
442
451
  #
443
452
  # Overridable methods
444
453
  #
@@ -811,8 +820,8 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
811
820
  merged_state = merged_state.merge(other)
812
821
  return merged_state, merged_state == states[0]
813
822
 
814
- def _find_callees(self, node) -> List[Function]:
815
- callees: List[Function] = []
823
+ def _find_callees(self, node) -> list[Function]:
824
+ callees: list[Function] = []
816
825
  for _, dst, data in self._func.transition_graph.out_edges(node, data=True):
817
826
  if data.get("type") == "call":
818
827
  if isinstance(dst, Function):
@@ -1,4 +1,4 @@
1
- from typing import Set, List, Tuple, Optional, TYPE_CHECKING
1
+ from typing import TYPE_CHECKING
2
2
 
3
3
  import networkx
4
4
 
@@ -29,7 +29,7 @@ class DFAConstraintSolver:
29
29
  """
30
30
 
31
31
  @staticmethod
32
- def graph_to_epsilon_nfa(graph: networkx.DiGraph, starts: Set, ends: Set) -> EpsilonNFA:
32
+ def graph_to_epsilon_nfa(graph: networkx.DiGraph, starts: set, ends: set) -> EpsilonNFA:
33
33
  enfa = EpsilonNFA()
34
34
 
35
35
  # print("Converting graph to eNFA")
@@ -62,7 +62,7 @@ class DFAConstraintSolver:
62
62
  raise EmptyEpsilonNFAError()
63
63
  return enfa
64
64
 
65
- def generate_constraints_between(self, graph: networkx.DiGraph, starts: Set, ends: Set) -> Set:
65
+ def generate_constraints_between(self, graph: networkx.DiGraph, starts: set, ends: set) -> set:
66
66
  epsilon_nfa = self.graph_to_epsilon_nfa(graph, starts, ends)
67
67
  min_dfa: "DeterministicFiniteAutomaton" = epsilon_nfa.minimize()
68
68
  dfa_graph: networkx.MultiDiGraph = min_dfa.to_networkx()
@@ -86,7 +86,7 @@ class DFAConstraintSolver:
86
86
  return constraints
87
87
 
88
88
  @staticmethod
89
- def _check_constraint(src, dst, string: List[Tuple[BaseLabel, str]]) -> Optional[Subtype]:
89
+ def _check_constraint(src, dst, string: list[tuple[BaseLabel, str]]) -> Subtype | None:
90
90
  forgets = []
91
91
  recalls = []
92
92
  for label, kind in string:
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=missing-class-docstring
2
- from typing import Union, Type, Set, Dict, Optional, Tuple, List, DefaultDict
2
+ from typing import DefaultDict
3
3
  import enum
4
4
  from collections import defaultdict
5
5
  import logging
@@ -125,8 +125,8 @@ class SketchNode(SketchNodeBase):
125
125
 
126
126
  __slots__ = ("typevar", "upper_bound", "lower_bound")
127
127
 
128
- def __init__(self, typevar: Union[TypeVariable, DerivedTypeVariable]):
129
- self.typevar: Union[TypeVariable, DerivedTypeVariable] = typevar
128
+ def __init__(self, typevar: TypeVariable | DerivedTypeVariable):
129
+ self.typevar: TypeVariable | DerivedTypeVariable = typevar
130
130
  self.upper_bound = TopType()
131
131
  self.lower_bound = BottomType()
132
132
 
@@ -172,17 +172,17 @@ class Sketch:
172
172
  def __init__(self, solver: "SimpleSolver", root: TypeVariable):
173
173
  self.root: SketchNode = SketchNode(root)
174
174
  self.graph = networkx.DiGraph()
175
- self.node_mapping: Dict[Union[TypeVariable, DerivedTypeVariable], SketchNodeBase] = {}
175
+ self.node_mapping: dict[TypeVariable | DerivedTypeVariable, SketchNodeBase] = {}
176
176
  self.solver = solver
177
177
 
178
178
  # add the root node
179
179
  self.graph.add_node(self.root)
180
180
  self.node_mapping[root] = self.root
181
181
 
182
- def lookup(self, typevar: Union[TypeVariable, DerivedTypeVariable]) -> Optional[SketchNodeBase]:
182
+ def lookup(self, typevar: TypeVariable | DerivedTypeVariable) -> SketchNodeBase | None:
183
183
  if typevar in self.node_mapping:
184
184
  return self.node_mapping[typevar]
185
- node: Optional[SketchNodeBase] = None
185
+ node: SketchNodeBase | None = None
186
186
  if isinstance(typevar, DerivedTypeVariable):
187
187
  node = self.node_mapping[SimpleSolver._to_typevar_or_typeconst(typevar.type_var)]
188
188
  for label in typevar.labels:
@@ -210,21 +210,21 @@ class Sketch:
210
210
  if SimpleSolver._typevar_inside_set(subtype, PRIMITIVE_TYPES) and not SimpleSolver._typevar_inside_set(
211
211
  supertype, PRIMITIVE_TYPES
212
212
  ):
213
- super_node: Optional[SketchNode] = self.lookup(supertype)
213
+ super_node: SketchNode | None = self.lookup(supertype)
214
214
  if super_node is not None:
215
215
  super_node.lower_bound = self.solver.join(super_node.lower_bound, subtype)
216
216
  elif SimpleSolver._typevar_inside_set(supertype, PRIMITIVE_TYPES) and not SimpleSolver._typevar_inside_set(
217
217
  subtype, PRIMITIVE_TYPES
218
218
  ):
219
- sub_node: Optional[SketchNode] = self.lookup(subtype)
219
+ sub_node: SketchNode | None = self.lookup(subtype)
220
220
  # assert sub_node is not None
221
221
  if sub_node is not None:
222
222
  sub_node.upper_bound = self.solver.meet(sub_node.upper_bound, supertype)
223
223
 
224
224
  @staticmethod
225
225
  def flatten_typevar(
226
- derived_typevar: Union[TypeVariable, TypeConstant, DerivedTypeVariable]
227
- ) -> Union[DerivedTypeVariable, TypeVariable, TypeConstant]:
226
+ derived_typevar: TypeVariable | TypeConstant | DerivedTypeVariable,
227
+ ) -> DerivedTypeVariable | TypeVariable | TypeConstant:
228
228
  # pylint:disable=too-many-boolean-expressions
229
229
  if (
230
230
  isinstance(derived_typevar, DerivedTypeVariable)
@@ -261,7 +261,7 @@ class ConstraintGraphNode:
261
261
 
262
262
  def __init__(
263
263
  self,
264
- typevar: Union[TypeVariable, DerivedTypeVariable],
264
+ typevar: TypeVariable | DerivedTypeVariable,
265
265
  variance: Variance,
266
266
  tag: ConstraintGraphTag,
267
267
  forgotten: FORGOTTEN,
@@ -298,7 +298,7 @@ class ConstraintGraphNode:
298
298
  def __hash__(self):
299
299
  return hash((ConstraintGraphNode, self.typevar, self.variance, self.tag, self.forgotten))
300
300
 
301
- def forget_last_label(self) -> Optional[Tuple["ConstraintGraphNode", BaseLabel]]:
301
+ def forget_last_label(self) -> tuple["ConstraintGraphNode", BaseLabel] | None:
302
302
  if isinstance(self.typevar, DerivedTypeVariable) and self.typevar.labels:
303
303
  last_label = self.typevar.labels[-1]
304
304
  if len(self.typevar.labels) == 1:
@@ -382,8 +382,8 @@ class SimpleSolver:
382
382
  raise ValueError("Pointer size %d is not supported. Expect 32 or 64." % bits)
383
383
 
384
384
  self.bits = bits
385
- self._constraints: Dict[TypeVariable, Set[TypeConstraint]] = constraints
386
- self._typevars: Set[TypeVariable] = typevars
385
+ self._constraints: dict[TypeVariable, set[TypeConstraint]] = constraints
386
+ self._typevars: set[TypeVariable] = typevars
387
387
  self._base_lattice = BASE_LATTICES[bits]
388
388
  self._base_lattice_inverted = networkx.DiGraph()
389
389
  for src, dst in self._base_lattice.edges:
@@ -463,15 +463,15 @@ class SimpleSolver:
463
463
  return equivalence_classes, sketches, type_schemes
464
464
 
465
465
  def infer_shapes(
466
- self, typevars: Set[TypeVariable], constraints: Set[TypeConstraint]
467
- ) -> Tuple[Dict, Dict[TypeVariable, Sketch]]:
466
+ self, typevars: set[TypeVariable], constraints: set[TypeConstraint]
467
+ ) -> tuple[dict, dict[TypeVariable, Sketch]]:
468
468
  """
469
469
  Computing sketches from constraint sets. Implements Algorithm E.1 in the retypd paper.
470
470
  """
471
471
 
472
472
  equivalence_classes, quotient_graph = self.compute_quotient_graph(constraints)
473
473
 
474
- sketches: Dict[TypeVariable, Sketch] = {}
474
+ sketches: dict[TypeVariable, Sketch] = {}
475
475
  for tv in typevars:
476
476
  sketches[tv] = Sketch(self, tv)
477
477
 
@@ -485,7 +485,7 @@ class SimpleSolver:
485
485
  self._get_all_paths(quotient_graph, sketch, graph_node, visited)
486
486
  return equivalence_classes, sketches
487
487
 
488
- def compute_quotient_graph(self, constraints: Set[TypeConstraint]):
488
+ def compute_quotient_graph(self, constraints: set[TypeConstraint]):
489
489
  """
490
490
  Compute the quotient graph (the constraint graph modulo ~ in Algorithm E.1 in the retypd paper) with respect to
491
491
  a given set of type constraints.
@@ -547,21 +547,21 @@ class SimpleSolver:
547
547
 
548
548
  def _generate_primitive_constraints(
549
549
  self,
550
- non_primitive_endpoints: Set[Union[TypeVariable, DerivedTypeVariable]],
550
+ non_primitive_endpoints: set[TypeVariable | DerivedTypeVariable],
551
551
  constraint_graph,
552
- ) -> Set[TypeConstraint]:
552
+ ) -> set[TypeConstraint]:
553
553
  # FIXME: Extract interesting variables
554
554
  constraints_0 = self._solve_constraints_between(constraint_graph, non_primitive_endpoints, PRIMITIVE_TYPES)
555
555
  constraints_1 = self._solve_constraints_between(constraint_graph, PRIMITIVE_TYPES, non_primitive_endpoints)
556
556
  return constraints_0 | constraints_1
557
557
 
558
558
  @staticmethod
559
- def _typevars_from_constraints(constraints: Set[TypeConstraint]) -> Set[Union[TypeVariable, DerivedTypeVariable]]:
559
+ def _typevars_from_constraints(constraints: set[TypeConstraint]) -> set[TypeVariable | DerivedTypeVariable]:
560
560
  """
561
561
  Collect derived type variables from a set of constraints.
562
562
  """
563
563
 
564
- typevars: Set[Union[TypeVariable, DerivedTypeVariable]] = set()
564
+ typevars: set[TypeVariable | DerivedTypeVariable] = set()
565
565
  for constraint in constraints:
566
566
  if isinstance(constraint, Subtype):
567
567
  typevars.add(constraint.sub_type)
@@ -574,7 +574,7 @@ class SimpleSolver:
574
574
  graph: networkx.DiGraph,
575
575
  sketch: Sketch,
576
576
  node: DerivedTypeVariable,
577
- visited: Dict[Union[TypeVariable, DerivedTypeVariable], SketchNode],
577
+ visited: dict[TypeVariable | DerivedTypeVariable, SketchNode],
578
578
  ):
579
579
  if node not in graph:
580
580
  return
@@ -608,7 +608,7 @@ class SimpleSolver:
608
608
 
609
609
  @staticmethod
610
610
  def _unify(
611
- equivalence_classes: Dict, cls0: DerivedTypeVariable, cls1: DerivedTypeVariable, graph: networkx.DiGraph
611
+ equivalence_classes: dict, cls0: DerivedTypeVariable, cls1: DerivedTypeVariable, graph: networkx.DiGraph
612
612
  ) -> None:
613
613
  # first convert cls0 and cls1 to their equivalence classes
614
614
  cls0 = equivalence_classes[cls0]
@@ -736,8 +736,8 @@ class SimpleSolver:
736
736
 
737
737
  @staticmethod
738
738
  def _generate_constraint_subset(
739
- constraints: Set[TypeConstraint], typevars: Set[TypeVariable]
740
- ) -> Set[TypeConstraint]:
739
+ constraints: set[TypeConstraint], typevars: set[TypeVariable]
740
+ ) -> set[TypeConstraint]:
741
741
  subset = set()
742
742
  related_typevars = set(typevars)
743
743
  while True:
@@ -770,7 +770,7 @@ class SimpleSolver:
770
770
  return subset
771
771
 
772
772
  def _generate_constraint_graph(
773
- self, constraints: Set[TypeConstraint], interesting_variables: Set[DerivedTypeVariable]
773
+ self, constraints: set[TypeConstraint], interesting_variables: set[DerivedTypeVariable]
774
774
  ) -> networkx.DiGraph:
775
775
  """
776
776
  A constraint graph is the same as the finite state transducer that is presented in Appendix D in the retypd
@@ -811,9 +811,9 @@ class SimpleSolver:
811
811
  def _constraint_graph_add_edges(
812
812
  self,
813
813
  graph: networkx.DiGraph,
814
- subtype: Union[TypeVariable, DerivedTypeVariable],
815
- supertype: Union[TypeVariable, DerivedTypeVariable],
816
- interesting_variables: Set[DerivedTypeVariable],
814
+ subtype: TypeVariable | DerivedTypeVariable,
815
+ supertype: TypeVariable | DerivedTypeVariable,
816
+ interesting_variables: set[DerivedTypeVariable],
817
817
  ):
818
818
  # left and right tags
819
819
  if self._typevar_inside_set(self._to_typevar_or_typeconst(subtype), interesting_variables):
@@ -844,7 +844,7 @@ class SimpleSolver:
844
844
  """
845
845
  The saturation algorithm D.2 as described in Appendix of the retypd paper.
846
846
  """
847
- R: DefaultDict[ConstraintGraphNode, Set[Tuple[BaseLabel, ConstraintGraphNode]]] = defaultdict(set)
847
+ R: DefaultDict[ConstraintGraphNode, set[tuple[BaseLabel, ConstraintGraphNode]]] = defaultdict(set)
848
848
 
849
849
  # initialize the reaching-push sets R(x)
850
850
  for x, y, data in graph.edges(data=True):
@@ -913,9 +913,7 @@ class SimpleSolver:
913
913
  graph.add_edge(forget_src, forget_dst, **data)
914
914
 
915
915
  @staticmethod
916
- def _to_typevar_or_typeconst(
917
- obj: Union[TypeVariable, DerivedTypeVariable, TypeConstant]
918
- ) -> Union[TypeVariable, TypeConstant]:
916
+ def _to_typevar_or_typeconst(obj: TypeVariable | DerivedTypeVariable | TypeConstant) -> TypeVariable | TypeConstant:
919
917
  if isinstance(obj, DerivedTypeVariable):
920
918
  return SimpleSolver._to_typevar_or_typeconst(obj.type_var)
921
919
  elif isinstance(obj, TypeVariable):
@@ -929,7 +927,7 @@ class SimpleSolver:
929
927
  #
930
928
 
931
929
  @staticmethod
932
- def _typevar_inside_set(typevar, typevar_set: Set[Union[TypeConstant, TypeVariable, DerivedTypeVariable]]) -> bool:
930
+ def _typevar_inside_set(typevar, typevar_set: set[TypeConstant | TypeVariable | DerivedTypeVariable]) -> bool:
933
931
  if typevar in typevar_set:
934
932
  return True
935
933
  if isinstance(typevar, Struct) and Struct_ in typevar_set:
@@ -948,9 +946,9 @@ class SimpleSolver:
948
946
  def _solve_constraints_between(
949
947
  self,
950
948
  graph: networkx.DiGraph,
951
- starts: Set[Union[TypeConstant, TypeVariable, DerivedTypeVariable]],
952
- ends: Set[Union[TypeConstant, TypeVariable, DerivedTypeVariable]],
953
- ) -> Set[TypeConstraint]:
949
+ starts: set[TypeConstant | TypeVariable | DerivedTypeVariable],
950
+ ends: set[TypeConstant | TypeVariable | DerivedTypeVariable],
951
+ ) -> set[TypeConstraint]:
954
952
  start_nodes = set()
955
953
  end_nodes = set()
956
954
  for node in graph.nodes:
@@ -979,7 +977,7 @@ class SimpleSolver:
979
977
  # Type lattice
980
978
  #
981
979
 
982
- def join(self, t1: Union[TypeConstant, TypeVariable], t2: Union[TypeConstant, TypeVariable]) -> TypeConstant:
980
+ def join(self, t1: TypeConstant | TypeVariable, t2: TypeConstant | TypeVariable) -> TypeConstant:
983
981
  abstract_t1 = self.abstract(t1)
984
982
  abstract_t2 = self.abstract(t2)
985
983
  if abstract_t1 in self._base_lattice and abstract_t2 in self._base_lattice:
@@ -996,7 +994,7 @@ class SimpleSolver:
996
994
  return t1
997
995
  return Bottom_
998
996
 
999
- def meet(self, t1: Union[TypeConstant, TypeVariable], t2: Union[TypeConstant, TypeVariable]) -> TypeConstant:
997
+ def meet(self, t1: TypeConstant | TypeVariable, t2: TypeConstant | TypeVariable) -> TypeConstant:
1000
998
  abstract_t1 = self.abstract(t1)
1001
999
  abstract_t2 = self.abstract(t2)
1002
1000
  if abstract_t1 in self._base_lattice_inverted and abstract_t2 in self._base_lattice_inverted:
@@ -1014,7 +1012,7 @@ class SimpleSolver:
1014
1012
  return Top_
1015
1013
 
1016
1014
  @staticmethod
1017
- def abstract(t: Union[TypeConstant, TypeVariable]) -> Union[TypeConstant, TypeVariable]:
1015
+ def abstract(t: TypeConstant | TypeVariable) -> TypeConstant | TypeVariable:
1018
1016
  if isinstance(t, Pointer32):
1019
1017
  return Pointer32()
1020
1018
  elif isinstance(t, Pointer64):
@@ -1023,10 +1021,10 @@ class SimpleSolver:
1023
1021
 
1024
1022
  def determine(
1025
1023
  self,
1026
- equivalent_classes: Dict[TypeVariable, TypeVariable],
1024
+ equivalent_classes: dict[TypeVariable, TypeVariable],
1027
1025
  sketches,
1028
- solution: Dict,
1029
- nodes: Optional[Set[SketchNode]] = None,
1026
+ solution: dict,
1027
+ nodes: set[SketchNode] | None = None,
1030
1028
  ) -> None:
1031
1029
  """
1032
1030
  Determine C-like types from sketches.
@@ -1045,9 +1043,7 @@ class SimpleSolver:
1045
1043
  if v not in solution and e in solution:
1046
1044
  solution[v] = solution[e]
1047
1045
 
1048
- def _determine(
1049
- self, equivalent_classes, the_typevar, sketch, solution: Dict, nodes: Optional[Set[SketchNode]] = None
1050
- ):
1046
+ def _determine(self, equivalent_classes, the_typevar, sketch, solution: dict, nodes: set[SketchNode] | None = None):
1051
1047
  """
1052
1048
  Return the solution from sketches
1053
1049
  """
@@ -1214,13 +1210,13 @@ class SimpleSolver:
1214
1210
  return result
1215
1211
 
1216
1212
  @staticmethod
1217
- def _collect_sketch_paths(node: SketchNodeBase, sketch: Sketch) -> List[Tuple[List[BaseLabel], SketchNodeBase]]:
1213
+ def _collect_sketch_paths(node: SketchNodeBase, sketch: Sketch) -> list[tuple[list[BaseLabel], SketchNodeBase]]:
1218
1214
  """
1219
1215
  Collect all paths that go from `typevar` to its leaves.
1220
1216
  """
1221
1217
  paths = []
1222
- visited: Set[SketchNodeBase] = set()
1223
- queue: List[Tuple[List[BaseLabel], SketchNodeBase]] = [([], node)]
1218
+ visited: set[SketchNodeBase] = set()
1219
+ queue: list[tuple[list[BaseLabel], SketchNodeBase]] = [([], node)]
1224
1220
 
1225
1221
  while queue:
1226
1222
  curr_labels, curr_node = queue.pop(0)
@@ -1232,7 +1228,7 @@ class SimpleSolver:
1232
1228
  for _, succ, data in out_edges:
1233
1229
  if isinstance(succ, RecursiveRefNode):
1234
1230
  ref = succ
1235
- succ: Optional[SketchNode] = sketch.lookup(succ.target)
1231
+ succ: SketchNode | None = sketch.lookup(succ.target)
1236
1232
  if succ is None:
1237
1233
  # failed to resolve...
1238
1234
  _l.warning(
@@ -1254,7 +1250,7 @@ class SimpleSolver:
1254
1250
 
1255
1251
  return paths
1256
1252
 
1257
- def _pointer_class(self) -> Union[Type[Pointer32], Type[Pointer64]]:
1253
+ def _pointer_class(self) -> type[Pointer32] | type[Pointer64]:
1258
1254
  if self.bits == 32:
1259
1255
  return Pointer32
1260
1256
  elif self.bits == 64:
@@ -1,4 +1,3 @@
1
- from typing import Dict, Union
2
1
  from itertools import count
3
2
 
4
3
  from ... import sim_type
@@ -24,8 +23,8 @@ class TypeTranslator:
24
23
  def __init__(self, arch=None):
25
24
  self.arch = arch
26
25
 
27
- self.translated: Dict[TypeConstant, SimType] = {}
28
- self.translated_simtypes: Dict[SimType, TypeConstant] = {}
26
+ self.translated: dict[TypeConstant, SimType] = {}
27
+ self.translated_simtypes: dict[SimType, TypeConstant] = {}
29
28
  self.structs = {}
30
29
  self._struct_ctr = count()
31
30
 
@@ -209,9 +208,7 @@ class TypeTranslator:
209
208
  array_tc = typeconsts.Array(elem_type, count=st.length)
210
209
  return array_tc
211
210
 
212
- def _translate_SimTypePointer(
213
- self, st: sim_type.SimTypePointer
214
- ) -> Union[typeconsts.Pointer32, typeconsts.Pointer64]:
211
+ def _translate_SimTypePointer(self, st: sim_type.SimTypePointer) -> typeconsts.Pointer32 | typeconsts.Pointer64:
215
212
  base = self._simtype2tc(st.pts_to)
216
213
  if self.arch.bits == 32:
217
214
  return typeconsts.Pointer32(base)