angr 9.2.102__py3-none-win_amd64.whl → 9.2.103__py3-none-win_amd64.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 (240) 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 +39 -39
  176. angr/knowledge_plugins/xrefs/xref.py +9 -11
  177. angr/knowledge_plugins/xrefs/xref_manager.py +3 -4
  178. angr/lib/angr_native.dll +0 -0
  179. angr/misc/ansi.py +1 -2
  180. angr/misc/autoimport.py +3 -3
  181. angr/misc/plugins.py +9 -9
  182. angr/procedures/definitions/__init__.py +16 -16
  183. angr/procedures/definitions/linux_kernel.py +1 -1
  184. angr/procedures/definitions/parse_win32json.py +1 -1
  185. angr/procedures/java_jni/__init__.py +1 -1
  186. angr/procedures/java_jni/array_operations.py +1 -2
  187. angr/procedures/java_jni/method_calls.py +1 -2
  188. angr/procedures/posix/inet_ntoa.py +1 -2
  189. angr/procedures/stubs/format_parser.py +3 -3
  190. angr/project.py +13 -11
  191. angr/sim_manager.py +12 -12
  192. angr/sim_procedure.py +7 -3
  193. angr/sim_state.py +2 -2
  194. angr/sim_type.py +60 -45
  195. angr/sim_variable.py +5 -5
  196. angr/simos/simos.py +1 -2
  197. angr/simos/userland.py +1 -2
  198. angr/state_plugins/callstack.py +3 -2
  199. angr/state_plugins/history.py +1 -2
  200. angr/state_plugins/solver.py +34 -34
  201. angr/storage/memory_mixins/__init__.py +4 -3
  202. angr/storage/memory_mixins/actions_mixin.py +1 -3
  203. angr/storage/memory_mixins/address_concretization_mixin.py +1 -3
  204. angr/storage/memory_mixins/convenient_mappings_mixin.py +3 -4
  205. angr/storage/memory_mixins/default_filler_mixin.py +1 -1
  206. angr/storage/memory_mixins/label_merger_mixin.py +2 -2
  207. angr/storage/memory_mixins/multi_value_merger_mixin.py +4 -3
  208. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +9 -8
  209. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +12 -11
  210. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +8 -8
  211. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +2 -3
  212. angr/storage/memory_mixins/paged_memory/pages/list_page.py +10 -11
  213. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +11 -10
  214. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +18 -17
  215. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +12 -11
  216. angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +3 -3
  217. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +3 -2
  218. angr/storage/memory_mixins/regioned_memory/region_data.py +1 -2
  219. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +2 -2
  220. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +3 -3
  221. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +18 -21
  222. angr/storage/memory_mixins/size_resolution_mixin.py +1 -2
  223. angr/storage/memory_mixins/symbolic_merger_mixin.py +3 -2
  224. angr/storage/memory_mixins/top_merger_mixin.py +3 -2
  225. angr/storage/memory_object.py +2 -4
  226. angr/utils/algo.py +3 -2
  227. angr/utils/dynamic_dictlist.py +5 -5
  228. angr/utils/formatting.py +4 -4
  229. angr/utils/funcid.py +1 -2
  230. angr/utils/graph.py +5 -6
  231. angr/utils/library.py +5 -5
  232. angr/utils/mp.py +5 -4
  233. angr/utils/segment_list.py +3 -4
  234. angr/utils/typing.py +3 -2
  235. {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/METADATA +9 -11
  236. {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/RECORD +240 -237
  237. {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/LICENSE +0 -0
  238. {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/WHEEL +0 -0
  239. {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/entry_points.txt +0 -0
  240. {angr-9.2.102.dist-info → angr-9.2.103.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  from collections import defaultdict
3
- from typing import Union, Optional, Sequence, Tuple, Any
3
+ from typing import Union, Any
4
+ from collections.abc import Sequence
4
5
 
5
6
  import pyvex
6
7
  import archinfo
@@ -963,11 +964,11 @@ class Disassembly(Analysis):
963
964
 
964
965
  def __init__(
965
966
  self,
966
- function: Optional[Function] = None,
967
- ranges: Optional[Sequence[Tuple[int, int]]] = None,
967
+ function: Function | None = None,
968
+ ranges: Sequence[tuple[int, int]] | None = None,
968
969
  thumb: bool = False,
969
970
  include_ir: bool = False,
970
- block_bytes: Optional[bytes] = None,
971
+ block_bytes: bytes | None = None,
971
972
  ):
972
973
  self.raw_result = []
973
974
  self.raw_result_map = {
@@ -1156,7 +1157,7 @@ class Disassembly(Analysis):
1156
1157
  show_edges: bool = True,
1157
1158
  show_addresses: bool = True,
1158
1159
  show_bytes: bool = False,
1159
- ascii_only: Optional[bool] = None,
1160
+ ascii_only: bool | None = None,
1160
1161
  color: bool = True,
1161
1162
  ) -> str:
1162
1163
  """
@@ -1188,7 +1189,7 @@ class Disassembly(Analysis):
1188
1189
  "format_callback": lambda item, s: ansi_color(s, formatting["colors"].get(type(item), None)),
1189
1190
  }
1190
1191
 
1191
- def col(item: Any) -> Optional[str]:
1192
+ def col(item: Any) -> str | None:
1192
1193
  try:
1193
1194
  return formatting["colors"][item]
1194
1195
  except KeyError:
angr/analyses/flirt.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import Union, List, Dict, Tuple, TYPE_CHECKING, Optional
1
+ from typing import TYPE_CHECKING
2
2
  from functools import partial
3
3
  from collections import defaultdict
4
4
  import logging
@@ -30,11 +30,11 @@ class FlirtAnalysis(Analysis):
30
30
  current binary, and then match all possible signatures for the architecture.
31
31
  """
32
32
 
33
- def __init__(self, sig: Optional[Union[FlirtSignature, str]] = None):
33
+ def __init__(self, sig: FlirtSignature | str | None = None):
34
34
  self._is_arm = is_arm_arch(self.project.arch)
35
- self._all_suggestions: Dict[str, Dict[str, Dict[int, str]]] = {}
36
- self._suggestions: Dict[int, str] = {}
37
- self.matched_suggestions: Dict[str, Tuple[FlirtSignature, Dict[int, str]]] = {}
35
+ self._all_suggestions: dict[str, dict[str, dict[int, str]]] = {}
36
+ self._suggestions: dict[int, str] = {}
37
+ self.matched_suggestions: dict[str, tuple[FlirtSignature, dict[int, str]]] = {}
38
38
  self._temporary_sig = False
39
39
 
40
40
  if sig:
@@ -64,7 +64,7 @@ class FlirtAnalysis(Analysis):
64
64
  self.signatures = list(self._find_hits_by_strings(mem_regions))
65
65
  _l.debug("Identified %d signatures to apply.", len(self.signatures))
66
66
 
67
- path_to_sig: Dict[str, FlirtSignature] = {}
67
+ path_to_sig: dict[str, FlirtSignature] = {}
68
68
  for sig_ in self.signatures:
69
69
  self._match_all_against_one_signature(sig_)
70
70
  if sig_.sig_name not in self._all_suggestions:
@@ -90,8 +90,8 @@ class FlirtAnalysis(Analysis):
90
90
  )
91
91
  self.matched_suggestions[lib] = (sig_, sig_to_suggestions[max_suggestion_sig_path])
92
92
 
93
- def _find_hits_by_strings(self, regions: List[bytes]) -> List[FlirtSignature]:
94
- library_hits: Dict[str, int] = defaultdict(int)
93
+ def _find_hits_by_strings(self, regions: list[bytes]) -> list[FlirtSignature]:
94
+ library_hits: dict[str, int] = defaultdict(int)
95
95
  for s, libs in STRING_TO_LIBRARIES.items():
96
96
  for region in regions:
97
97
  if s.encode("ascii") in region:
@@ -173,7 +173,7 @@ class FlirtAnalysis(Analysis):
173
173
  func_name = f"unknown_function_{func.addr:x}"
174
174
  self._suggestions[func.addr] = func_name
175
175
 
176
- def _apply_changes(self, library_name: Optional[str], suggestion: Dict[int, str]) -> None:
176
+ def _apply_changes(self, library_name: str | None, suggestion: dict[int, str]) -> None:
177
177
  for func_addr, suggested_name in suggestion.items():
178
178
  func = self.kb.functions.get_by_addr(func_addr)
179
179
  func.name = suggested_name
@@ -1,5 +1,6 @@
1
1
  from collections import defaultdict
2
- from typing import Any, Dict, List, Callable, Optional, Generic, Type, TypeVar, Tuple, Set, TYPE_CHECKING, Union
2
+ from typing import Any, Optional, Generic, TypeVar, TYPE_CHECKING
3
+ from collections.abc import Callable
3
4
 
4
5
  import networkx
5
6
 
@@ -41,7 +42,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
41
42
  order_jobs=False,
42
43
  allow_merging=False,
43
44
  allow_widening=False,
44
- status_callback: Optional[Callable[[Type["ForwardAnalysis"]], Any]] = None,
45
+ status_callback: Callable[[type["ForwardAnalysis"]], Any] | None = None,
45
46
  graph_visitor: "Optional[GraphVisitor[NodeType]]" = None,
46
47
  ):
47
48
  """
@@ -69,15 +70,15 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
69
70
  self._should_abort = False
70
71
 
71
72
  # All remaining jobs
72
- self._job_info_queue: List[JobInfo[JobType, JobKey]] = []
73
+ self._job_info_queue: list[JobInfo[JobType, JobKey]] = []
73
74
 
74
75
  # A map between job key to job. Jobs with the same key will be merged by calling _merge_jobs()
75
- self._job_map: Dict[JobKey, JobInfo[JobType, JobKey]] = {}
76
+ self._job_map: dict[JobKey, JobInfo[JobType, JobKey]] = {}
76
77
 
77
78
  # A mapping between node and its input states
78
- self._input_states: Dict[NodeType, List[AnalysisState]] = defaultdict(list)
79
+ self._input_states: dict[NodeType, list[AnalysisState]] = defaultdict(list)
79
80
  # A mapping between node and its output state
80
- self._output_state: Dict[NodeType, AnalysisState] = {}
81
+ self._output_state: dict[NodeType, AnalysisState] = {}
81
82
 
82
83
  # The graph!
83
84
  # Analysis results (nodes) are stored here
@@ -149,16 +150,16 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
149
150
  def _job_key(self, job: JobType) -> JobKey:
150
151
  raise NotImplementedError("_job_key() is not implemented.")
151
152
 
152
- def _get_successors(self, job: JobType) -> Union[List[SimState], List[JobType]]:
153
+ def _get_successors(self, job: JobType) -> list[SimState] | list[JobType]:
153
154
  raise NotImplementedError("_get_successors() is not implemented.")
154
155
 
155
156
  def _pre_job_handling(self, job: JobType) -> None:
156
157
  raise NotImplementedError("_pre_job_handling() is not implemented.")
157
158
 
158
- def _post_job_handling(self, job: JobType, new_jobs, successors: List[SimState]) -> None:
159
+ def _post_job_handling(self, job: JobType, new_jobs, successors: list[SimState]) -> None:
159
160
  raise NotImplementedError("_post_job_handling() is not implemented.")
160
161
 
161
- def _handle_successor(self, job: JobType, successor: SimState, successors: List[SimState]) -> List[JobType]:
162
+ def _handle_successor(self, job: JobType, successor: SimState, successors: list[SimState]) -> list[JobType]:
162
163
  raise NotImplementedError("_handle_successor() is not implemented.")
163
164
 
164
165
  def _job_queue_empty(self) -> None:
@@ -179,7 +180,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
179
180
  """
180
181
  return node
181
182
 
182
- def _run_on_node(self, node: NodeType, state: AnalysisState) -> Tuple[bool, AnalysisState]:
183
+ def _run_on_node(self, node: NodeType, state: AnalysisState) -> tuple[bool, AnalysisState]:
183
184
  """
184
185
  The analysis routine that runs on each node in the graph.
185
186
 
@@ -197,7 +198,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
197
198
 
198
199
  raise NotImplementedError("_run_on_node() is not implemented.")
199
200
 
200
- def _merge_states(self, node: NodeType, *states: AnalysisState) -> Tuple[AnalysisState, bool]:
201
+ def _merge_states(self, node: NodeType, *states: AnalysisState) -> tuple[AnalysisState, bool]:
201
202
  """
202
203
  Merge multiple abstract states into one.
203
204
 
@@ -311,7 +312,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
311
312
  for succ in successors_to_visit:
312
313
  self._graph_visitor.revisit_node(succ)
313
314
 
314
- def _add_input_state(self, node: NodeType, input_state: AnalysisState) -> Set[NodeType]:
315
+ def _add_input_state(self, node: NodeType, input_state: AnalysisState) -> set[NodeType]:
315
316
  """
316
317
  Add the input state to all successors of the given node.
317
318
 
@@ -334,7 +335,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
334
335
 
335
336
  return successors
336
337
 
337
- def _get_and_update_input_state(self, node: NodeType) -> Optional[AnalysisState]:
338
+ def _get_and_update_input_state(self, node: NodeType) -> AnalysisState | None:
338
339
  """
339
340
  Get the input abstract state for this node, and remove it from the state map.
340
341
 
@@ -348,7 +349,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
348
349
  return input_state
349
350
  return None
350
351
 
351
- def _get_input_state(self, node: NodeType) -> Optional[AnalysisState]:
352
+ def _get_input_state(self, node: NodeType) -> AnalysisState | None:
352
353
  """
353
354
  Get the input abstract state for this node.
354
355
 
@@ -1,4 +1,3 @@
1
- from typing import List, Tuple
2
1
  import logging
3
2
 
4
3
  import networkx
@@ -74,7 +73,7 @@ class FunctionGraphVisitor(GraphVisitor):
74
73
 
75
74
  return sorted_nodes
76
75
 
77
- def back_edges(self) -> List[Tuple[NodeType, NodeType]]:
76
+ def back_edges(self) -> list[tuple[NodeType, NodeType]]:
78
77
  start_nodes = [node for node in self.graph if node.addr == self.function.addr]
79
78
  if not start_nodes:
80
79
  start_nodes = [node for node in self.graph if self.graph.in_degree(node) == 0]
@@ -1,4 +1,5 @@
1
- from typing import TypeVar, Generic, List, Collection, Optional, Iterator, Set, Dict, Tuple
1
+ from typing import TypeVar, Generic
2
+ from collections.abc import Collection, Iterator
2
3
  from collections import defaultdict
3
4
 
4
5
  from ....misc.ux import deprecated
@@ -25,21 +26,21 @@ class GraphVisitor(Generic[NodeType]):
25
26
  )
26
27
 
27
28
  def __init__(self):
28
- self._sorted_nodes: List[NodeType] = [] # a list of sorted nodes. do not change until we get a new graph
29
- self._worklist: List[NodeType] = [] # a list of nodes that the analysis should work on and finally exhaust
30
- self._nodes_set: Set[NodeType] = set()
31
- self._node_to_index: Dict[NodeType, int] = {}
32
- self._reached_fixedpoint: Set[NodeType] = set()
33
- self._back_edges_by_src: Optional[Dict[NodeType, Set[NodeType]]] = None
34
- self._back_edges_by_dst: Optional[Dict[NodeType, Set[NodeType]]] = None
29
+ self._sorted_nodes: list[NodeType] = [] # a list of sorted nodes. do not change until we get a new graph
30
+ self._worklist: list[NodeType] = [] # a list of nodes that the analysis should work on and finally exhaust
31
+ self._nodes_set: set[NodeType] = set()
32
+ self._node_to_index: dict[NodeType, int] = {}
33
+ self._reached_fixedpoint: set[NodeType] = set()
34
+ self._back_edges_by_src: dict[NodeType, set[NodeType]] | None = None
35
+ self._back_edges_by_dst: dict[NodeType, set[NodeType]] | None = None
35
36
 
36
- self._pending_nodes: Dict[NodeType, Set[NodeType]] = defaultdict(set)
37
+ self._pending_nodes: dict[NodeType, set[NodeType]] = defaultdict(set)
37
38
 
38
39
  #
39
40
  # Interfaces
40
41
  #
41
42
 
42
- def successors(self, node: NodeType) -> List[NodeType]:
43
+ def successors(self, node: NodeType) -> list[NodeType]:
43
44
  """
44
45
  Get successors of a node. The node should be in the graph.
45
46
 
@@ -50,7 +51,7 @@ class GraphVisitor(Generic[NodeType]):
50
51
 
51
52
  raise NotImplementedError()
52
53
 
53
- def predecessors(self, node: NodeType) -> List[NodeType]:
54
+ def predecessors(self, node: NodeType) -> list[NodeType]:
54
55
  """
55
56
  Get predecessors of a node. The node should be in the graph.
56
57
 
@@ -60,7 +61,7 @@ class GraphVisitor(Generic[NodeType]):
60
61
 
61
62
  raise NotImplementedError()
62
63
 
63
- def sort_nodes(self, nodes: Optional[Collection[NodeType]] = None) -> List[NodeType]:
64
+ def sort_nodes(self, nodes: Collection[NodeType] | None = None) -> list[NodeType]:
64
65
  """
65
66
  Get a list of all nodes sorted in an optimal traversal order.
66
67
 
@@ -70,7 +71,7 @@ class GraphVisitor(Generic[NodeType]):
70
71
 
71
72
  raise NotImplementedError()
72
73
 
73
- def back_edges(self) -> List[Tuple[NodeType, NodeType]]:
74
+ def back_edges(self) -> list[tuple[NodeType, NodeType]]:
74
75
  """
75
76
  Get a list of back edges. This function is optional. If not overriden, the traverser cannot achieve an optimal
76
77
  graph traversal order.
@@ -122,7 +123,7 @@ class GraphVisitor(Generic[NodeType]):
122
123
 
123
124
  self._populate_back_edges()
124
125
 
125
- def next_node(self) -> Optional[NodeType]:
126
+ def next_node(self) -> NodeType | None:
126
127
  """
127
128
  Get the next node to visit.
128
129
 
@@ -167,7 +168,7 @@ class GraphVisitor(Generic[NodeType]):
167
168
 
168
169
  return node
169
170
 
170
- def all_successors(self, node: NodeType, skip_reached_fixedpoint=False) -> Set[NodeType]:
171
+ def all_successors(self, node: NodeType, skip_reached_fixedpoint=False) -> set[NodeType]:
171
172
  """
172
173
  Returns all successors to the specific node.
173
174
 
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=arguments-differ,arguments-renamed,isinstance-second-argument-not-valid-type
2
- from typing import Optional, Union, Tuple, TYPE_CHECKING
2
+ from typing import Optional, TYPE_CHECKING
3
3
  import logging
4
4
 
5
5
  import claripy
@@ -34,12 +34,12 @@ class SimEnginePropagatorAIL(
34
34
 
35
35
  state: "PropagatorAILState"
36
36
 
37
- def _is_top(self, expr: Union[claripy.ast.Base, Expr.StackBaseOffset]) -> bool:
37
+ def _is_top(self, expr: claripy.ast.Base | Expr.StackBaseOffset) -> bool:
38
38
  if isinstance(expr, Expr.StackBaseOffset):
39
39
  return False
40
40
  return super()._is_top(expr)
41
41
 
42
- def extract_offset_to_sp(self, expr: Union[claripy.ast.Base, Expr.StackBaseOffset]) -> Optional[int]:
42
+ def extract_offset_to_sp(self, expr: claripy.ast.Base | Expr.StackBaseOffset) -> int | None:
43
43
  if isinstance(expr, Expr.StackBaseOffset):
44
44
  return expr.offset
45
45
  elif isinstance(expr, Expr.Expression):
@@ -288,7 +288,7 @@ class SimEnginePropagatorAIL(
288
288
  #
289
289
 
290
290
  # this method exists so that I can annotate the return type
291
- def _expr(self, expr) -> Optional[PropValue]: # pylint:disable=useless-super-delegation
291
+ def _expr(self, expr) -> PropValue | None: # pylint:disable=useless-super-delegation
292
292
  return super()._expr(expr)
293
293
 
294
294
  def _ail_handle_Tmp(self, expr: Expr.Tmp) -> PropValue:
@@ -361,7 +361,7 @@ class SimEnginePropagatorAIL(
361
361
 
362
362
  return PropValue(self.state.top(expr.size * self.arch.byte_width))
363
363
 
364
- def _ail_handle_Register(self, expr: Expr.Register) -> Optional[PropValue]:
364
+ def _ail_handle_Register(self, expr: Expr.Register) -> PropValue | None:
365
365
  self.state: "PropagatorAILState"
366
366
 
367
367
  # Special handling for SP and BP
@@ -527,19 +527,19 @@ class SimEnginePropagatorAIL(
527
527
  bp_as_gpr=self.bp_as_gpr,
528
528
  )
529
529
  elif all_subexprs and None not in all_subexprs and len(all_subexprs) == 1:
530
- # if the expression has been replaced before, we should remove previous replacements
531
- reg_defs = self._reaching_definitions.get_defs(
532
- Register(expr.reg_offset, expr.size), self._codeloc(), OP_BEFORE
533
- )
534
- if len(reg_defs) == 1:
535
- reg_def = next(iter(reg_defs))
536
- else:
537
- reg_def = None
538
- updated_codelocs = self.state.revert_past_replacements(
539
- all_subexprs[0], to_replace=expr, to_replace_def=reg_def
540
- )
541
- # scan through the code locations and recursively remove assignment replacements
542
530
  if self._reaching_definitions is not None:
531
+ # if the expression has been replaced before, we should remove previous replacements
532
+ reg_defs = self._reaching_definitions.get_defs(
533
+ Register(expr.reg_offset, expr.size), self._codeloc(), OP_BEFORE
534
+ )
535
+ if len(reg_defs) == 1:
536
+ reg_def = next(iter(reg_defs))
537
+ else:
538
+ reg_def = None
539
+ updated_codelocs = self.state.revert_past_replacements(
540
+ all_subexprs[0], to_replace=expr, to_replace_def=reg_def
541
+ )
542
+ # scan through the code locations and recursively remove assignment replacements
543
543
  while updated_codelocs:
544
544
  new_updated_codelocs = set()
545
545
  for u_codeloc in updated_codelocs:
@@ -576,7 +576,7 @@ class SimEnginePropagatorAIL(
576
576
 
577
577
  return PropValue.from_value_and_details(self.state.top(expr.bits), expr.size, expr, self._codeloc())
578
578
 
579
- def _ail_handle_Load(self, expr: Expr.Load) -> Optional[PropValue]:
579
+ def _ail_handle_Load(self, expr: Expr.Load) -> PropValue | None:
580
580
  self.state: "PropagatorAILState"
581
581
 
582
582
  addr = self._expr(expr.addr)
@@ -633,6 +633,11 @@ class SimEnginePropagatorAIL(
633
633
  def _ail_handle_Convert(self, expr: Expr.Convert) -> PropValue:
634
634
  o_value = self._expr(expr.operand)
635
635
 
636
+ if not (expr.from_type == Expr.Convert.TYPE_INT and expr.to_type == Expr.Convert.TYPE_INT):
637
+ # we do not support floating-point conversions
638
+ new_value = self.state.top(expr.to_bits)
639
+ return PropValue.from_value_and_details(new_value, expr.size, expr, self._codeloc())
640
+
636
641
  if o_value is None or self.state.is_top(o_value.value):
637
642
  new_value = self.state.top(expr.to_bits)
638
643
  else:
@@ -739,16 +744,14 @@ class SimEnginePropagatorAIL(
739
744
  v = claripy.BVV(expr.value, expr.bits)
740
745
  return PropValue.from_value_and_details(v, expr.size, expr, self._codeloc())
741
746
 
742
- def _ail_handle_DirtyExpression(
743
- self, expr: Expr.DirtyExpression
744
- ) -> Optional[PropValue]: # pylint:disable=no-self-use
747
+ def _ail_handle_DirtyExpression(self, expr: Expr.DirtyExpression) -> PropValue | None: # pylint:disable=no-self-use
745
748
  if isinstance(expr.dirty_expr, Expr.VEXCCallExpression):
746
749
  for operand in expr.dirty_expr.operands:
747
750
  _ = self._expr(operand)
748
751
 
749
752
  return PropValue.from_value_and_details(self.state.top(expr.bits), expr.size, expr, self._codeloc())
750
753
 
751
- def _ail_handle_ITE(self, expr: Expr.ITE) -> Optional[PropValue]:
754
+ def _ail_handle_ITE(self, expr: Expr.ITE) -> PropValue | None:
752
755
  # pylint:disable=unused-variable
753
756
  self._expr(expr.cond) # cond
754
757
  self._expr(expr.iftrue) # iftrue
@@ -756,7 +759,7 @@ class SimEnginePropagatorAIL(
756
759
 
757
760
  return PropValue.from_value_and_details(self.state.top(expr.bits), expr.size, expr, self._codeloc())
758
761
 
759
- def _ail_handle_Reinterpret(self, expr: Expr.Reinterpret) -> Optional[PropValue]:
762
+ def _ail_handle_Reinterpret(self, expr: Expr.Reinterpret) -> PropValue | None:
760
763
  arg = self._expr(expr.operand)
761
764
 
762
765
  if self.state.is_top(arg.value):
@@ -768,7 +771,7 @@ class SimEnginePropagatorAIL(
768
771
 
769
772
  return PropValue.from_value_and_details(arg.value, expr.size, expr, self._codeloc())
770
773
 
771
- def _ail_handle_CallExpr(self, expr_stmt: Stmt.Call) -> Optional[PropValue]:
774
+ def _ail_handle_CallExpr(self, expr_stmt: Stmt.Call) -> PropValue | None:
772
775
  if isinstance(expr_stmt.target, Expr.Expression):
773
776
  _ = self._expr(expr_stmt.target)
774
777
 
@@ -847,6 +850,7 @@ class SimEnginePropagatorAIL(
847
850
  _ail_handle_CmpGTs = _ail_handle_Cmp
848
851
  _ail_handle_CmpEQ = _ail_handle_Cmp
849
852
  _ail_handle_CmpNE = _ail_handle_Cmp
853
+ _ail_handle_CmpORD = _ail_handle_Cmp
850
854
 
851
855
  def _ail_handle_Add(self, expr: Expr.BinaryOp) -> PropValue:
852
856
  o0_value = self._expr(expr.operands[0])
@@ -1492,8 +1496,8 @@ class SimEnginePropagatorAIL(
1492
1496
  expr: Expr.Expression,
1493
1497
  expr_defat: Optional["CodeLocation"],
1494
1498
  current_loc: "CodeLocation",
1495
- avoid: Optional[Expr.Expression] = None,
1496
- ) -> Tuple[bool, bool]:
1499
+ avoid: Expr.Expression | None = None,
1500
+ ) -> tuple[bool, bool]:
1497
1501
  if self._reaching_definitions is None:
1498
1502
  l.warning(
1499
1503
  "Reaching definition information is not provided to propagator. Assume the definition is out-dated."
@@ -1,5 +1,6 @@
1
1
  # pylint:disable=consider-using-in
2
- from typing import Optional, Callable, TYPE_CHECKING
2
+ from typing import TYPE_CHECKING
3
+ from collections.abc import Callable
3
4
 
4
5
  from ailment import Block, Stmt, Expr, AILBlockWalker
5
6
 
@@ -25,7 +26,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
25
26
  current_loc: CodeLocation,
26
27
  state: "PropagatorAILState",
27
28
  arch: "Arch",
28
- avoid: Optional[Expr.Expression] = None,
29
+ avoid: Expr.Expression | None = None,
29
30
  extract_offset_to_sp: Callable = None,
30
31
  rda: "ReachingDefinitionsModel" = None,
31
32
  ):
@@ -46,13 +47,13 @@ class OutdatedDefinitionWalker(AILBlockWalker):
46
47
  self.rda = rda
47
48
 
48
49
  # pylint:disable=unused-argument
49
- def _handle_Tmp(self, expr_idx: int, expr: Expr.Tmp, stmt_idx: int, stmt: Stmt.Assignment, block: Optional[Block]):
50
+ def _handle_Tmp(self, expr_idx: int, expr: Expr.Tmp, stmt_idx: int, stmt: Stmt.Assignment, block: Block | None):
50
51
  if self.avoid is not None and expr.likes(self.avoid):
51
52
  self.has_avoid = True
52
53
 
53
54
  # pylint:disable=unused-argument
54
55
  def _handle_Register(
55
- self, expr_idx: int, expr: Expr.Register, stmt_idx: int, stmt: Stmt.Assignment, block: Optional[Block]
56
+ self, expr_idx: int, expr: Expr.Register, stmt_idx: int, stmt: Stmt.Assignment, block: Block | None
56
57
  ):
57
58
  if (
58
59
  self.avoid is not None
@@ -70,7 +71,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
70
71
  if not (codelocs_defat and codelocs_currentloc and codelocs_defat == codelocs_currentloc):
71
72
  self.out_dated = True
72
73
 
73
- def _handle_Load(self, expr_idx: int, expr: Expr.Load, stmt_idx: int, stmt: Stmt.Statement, block: Optional[Block]):
74
+ def _handle_Load(self, expr_idx: int, expr: Expr.Load, stmt_idx: int, stmt: Stmt.Statement, block: Block | None):
74
75
  if self.avoid is not None and (expr == self.avoid or expr.addr == self.avoid):
75
76
  self.has_avoid = True
76
77
 
@@ -131,7 +132,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
131
132
  self.out_dated = True
132
133
 
133
134
  def _handle_VEXCCallExpression(
134
- self, expr_idx: int, expr: Expr.VEXCCallExpression, stmt_idx: int, stmt: Stmt.Statement, block: Optional[Block]
135
+ self, expr_idx: int, expr: Expr.VEXCCallExpression, stmt_idx: int, stmt: Stmt.Statement, block: Block | None
135
136
  ):
136
137
  if self.avoid is not None:
137
138
  if any(op == self.avoid for op in expr.operands):
@@ -148,7 +149,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
148
149
  return False
149
150
 
150
151
  @staticmethod
151
- def _check_store_precedes_load(store_defat: Optional[CodeLocation], load_defat: Optional[CodeLocation]) -> bool:
152
+ def _check_store_precedes_load(store_defat: CodeLocation | None, load_defat: CodeLocation | None) -> bool:
152
153
  """
153
154
  Check if store precedes load based on their AIL statement IDs.
154
155
  """
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=isinstance-second-argument-not-valid-type
2
- from typing import Optional, Any, Tuple, Union, Set, TYPE_CHECKING
2
+ from typing import Optional, Any, TYPE_CHECKING
3
3
  import logging
4
4
  import time
5
5
 
@@ -61,10 +61,10 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
61
61
  do_binops=True,
62
62
  store_tops=True,
63
63
  vex_cross_insn_opt=False,
64
- func_addr: Optional[int] = None,
65
- gp: Optional[int] = None,
64
+ func_addr: int | None = None,
65
+ gp: int | None = None,
66
66
  cache_results: bool = False,
67
- key_prefix: Optional[str] = None,
67
+ key_prefix: str | None = None,
68
68
  reaching_definitions: Optional["ReachingDefinitionsModel"] = None,
69
69
  immediate_stmt_removal: bool = False,
70
70
  profiling: bool = False,
@@ -103,7 +103,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
103
103
  self._cache_results = cache_results
104
104
  self._reaching_definitions = reaching_definitions
105
105
  self._initial_codeloc: CodeLocation
106
- self.stmts_to_remove: Set[CodeLocation] = set()
106
+ self.stmts_to_remove: set[CodeLocation] = set()
107
107
  if self.flavor == "function":
108
108
  self._initial_codeloc = CodeLocation(self._func_addr, stmt_idx=0, ins_addr=self._func_addr)
109
109
  else: # flavor == "block"
@@ -124,11 +124,11 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
124
124
  else:
125
125
  cache_used = True
126
126
 
127
- graph_visitor: Union[visitors.SingleNodeGraphVisitor, visitors.FunctionGraphVisitor]
127
+ graph_visitor: visitors.SingleNodeGraphVisitor | visitors.FunctionGraphVisitor
128
128
  if self.flavor == "block":
129
129
  graph_visitor = None
130
130
  if self._cache_results:
131
- graph_visitor: Optional[visitors.SingleNodeGraphVisitor] = self.model.graph_visitor
131
+ graph_visitor: visitors.SingleNodeGraphVisitor | None = self.model.graph_visitor
132
132
 
133
133
  if graph_visitor is None:
134
134
  graph_visitor = visitors.SingleNodeGraphVisitor(block)
@@ -136,7 +136,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
136
136
  elif self.flavor == "function":
137
137
  graph_visitor = None
138
138
  if self._cache_results:
139
- graph_visitor: Optional[visitors.FunctionGraphVisitor] = self.model.graph_visitor
139
+ graph_visitor: visitors.FunctionGraphVisitor | None = self.model.graph_visitor
140
140
  if graph_visitor is not None:
141
141
  # resume
142
142
  resumed = graph_visitor.resume_with_new_graph(func_graph if func_graph is not None else func.graph)
@@ -209,7 +209,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
209
209
  _l.warning(" Analyzed statements: %d", self._analyzed_statements)
210
210
 
211
211
  @property
212
- def prop_key(self) -> Tuple[Optional[str], str, int, bool, bool, bool]:
212
+ def prop_key(self) -> tuple[str | None, str, int, bool, bool, bool]:
213
213
  """
214
214
  Gets a key that represents the function and the "flavor" of the propagation result.
215
215
  """
@@ -228,7 +228,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
228
228
  # Main analysis routines
229
229
  #
230
230
 
231
- def _node_key(self, node: Union[ailment.Block, pyvex.IRSB]) -> Any:
231
+ def _node_key(self, node: ailment.Block | pyvex.IRSB) -> Any:
232
232
  if type(node) is ailment.Block:
233
233
  return node.addr, node.idx
234
234
  elif type(node) is pyvex.IRSB:
@@ -327,9 +327,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
327
327
  else:
328
328
  return False, state
329
329
 
330
- def _process_input_state_for_successor(
331
- self, node, successor, input_state: Union[PropagatorAILState, PropagatorVEXState]
332
- ):
330
+ def _process_input_state_for_successor(self, node, successor, input_state: PropagatorAILState | PropagatorVEXState):
333
331
  if self._only_consts:
334
332
  if isinstance(input_state, PropagatorAILState):
335
333
  key = node.addr, successor.addr