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
@@ -2,7 +2,7 @@
2
2
 
3
3
  import logging
4
4
  import math
5
- from typing import Optional, List, Union, Dict, Set, Tuple, TYPE_CHECKING
5
+ from typing import Optional, Union, TYPE_CHECKING
6
6
 
7
7
  from networkx import DiGraph
8
8
 
@@ -54,9 +54,9 @@ class DataDependencyGraphAnalysis(Analysis):
54
54
  def __init__(
55
55
  self,
56
56
  end_state: "SimState",
57
- start_from: Optional[int] = None,
58
- end_at: Optional[int] = None,
59
- block_addrs: Optional[List[int]] = None,
57
+ start_from: int | None = None,
58
+ end_at: int | None = None,
59
+ block_addrs: list[int] | None = None,
60
60
  ):
61
61
  """
62
62
  :param end_state: Simulation state used to extract all SimActionData
@@ -64,9 +64,9 @@ class DataDependencyGraphAnalysis(Analysis):
64
64
  :param end_at: An address or None, Specifies where to end generation of DDG
65
65
  :param iterable or None block_addrs: List of block addresses that the DDG analysis should be run on
66
66
  """
67
- self._graph: Optional[DiGraph] = None
68
- self._simplified_graph: Optional[DiGraph] = None
69
- self._sub_graph: Optional[DiGraph] = None
67
+ self._graph: DiGraph | None = None
68
+ self._simplified_graph: DiGraph | None = None
69
+ self._sub_graph: DiGraph | None = None
70
70
 
71
71
  self._end_state = end_state
72
72
  self._start_from = start_from if start_from else self.project.entry
@@ -77,12 +77,12 @@ class DataDependencyGraphAnalysis(Analysis):
77
77
  self._register_file.set_state(self._end_state)
78
78
  self._memory_map = DefaultMemory(memory_id="mem") # Tracks the current state of all parsed memory addresses
79
79
  self._memory_map.set_state(self._end_state)
80
- self._tmp_nodes: Dict[str, TmpDepNode] = {} # Per-block: Maps temp name to its current node
81
- self._constant_nodes: Dict[int, ConstantDepNode] = {} # Per program: Maps values to their ConstantDepNodes
82
- self._actions: List["SimActionData"] = []
80
+ self._tmp_nodes: dict[str, TmpDepNode] = {} # Per-block: Maps temp name to its current node
81
+ self._constant_nodes: dict[int, ConstantDepNode] = {} # Per program: Maps values to their ConstantDepNodes
82
+ self._actions: list["SimActionData"] = []
83
83
 
84
84
  # Used by parser to track instruction addresses processed
85
- self._parsed_ins_addrs: List[ParsedInstruction] = [] # Instruction address, min stmt_idx, max stmt_idx
85
+ self._parsed_ins_addrs: list[ParsedInstruction] = [] # Instruction address, min stmt_idx, max stmt_idx
86
86
 
87
87
  # Parameter sanity check
88
88
  if self._block_addrs and self._end_at:
@@ -91,15 +91,15 @@ class DataDependencyGraphAnalysis(Analysis):
91
91
  self._work()
92
92
 
93
93
  @property
94
- def graph(self) -> Optional[DiGraph]:
94
+ def graph(self) -> DiGraph | None:
95
95
  return self._graph
96
96
 
97
97
  @property
98
- def simplified_graph(self) -> Optional[DiGraph]:
98
+ def simplified_graph(self) -> DiGraph | None:
99
99
  return self._simplified_graph
100
100
 
101
101
  @property
102
- def sub_graph(self) -> Optional[DiGraph]:
102
+ def sub_graph(self) -> DiGraph | None:
103
103
  return self._sub_graph
104
104
 
105
105
  def _pop(self) -> Optional["SimActionData"]:
@@ -171,7 +171,7 @@ class DataDependencyGraphAnalysis(Analysis):
171
171
  self,
172
172
  type_: int,
173
173
  sim_act: "SimActionData",
174
- val: Tuple["BV", int],
174
+ val: tuple["BV", int],
175
175
  *constructor_params,
176
176
  ) -> "BaseDepNode":
177
177
  """
@@ -213,7 +213,7 @@ class DataDependencyGraphAnalysis(Analysis):
213
213
  return ret_node
214
214
 
215
215
  def _get_dep_node(
216
- self, dep_type: int, sim_act: SimActionData, var_src: Union[int, "BV"], val: Union[int, BV]
216
+ self, dep_type: int, sim_act: SimActionData, var_src: Union[int, "BV"], val: int | BV
217
217
  ) -> "BaseDepNode":
218
218
  if isinstance(var_src, BV):
219
219
  var_src = self._end_state.solver.eval(var_src)
@@ -287,7 +287,7 @@ class DataDependencyGraphAnalysis(Analysis):
287
287
  def _parse_action(self) -> "BaseDepNode":
288
288
  return self._get_generic_node(self._pop())
289
289
 
290
- def _parse_read_statement(self, read_nodes: Optional[Dict[int, List["BaseDepNode"]]] = None) -> "BaseDepNode":
290
+ def _parse_read_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> "BaseDepNode":
291
291
  act = self._peek()
292
292
  read_node = self._parse_action()
293
293
  ancestor_node = self._get_active_node(read_node)
@@ -310,7 +310,7 @@ class DataDependencyGraphAnalysis(Analysis):
310
310
 
311
311
  return read_node
312
312
 
313
- def _create_dep_edges(self, act, write_node, read_nodes: Dict[int, List["BaseDepNode"]]) -> bool:
313
+ def _create_dep_edges(self, act, write_node, read_nodes: dict[int, list["BaseDepNode"]]) -> bool:
314
314
  """Last resort for linking dependencies"""
315
315
  # Check tmp and reg deps
316
316
  var_read_nodes = []
@@ -337,7 +337,7 @@ class DataDependencyGraphAnalysis(Analysis):
337
337
 
338
338
  return dep_found
339
339
 
340
- def _parse_var_statement(self, read_nodes: Optional[Dict[int, List["BaseDepNode"]]] = None) -> SimActLocation:
340
+ def _parse_var_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> SimActLocation:
341
341
  act = self._peek()
342
342
  act_loc = SimActLocation(act.bbl_addr, act.ins_addr, act.stmt_idx)
343
343
 
@@ -383,7 +383,7 @@ class DataDependencyGraphAnalysis(Analysis):
383
383
  self._parse_statement(read_nodes) if self._peek() and act.stmt_idx == self._peek().stmt_idx else act_loc
384
384
  )
385
385
 
386
- def _parse_mem_statement(self, read_nodes: Optional[Dict[int, List["BaseDepNode"]]] = None) -> SimActLocation:
386
+ def _parse_mem_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> SimActLocation:
387
387
  act = self._peek()
388
388
  act_loc = SimActLocation(act.bbl_addr, act.ins_addr, act.stmt_idx)
389
389
 
@@ -416,7 +416,7 @@ class DataDependencyGraphAnalysis(Analysis):
416
416
 
417
417
  return ret_val if ret_val else self._parse_statement(read_nodes)
418
418
 
419
- def _parse_statement(self, read_nodes: Optional[Dict[int, List["BaseDepNode"]]] = None) -> SimActLocation:
419
+ def _parse_statement(self, read_nodes: dict[int, list["BaseDepNode"]] | None = None) -> SimActLocation:
420
420
  """
421
421
  statement -> write_var | write_mem
422
422
  statement -> read_var | write_mem statement
@@ -493,7 +493,7 @@ class DataDependencyGraphAnalysis(Analysis):
493
493
  self._parse_block()
494
494
  self._parse_blocks()
495
495
 
496
- def _filter_sim_actions(self) -> List[SimActionData]:
496
+ def _filter_sim_actions(self) -> list[SimActionData]:
497
497
  """
498
498
  Using the user's start/end address OR block address list parameters,
499
499
  filters the actions down to those that are relevant
@@ -574,7 +574,7 @@ class DataDependencyGraphAnalysis(Analysis):
574
574
  return g0
575
575
 
576
576
  @staticmethod
577
- def _get_related_nodes(G: DiGraph, curr_node: "BaseDepNode", nodes: Set["BaseDepNode"], get_ancestors: bool):
577
+ def _get_related_nodes(G: DiGraph, curr_node: "BaseDepNode", nodes: set["BaseDepNode"], get_ancestors: bool):
578
578
  nodes.add(curr_node)
579
579
 
580
580
  next_nodes = G.predecessors(curr_node) if get_ancestors else G.successors(curr_node)
@@ -587,7 +587,7 @@ class DataDependencyGraphAnalysis(Analysis):
587
587
  else:
588
588
  return
589
589
 
590
- def get_data_dep(self, g_node: "BaseDepNode", include_tmp_nodes: bool, backwards: bool) -> Optional[DiGraph]:
590
+ def get_data_dep(self, g_node: "BaseDepNode", include_tmp_nodes: bool, backwards: bool) -> DiGraph | None:
591
591
  # We have a matching node and can proceed to build a subgraph
592
592
  if g_node in self._graph:
593
593
  relevant_nodes = set()
@@ -1,4 +1,4 @@
1
- from typing import Optional, Tuple, TYPE_CHECKING
1
+ from typing import Optional, TYPE_CHECKING
2
2
 
3
3
  if TYPE_CHECKING:
4
4
  from claripy.ast.bv import BV
@@ -27,10 +27,10 @@ class BaseDepNode:
27
27
  self.ins_addr = sim_act.ins_addr
28
28
  self.stmt_idx = sim_act.stmt_idx
29
29
  self.action_id: int = sim_act.id
30
- self.value: Optional[int] = None
30
+ self.value: int | None = None
31
31
  self._value_ast: Optional["BV"] = None
32
32
 
33
- def value_tuple(self) -> Tuple["BV", int]:
33
+ def value_tuple(self) -> tuple["BV", int]:
34
34
  """
35
35
  :return: A tuple containing the node's value as a BV and as an evaluated integer
36
36
  """
angr/analyses/ddg.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  from collections import defaultdict
3
- from typing import List
4
3
 
5
4
  import networkx
6
5
  import pyvex
@@ -425,7 +424,7 @@ class DDGViewInstruction:
425
424
  return DDGViewItem(self._ddg, pv, simplified=self._simplified)
426
425
 
427
426
  @property
428
- def definitions(self) -> List[DDGViewItem]:
427
+ def definitions(self) -> list[DDGViewItem]:
429
428
  """
430
429
  Get all definitions located at the current instruction address.
431
430
 
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=too-many-boolean-expressions
2
- from typing import Set, Dict, List, Tuple, Any, Optional, TYPE_CHECKING
2
+ from typing import Any, Optional, TYPE_CHECKING
3
3
  from collections import defaultdict
4
4
  import logging
5
5
 
@@ -74,14 +74,15 @@ class AILSimplifier(Analysis):
74
74
  func,
75
75
  func_graph=None,
76
76
  remove_dead_memdefs=False,
77
- stack_arg_offsets: Optional[Set[Tuple[int, int]]] = None,
77
+ stack_arg_offsets: set[tuple[int, int]] | None = None,
78
78
  unify_variables=False,
79
79
  ail_manager: Optional["Manager"] = None,
80
- gp: Optional[int] = None,
80
+ gp: int | None = None,
81
81
  narrow_expressions=False,
82
82
  only_consts=False,
83
83
  fold_callexprs_into_conditions=False,
84
84
  use_callee_saved_regs_at_return=True,
85
+ rewrite_ccalls=True,
85
86
  ):
86
87
  self.func = func
87
88
  self.func_graph = func_graph if func_graph is not None else func.graph
@@ -97,9 +98,10 @@ class AILSimplifier(Analysis):
97
98
  self._only_consts = only_consts
98
99
  self._fold_callexprs_into_conditions = fold_callexprs_into_conditions
99
100
  self._use_callee_saved_regs_at_return = use_callee_saved_regs_at_return
101
+ self._should_rewrite_ccalls = rewrite_ccalls
100
102
 
101
- self._calls_to_remove: Set[CodeLocation] = set()
102
- self._assignments_to_remove: Set[CodeLocation] = set()
103
+ self._calls_to_remove: set[CodeLocation] = set()
104
+ self._assignments_to_remove: set[CodeLocation] = set()
103
105
  self.blocks = {} # Mapping nodes to simplified blocks
104
106
 
105
107
  self.simplified: bool = False
@@ -127,13 +129,14 @@ class AILSimplifier(Analysis):
127
129
  if self._only_consts:
128
130
  return
129
131
 
130
- _l.debug("Rewriting ccalls")
131
- ccalls_rewritten = self._rewrite_ccalls()
132
- self.simplified |= ccalls_rewritten
133
- if ccalls_rewritten:
134
- _l.debug("... ccalls rewritten")
135
- self._rebuild_func_graph()
136
- self._clear_cache()
132
+ if self._should_rewrite_ccalls:
133
+ _l.debug("Rewriting ccalls")
134
+ ccalls_rewritten = self._rewrite_ccalls()
135
+ self.simplified |= ccalls_rewritten
136
+ if ccalls_rewritten:
137
+ _l.debug("... ccalls rewritten")
138
+ self._rebuild_func_graph()
139
+ self._clear_cache()
137
140
 
138
141
  if self._unify_vars:
139
142
  _l.debug("Removing dead assignments")
@@ -227,7 +230,7 @@ class AILSimplifier(Analysis):
227
230
 
228
231
  narrowed = False
229
232
 
230
- addr_and_idx_to_block: Dict[Tuple[int, int], Block] = {}
233
+ addr_and_idx_to_block: dict[tuple[int, int], Block] = {}
231
234
  for block in self.func_graph.nodes():
232
235
  addr_and_idx_to_block[(block.addr, block.idx)] = block
233
236
 
@@ -457,13 +460,13 @@ class AILSimplifier(Analysis):
457
460
 
458
461
  def _narrowing_needed(
459
462
  self, def_, rd, addr_and_idx_to_block
460
- ) -> Tuple[bool, Optional[int], Optional[List[Tuple[CodeLocation, Tuple[str, Tuple[Expression, ...]]]]]]:
463
+ ) -> tuple[bool, int | None, list[tuple[CodeLocation, tuple[str, tuple[Expression, ...]]]] | None]:
461
464
  def_size = def_.size
462
465
  # find its uses
463
466
  use_and_exprs = rd.all_uses.get_uses_with_expr(def_)
464
467
 
465
468
  all_used_sizes = set()
466
- used_by: List[Tuple[CodeLocation, Tuple[str, Tuple[Expression, ...]]]] = []
469
+ used_by: list[tuple[CodeLocation, tuple[str, tuple[Expression, ...]]]] = []
467
470
 
468
471
  for loc, expr in use_and_exprs:
469
472
  old_block = addr_and_idx_to_block.get((loc.block_addr, loc.block_idx), None)
@@ -492,7 +495,7 @@ class AILSimplifier(Analysis):
492
495
 
493
496
  def _extract_expression_effective_size(
494
497
  self, statement, expr
495
- ) -> Tuple[Optional[int], Optional[Tuple[str, Tuple[Expression, ...]]]]:
498
+ ) -> tuple[int | None, tuple[str, tuple[Expression, ...]] | None]:
496
499
  """
497
500
  Determine the effective size of an expression when it's used.
498
501
  """
@@ -603,11 +606,11 @@ class AILSimplifier(Analysis):
603
606
  if not prop.model.equivalence:
604
607
  return simplified
605
608
 
606
- addr_and_idx_to_block: Dict[Tuple[int, int], Block] = {}
609
+ addr_and_idx_to_block: dict[tuple[int, int], Block] = {}
607
610
  for block in self.func_graph.nodes():
608
611
  addr_and_idx_to_block[(block.addr, block.idx)] = block
609
612
 
610
- equivalences: Dict[Any, Set[Equivalence]] = defaultdict(set)
613
+ equivalences: dict[Any, set[Equivalence]] = defaultdict(set)
611
614
  atom_by_loc = set()
612
615
  for eq in prop.model.equivalence:
613
616
  equivalences[eq.atom1].add(eq)
@@ -735,7 +738,7 @@ class AILSimplifier(Analysis):
735
738
  continue
736
739
 
737
740
  # find all its uses
738
- all_arg_copy_var_uses: Set[Tuple[CodeLocation, Any]] = set(
741
+ all_arg_copy_var_uses: set[tuple[CodeLocation, Any]] = set(
739
742
  rd.all_uses.get_uses_with_expr(arg_copy_def)
740
743
  )
741
744
  all_uses_with_def = set()
@@ -816,7 +819,7 @@ class AILSimplifier(Analysis):
816
819
 
817
820
  # find all uses of this definition
818
821
  # we make a copy of the set since we may touch the set (uses) when replacing expressions
819
- all_uses: Set[Tuple[CodeLocation, Any]] = set(rd.all_uses.get_uses_with_expr(to_replace_def))
822
+ all_uses: set[tuple[CodeLocation, Any]] = set(rd.all_uses.get_uses_with_expr(to_replace_def))
820
823
  # make sure none of these uses are phi nodes (depends on more than one def)
821
824
  all_uses_with_unique_def = set()
822
825
  for use_and_expr in all_uses:
@@ -943,7 +946,7 @@ class AILSimplifier(Analysis):
943
946
  return simplified
944
947
 
945
948
  @staticmethod
946
- def _find_atom_def_at(atom, rd, codeloc: CodeLocation) -> Optional[Definition]:
949
+ def _find_atom_def_at(atom, rd, codeloc: CodeLocation) -> Definition | None:
947
950
  if isinstance(atom, Register):
948
951
  defs = rd.get_defs(atom, codeloc, OP_BEFORE)
949
952
  return next(iter(defs)) if len(defs) == 1 else None
@@ -1007,18 +1010,18 @@ class AILSimplifier(Analysis):
1007
1010
  if not prop.model.equivalence:
1008
1011
  return simplified
1009
1012
 
1010
- addr_and_idx_to_block: Dict[Tuple[int, int], Block] = {}
1013
+ addr_and_idx_to_block: dict[tuple[int, int], Block] = {}
1011
1014
  for block in self.func_graph.nodes():
1012
1015
  addr_and_idx_to_block[(block.addr, block.idx)] = block
1013
1016
 
1014
- def_locations_to_remove: Set[CodeLocation] = set()
1015
- updated_use_locations: Set[CodeLocation] = set()
1017
+ def_locations_to_remove: set[CodeLocation] = set()
1018
+ updated_use_locations: set[CodeLocation] = set()
1016
1019
 
1017
1020
  eq: Equivalence
1018
1021
  for eq in prop.model.equivalence:
1019
1022
  # register variable == Call
1020
1023
  if isinstance(eq.atom0, Register):
1021
- call_addr: Optional[int]
1024
+ call_addr: int | None
1022
1025
  if isinstance(eq.atom1, Call):
1023
1026
  # register variable = Call
1024
1027
  call: Expression = eq.atom1
@@ -1052,7 +1055,7 @@ class AILSimplifier(Analysis):
1052
1055
  the_def: Definition = defs[0]
1053
1056
 
1054
1057
  # find all uses of this definition
1055
- all_uses: Set[Tuple[CodeLocation, Any]] = set(rd.all_uses.get_uses_with_expr(the_def))
1058
+ all_uses: set[tuple[CodeLocation, Any]] = set(rd.all_uses.get_uses_with_expr(the_def))
1056
1059
 
1057
1060
  if len(all_uses) != 1:
1058
1061
  continue
@@ -1156,8 +1159,8 @@ class AILSimplifier(Analysis):
1156
1159
  # no need to clear the cache at the end of this method
1157
1160
  return simplified
1158
1161
 
1159
- def _get_super_node_blocks(self, start_node: Block) -> List[Block]:
1160
- lst: List[Block] = [start_node]
1162
+ def _get_super_node_blocks(self, start_node: Block) -> list[Block]:
1163
+ lst: list[Block] = [start_node]
1161
1164
  while True:
1162
1165
  b = lst[-1]
1163
1166
  successors = list(self.func_graph.successors(b))
@@ -1178,7 +1181,7 @@ class AILSimplifier(Analysis):
1178
1181
 
1179
1182
  def _replace_expr_and_update_block(
1180
1183
  self, block, stmt_idx, stmt, the_def, codeloc, src_expr, dst_expr
1181
- ) -> Tuple[bool, Optional[Block]]:
1184
+ ) -> tuple[bool, Block | None]:
1182
1185
  replaced, new_stmt = stmt.replace(src_expr, dst_expr)
1183
1186
  if replaced:
1184
1187
  new_block = block.copy()
@@ -1193,7 +1196,7 @@ class AILSimplifier(Analysis):
1193
1196
  return False, None
1194
1197
 
1195
1198
  def _remove_dead_assignments(self) -> bool:
1196
- stmts_to_remove_per_block: Dict[Tuple[int, int], Set[int]] = defaultdict(set)
1199
+ stmts_to_remove_per_block: dict[tuple[int, int], set[int]] = defaultdict(set)
1197
1200
 
1198
1201
  # Find all statements that should be removed
1199
1202
  mask = (1 << self.project.arch.bits) - 1
@@ -1325,9 +1328,7 @@ class AILSimplifier(Analysis):
1325
1328
 
1326
1329
  v = False
1327
1330
 
1328
- def _handle_expr(
1329
- expr_idx: int, expr: Expression, stmt_idx: int, stmt: Statement, block
1330
- ) -> Optional[Expression]:
1331
+ def _handle_expr(expr_idx: int, expr: Expression, stmt_idx: int, stmt: Statement, block) -> Expression | None:
1331
1332
  if isinstance(expr, DirtyExpression) and isinstance(expr.dirty_expr, VEXCCallExpression):
1332
1333
  rewriter = rewriter_cls(expr.dirty_expr, self.project.arch)
1333
1334
  if rewriter.result is not None:
@@ -1383,7 +1384,7 @@ class AILSimplifier(Analysis):
1383
1384
  return False
1384
1385
 
1385
1386
  @staticmethod
1386
- def _count_calls_in_supernodeblocks(blocks: List[Block], start: CodeLocation, end: CodeLocation) -> int:
1387
+ def _count_calls_in_supernodeblocks(blocks: list[Block], start: CodeLocation, end: CodeLocation) -> int:
1387
1388
  """
1388
1389
  Count the number of call statements in a list of blocks for a single super block between two given code
1389
1390
  locations (exclusive).
@@ -1,5 +1,5 @@
1
1
  from collections import defaultdict
2
- from typing import Any, Optional, Union, List
2
+ from typing import Any
3
3
 
4
4
  from ailment import Block
5
5
  from ailment.statement import Call, Statement, ConditionalJump, Assignment, Store, Return, Jump
@@ -26,7 +26,7 @@ class BlockIOFinder(AILBlockWalkerBase):
26
26
  I/O locations can be a Register, MemoryLocation, or SpOffset (wrapped in a Memory Location).
27
27
  """
28
28
 
29
- def __init__(self, ail_obj: Union[Block, List[Statement]], project, as_atom=True):
29
+ def __init__(self, ail_obj: Block | list[Statement], project, as_atom=True):
30
30
  super().__init__()
31
31
  self.expr_handlers[StackBaseOffset] = self._handle_StackBaseOffset
32
32
  self._as_atom = as_atom
@@ -86,7 +86,7 @@ class BlockIOFinder(AILBlockWalkerBase):
86
86
  other_input = self.inputs_by_stmt[other_idx]
87
87
  return target_output.intersection(other_input)
88
88
 
89
- def can_swap(self, stmt, ail_obj: Union[Block, List[Statement]], offset: int):
89
+ def can_swap(self, stmt, ail_obj: Block | list[Statement], offset: int):
90
90
  all_stmts = (ail_obj.statements or []) if isinstance(ail_obj, Block) else ail_obj
91
91
  if stmt not in all_stmts:
92
92
  raise RuntimeError("Statement not in block, and we can't compute moving a stmt to a new block!")
@@ -123,14 +123,14 @@ class BlockIOFinder(AILBlockWalkerBase):
123
123
  # Statements (all with side effects)
124
124
  #
125
125
 
126
- def _handle_Assignment(self, stmt_idx: int, stmt: Assignment, block: Optional[Block]):
126
+ def _handle_Assignment(self, stmt_idx: int, stmt: Assignment, block: Block | None):
127
127
  output_loc = self._handle_expr(0, stmt.dst, stmt_idx, stmt, block)
128
128
  self._add_or_update_dict(self.outputs_by_stmt, stmt_idx, output_loc)
129
129
 
130
130
  input_loc = self._handle_expr(1, stmt.src, stmt_idx, stmt, block)
131
131
  self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input_loc)
132
132
 
133
- def _handle_Call(self, stmt_idx: int, stmt: Call, block: Optional[Block]):
133
+ def _handle_Call(self, stmt_idx: int, stmt: Call, block: Block | None):
134
134
  if stmt.args:
135
135
  for i, arg in enumerate(stmt.args):
136
136
  input_loc = self._handle_expr(i, arg, stmt_idx, stmt, block)
@@ -139,14 +139,14 @@ class BlockIOFinder(AILBlockWalkerBase):
139
139
  out_loc = self._handle_expr(0, stmt.ret_expr, stmt_idx, stmt, block)
140
140
  self._add_or_update_dict(self.outputs_by_stmt, stmt_idx, out_loc)
141
141
 
142
- def _handle_Store(self, stmt_idx: int, stmt: Store, block: Optional[Block]):
142
+ def _handle_Store(self, stmt_idx: int, stmt: Store, block: Block | None):
143
143
  out_loc = self._handle_expr(0, stmt.addr, stmt_idx, stmt, block, is_memory=True)
144
144
  self._add_or_update_dict(self.outputs_by_stmt, stmt_idx, out_loc)
145
145
 
146
146
  input_loc = self._handle_expr(1, stmt.data, stmt_idx, stmt, block)
147
147
  self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input_loc)
148
148
 
149
- def _handle_ConditionalJump(self, stmt_idx: int, stmt: ConditionalJump, block: Optional[Block]):
149
+ def _handle_ConditionalJump(self, stmt_idx: int, stmt: ConditionalJump, block: Block | None):
150
150
  input1 = self._handle_expr(0, stmt.condition, stmt_idx, stmt, block)
151
151
  input2 = self._handle_expr(1, stmt.true_target, stmt_idx, stmt, block)
152
152
  input3 = self._handle_expr(2, stmt.false_target, stmt_idx, stmt, block)
@@ -154,7 +154,7 @@ class BlockIOFinder(AILBlockWalkerBase):
154
154
  self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input2)
155
155
  self._add_or_update_dict(self.inputs_by_stmt, stmt_idx, input3)
156
156
 
157
- def _handle_Return(self, stmt_idx: int, stmt: Return, block: Optional[Block]):
157
+ def _handle_Return(self, stmt_idx: int, stmt: Return, block: Block | None):
158
158
  if stmt.ret_exprs:
159
159
  for i, ret_expr in enumerate(stmt.ret_exprs):
160
160
  loc = self._handle_expr(i, ret_expr, stmt_idx, stmt, block)
@@ -170,8 +170,8 @@ class BlockIOFinder(AILBlockWalkerBase):
170
170
  expr_idx: int,
171
171
  expr: Expression,
172
172
  stmt_idx: int,
173
- stmt: Optional[Statement],
174
- block: Optional[Block],
173
+ stmt: Statement | None,
174
+ block: Block | None,
175
175
  is_memory=False,
176
176
  ) -> Any:
177
177
  try:
@@ -185,14 +185,14 @@ class BlockIOFinder(AILBlockWalkerBase):
185
185
 
186
186
  # pylint: disable=unused-argument
187
187
  def _handle_Load(
188
- self, expr_idx: int, expr: Load, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=True
188
+ self, expr_idx: int, expr: Load, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=True
189
189
  ):
190
190
  load_loc = self._handle_expr(0, expr.addr, stmt_idx, stmt, block, is_memory=True)
191
191
  self._add_or_update_dict(self.derefed_at, stmt_idx, load_loc)
192
192
  return load_loc
193
193
 
194
194
  def _handle_CallExpr(
195
- self, expr_idx: int, expr: Call, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
195
+ self, expr_idx: int, expr: Call, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
196
196
  ):
197
197
  args = set()
198
198
  if expr.args:
@@ -202,7 +202,7 @@ class BlockIOFinder(AILBlockWalkerBase):
202
202
  return args
203
203
 
204
204
  def _handle_BinaryOp(
205
- self, expr_idx: int, expr: BinaryOp, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
205
+ self, expr_idx: int, expr: BinaryOp, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
206
206
  ):
207
207
  input_locs = set()
208
208
  self._add_or_update_set(
@@ -215,17 +215,17 @@ class BlockIOFinder(AILBlockWalkerBase):
215
215
  return input_locs
216
216
 
217
217
  def _handle_UnaryOp(
218
- self, expr_idx: int, expr: UnaryOp, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
218
+ self, expr_idx: int, expr: UnaryOp, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
219
219
  ):
220
220
  return self._handle_expr(0, expr.operand, stmt_idx, stmt, block, is_memory=is_memory)
221
221
 
222
222
  def _handle_Convert(
223
- self, expr_idx: int, expr: Convert, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
223
+ self, expr_idx: int, expr: Convert, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
224
224
  ):
225
225
  return self._handle_expr(expr_idx, expr.operand, stmt_idx, stmt, block, is_memory=is_memory)
226
226
 
227
227
  def _handle_ITE(
228
- self, expr_idx: int, expr: ITE, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
228
+ self, expr_idx: int, expr: ITE, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
229
229
  ):
230
230
  input_locs = set()
231
231
  self._add_or_update_set(
@@ -249,7 +249,7 @@ class BlockIOFinder(AILBlockWalkerBase):
249
249
 
250
250
  # pylint: disable=unused-argument
251
251
  def _handle_Tmp(
252
- self, expr_idx: int, expr: Tmp, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
252
+ self, expr_idx: int, expr: Tmp, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
253
253
  ):
254
254
  if self._as_atom:
255
255
  return None
@@ -258,7 +258,7 @@ class BlockIOFinder(AILBlockWalkerBase):
258
258
 
259
259
  # pylint: disable=unused-argument
260
260
  def _handle_Register(
261
- self, expr_idx: int, expr: Register, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
261
+ self, expr_idx: int, expr: Register, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
262
262
  ):
263
263
  if self._as_atom:
264
264
  return Register(expr.reg_offset, expr.size)
@@ -266,7 +266,7 @@ class BlockIOFinder(AILBlockWalkerBase):
266
266
  return expr
267
267
 
268
268
  def _handle_Const(
269
- self, expr_idx: int, expr: Const, stmt_idx: int, stmt: Statement, block: Optional[Block], is_memory=False
269
+ self, expr_idx: int, expr: Const, stmt_idx: int, stmt: Statement, block: Block | None, is_memory=False
270
270
  ):
271
271
  if self._as_atom:
272
272
  return MemoryLocation(expr.value, expr.size) if is_memory else ConstantSrc(expr.value, expr.size)
@@ -283,7 +283,7 @@ class BlockIOFinder(AILBlockWalkerBase):
283
283
  expr: StackBaseOffset,
284
284
  stmt_idx: int,
285
285
  stmt: Statement,
286
- block: Optional[Block],
286
+ block: Block | None,
287
287
  is_memory=False,
288
288
  ):
289
289
  if self._as_atom:
@@ -1,5 +1,3 @@
1
- from typing import Union, Optional, List, Tuple
2
-
3
1
  import networkx as nx
4
2
  from ailment.block import Block
5
3
  from ailment.statement import Statement, ConditionalJump
@@ -19,7 +17,7 @@ def has_similar_stmt(blk1: Block, blk2: Block):
19
17
 
20
18
 
21
19
  def is_similar(
22
- ail_obj1: Union[Block, Statement], ail_obj2: Union[Block, Statement], graph: nx.DiGraph = None, partial: bool = True
20
+ ail_obj1: Block | Statement, ail_obj2: Block | Statement, graph: nx.DiGraph = None, partial: bool = True
23
21
  ):
24
22
  """
25
23
  Returns True if the two AIL objects are similar, False otherwise.
@@ -128,7 +126,7 @@ def _kmp_search_ail_obj(search_pattern, stmt_seq, graph=None, partial=True):
128
126
  yield start_pos
129
127
 
130
128
 
131
- def index_of_similar_stmts(search_stmts, other_stmts, graph=None, all_positions=False) -> Optional[int]:
129
+ def index_of_similar_stmts(search_stmts, other_stmts, graph=None, all_positions=False) -> int | None:
132
130
  """
133
131
  Returns the index of the first occurrence of the search_stmts (a list of Statement) in other_stmts (a list of
134
132
  Statement). If all_positions is True, returns a list of all positions.
@@ -157,8 +155,8 @@ def in_other(stmts, other, graph=None):
157
155
 
158
156
 
159
157
  def longest_ail_subseq(
160
- stmts_list: List[List[Statement]], graph=None
161
- ) -> Tuple[Optional[List[Statement]], Optional[List[int]]]:
158
+ stmts_list: list[list[Statement]], graph=None
159
+ ) -> tuple[list[Statement] | None, list[int] | None]:
162
160
  """
163
161
  Given a list of List[Statement], it returns the longest List[Statement] that is a subsequence of all the lists.
164
162
  The common List[Statement] most all be in the same order and adjacent to each other. If no common subsequence is
@@ -1,6 +1,7 @@
1
1
  # pylint:disable=too-many-boolean-expressions
2
2
  import logging
3
- from typing import Optional, Union, Type, Iterable, Tuple, Set, TYPE_CHECKING
3
+ from typing import Optional, TYPE_CHECKING
4
+ from collections.abc import Iterable
4
5
 
5
6
  from ailment.statement import Statement, Assignment, Call, Store, Jump
6
7
  from ailment.expression import Tmp, Load, Const, Register, Convert
@@ -60,13 +61,13 @@ class BlockSimplifier(Analysis):
60
61
  def __init__(
61
62
  self,
62
63
  block: Optional["Block"],
63
- func_addr: Optional[int] = None,
64
+ func_addr: int | None = None,
64
65
  remove_dead_memdefs=False,
65
66
  stack_pointer_tracker=None,
66
- peephole_optimizations: Optional[
67
- Iterable[Union[Type[PeepholeOptimizationStmtBase], Type[PeepholeOptimizationExprBase]]]
68
- ] = None,
69
- stack_arg_offsets: Optional[Set[Tuple[int, int]]] = None,
67
+ peephole_optimizations: None | (
68
+ Iterable[type[PeepholeOptimizationStmtBase] | type[PeepholeOptimizationExprBase]]
69
+ ) = None,
70
+ stack_arg_offsets: set[tuple[int, int]] | None = None,
70
71
  cached_reaching_definitions=None,
71
72
  cached_propagator=None,
72
73
  ):
@@ -194,14 +195,14 @@ class BlockSimplifier(Analysis):
194
195
  # propagator
195
196
  if nonconstant_stmts >= 2 and has_propagatable_assignments:
196
197
  propagator = self._compute_propagation(block)
197
- prop_state = list(propagator.model.states.values())[0]
198
- replacements = prop_state._replacements
199
- if replacements:
200
- _, new_block = self._replace_and_build(block, replacements, replace_registers=True)
201
- new_block = self._eliminate_self_assignments(new_block)
202
- self._clear_cache()
203
- else:
204
- new_block = block
198
+ new_block = block
199
+ if propagator.model.states:
200
+ prop_state = list(propagator.model.states.values())[0]
201
+ replacements = prop_state._replacements
202
+ if replacements:
203
+ _, new_block = self._replace_and_build(block, replacements, replace_registers=True)
204
+ new_block = self._eliminate_self_assignments(new_block)
205
+ self._clear_cache()
205
206
  else:
206
207
  # Skipped calling Propagator
207
208
  new_block = block
@@ -218,9 +219,9 @@ class BlockSimplifier(Analysis):
218
219
  replacements,
219
220
  replace_assignment_dsts: bool = False,
220
221
  replace_loads: bool = False,
221
- gp: Optional[int] = None,
222
+ gp: int | None = None,
222
223
  replace_registers: bool = True,
223
- ) -> Tuple[bool, "Block"]:
224
+ ) -> tuple[bool, "Block"]:
224
225
  new_statements = block.statements[::]
225
226
  replaced = False
226
227