angr 9.2.101__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 +56 -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.101.dist-info → angr-9.2.103.dist-info}/METADATA +9 -11
  236. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/RECORD +240 -237
  237. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/LICENSE +0 -0
  238. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/WHEEL +0 -0
  239. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/entry_points.txt +0 -0
  240. {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ import logging
4
4
  import math
5
5
  import re
6
6
  import string
7
- from typing import DefaultDict, List, Set, Dict, Optional, Tuple
7
+ from typing import DefaultDict
8
8
  from collections import defaultdict, OrderedDict
9
9
  from enum import Enum, unique
10
10
 
@@ -153,7 +153,7 @@ class PendingJobs:
153
153
 
154
154
  __nonzero__ = __bool__
155
155
 
156
- def _pop_job(self, func_addr: Optional[int]):
156
+ def _pop_job(self, func_addr: int | None):
157
157
  jobs = self._jobs[func_addr]
158
158
  j = jobs.pop(-1)
159
159
  if not jobs:
@@ -457,16 +457,16 @@ class CFGJob:
457
457
  addr: int,
458
458
  func_addr: int,
459
459
  jumpkind: str,
460
- ret_target: Optional[int] = None,
461
- last_addr: Optional[int] = None,
462
- src_node: Optional[CFGNode] = None,
463
- src_ins_addr: Optional[int] = None,
464
- src_stmt_idx: Optional[int] = None,
460
+ ret_target: int | None = None,
461
+ last_addr: int | None = None,
462
+ src_node: CFGNode | None = None,
463
+ src_ins_addr: int | None = None,
464
+ src_stmt_idx: int | None = None,
465
465
  returning_source=None,
466
466
  syscall: bool = False,
467
- func_edges: Optional[List] = None,
467
+ func_edges: list | None = None,
468
468
  job_type: CFGJobType = CFGJobType.NORMAL,
469
- gp: Optional[int] = None,
469
+ gp: int | None = None,
470
470
  ):
471
471
  self.addr = addr
472
472
  self.func_addr = func_addr
@@ -615,8 +615,8 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
615
615
  nodecode_window_size=512,
616
616
  nodecode_threshold=0.3,
617
617
  nodecode_step=16483,
618
- indirect_calls_always_return: Optional[bool] = None,
619
- jumptable_resolver_resolves_calls: Optional[bool] = None,
618
+ indirect_calls_always_return: bool | None = None,
619
+ jumptable_resolver_resolves_calls: bool | None = None,
620
620
  start=None, # deprecated
621
621
  end=None, # deprecated
622
622
  collect_data_references=None, # deprecated
@@ -808,7 +808,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
808
808
  self._known_thunks = {}
809
809
 
810
810
  self._initial_state = None
811
- self._next_addr: Optional[int] = None
811
+ self._next_addr: int | None = None
812
812
 
813
813
  # Create the segment list
814
814
  self._seg_list = SegmentList()
@@ -828,10 +828,10 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
828
828
  self._traced_addresses = None
829
829
  self._function_returns = None
830
830
  self._function_exits = None
831
- self._gp_value: Optional[int] = None
832
- self._ro_region_cdata_cache: Optional[List] = None
831
+ self._gp_value: int | None = None
832
+ self._ro_region_cdata_cache: list | None = None
833
833
  self._job_ctr = 0
834
- self._decoding_assumptions: Dict[int, DecodingAssumption] = {}
834
+ self._decoding_assumptions: dict[int, DecodingAssumption] = {}
835
835
  self._decoding_assumption_relations = None
836
836
 
837
837
  # A mapping between address and the actual data in memory
@@ -1174,7 +1174,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1174
1174
 
1175
1175
  return nodecode_bytes / total_bytes
1176
1176
 
1177
- def _next_code_addr_smart(self) -> Optional[int]:
1177
+ def _next_code_addr_smart(self) -> int | None:
1178
1178
  # in the smart scanning mode, if there are more than N consecutive no-decode cases, we skip an entire window of
1179
1179
  # bytes.
1180
1180
  nodecode_bytes_ratio = (
@@ -1215,7 +1215,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1215
1215
 
1216
1216
  # Initialize variables used during analysis
1217
1217
  self._pending_jobs: PendingJobs = PendingJobs(self.functions, self._deregister_analysis_job)
1218
- self._traced_addresses: Set[int] = {a for a, n in self._nodes_by_addr.items() if n}
1218
+ self._traced_addresses: set[int] = {a for a, n in self._nodes_by_addr.items() if n}
1219
1219
  self._function_returns = defaultdict(set)
1220
1220
 
1221
1221
  # Populate known objects in segment tracker
@@ -1230,7 +1230,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1230
1230
  # should record all exits from a single function, and then add
1231
1231
  # necessary calling edges in our call map during the post-processing
1232
1232
  # phase.
1233
- self._function_exits: DefaultDict[int, Set[int]] = defaultdict(set)
1233
+ self._function_exits: DefaultDict[int, set[int]] = defaultdict(set)
1234
1234
 
1235
1235
  # Create an initial state. Store it to self so we can use it globally.
1236
1236
  self._initial_state = self.project.factory.blank_state(
@@ -1245,7 +1245,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1245
1245
  if self._use_exceptions:
1246
1246
  self._preprocess_exception_handlings()
1247
1247
 
1248
- starting_points: Set[int] = set()
1248
+ starting_points: set[int] = set()
1249
1249
 
1250
1250
  if self._use_symbols:
1251
1251
  starting_points |= self._function_addresses_from_symbols
@@ -1257,7 +1257,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1257
1257
  starting_points |= set(self._extra_function_starts)
1258
1258
 
1259
1259
  # Sort it
1260
- sorted_starting_points: List[int] = sorted(list(starting_points), reverse=False)
1260
+ sorted_starting_points: list[int] = sorted(list(starting_points), reverse=False)
1261
1261
 
1262
1262
  if self._start_at_entry and self.project.entry is not None and self._inside_regions(self.project.entry):
1263
1263
  if self.project.entry not in starting_points:
@@ -1281,7 +1281,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1281
1281
  self._remaining_function_prologue_addrs = sorted(self._func_addrs_from_prologues())
1282
1282
 
1283
1283
  # assumption management
1284
- self._decoding_assumptions: Dict[int, DecodingAssumption] = {}
1284
+ self._decoding_assumptions: dict[int, DecodingAssumption] = {}
1285
1285
  self._decoding_assumption_relations = networkx.DiGraph()
1286
1286
 
1287
1287
  # register read-only regions to PyVEX
@@ -1329,7 +1329,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1329
1329
  def _intra_analysis(self):
1330
1330
  pass
1331
1331
 
1332
- def _get_successors(self, job: CFGJob) -> List[CFGJob]: # type: ignore[override] # pylint:disable=arguments-differ
1332
+ def _get_successors(self, job: CFGJob) -> list[CFGJob]: # type: ignore[override] # pylint:disable=arguments-differ
1333
1333
  # current_function_addr = job.func_addr
1334
1334
  # addr = job.addr
1335
1335
 
@@ -1412,7 +1412,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1412
1412
  func = self.kb.functions.get_by_addr(func_addr)
1413
1413
  if func.is_plt or func.is_simprocedure or func.is_syscall:
1414
1414
  return
1415
- if not (1 <= len(func.block_addrs_set) < 15):
1415
+ if not (9 <= len(func.block_addrs_set) < 12):
1416
1416
  return
1417
1417
 
1418
1418
  from angr.analyses.decompiler.clinic import ClinicMode # pylint:disable=wrong-import-position
@@ -1759,7 +1759,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1759
1759
  UPDATE_RATIO = 0.5
1760
1760
 
1761
1761
  all_memory_data = sorted(list(self.model.memory_data.items()), key=lambda x: x[0]) # sorted by addr
1762
- to_update: Dict[int, bytes] = {}
1762
+ to_update: dict[int, bytes] = {}
1763
1763
  total_string_refs: int = 0
1764
1764
  for i, (addr, md) in enumerate(all_memory_data):
1765
1765
  if not md.sort == MemoryDataSort.String:
@@ -1862,7 +1862,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1862
1862
 
1863
1863
  # Basic block scanning
1864
1864
 
1865
- def _scan_block(self, cfg_job: CFGJob) -> List[CFGJob]:
1865
+ def _scan_block(self, cfg_job: CFGJob) -> list[CFGJob]:
1866
1866
  """
1867
1867
  Scan a basic block starting at a specific address
1868
1868
 
@@ -1889,7 +1889,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1889
1889
 
1890
1890
  return entries
1891
1891
 
1892
- def _scan_procedure(self, cfg_job, current_func_addr) -> List[CFGJob]:
1892
+ def _scan_procedure(self, cfg_job, current_func_addr) -> list[CFGJob]:
1893
1893
  """
1894
1894
  Checks the hooking procedure for this address searching for new static
1895
1895
  exit points to add to successors (generating entries for them)
@@ -1945,7 +1945,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1945
1945
  # Mark the address as traced
1946
1946
  self._traced_addresses.add(addr)
1947
1947
 
1948
- entries: List[CFGJob] = []
1948
+ entries: list[CFGJob] = []
1949
1949
 
1950
1950
  if (
1951
1951
  cfg_job.src_node is not None
@@ -2020,7 +2020,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2020
2020
 
2021
2021
  return entries
2022
2022
 
2023
- def _scan_irsb(self, cfg_job, current_func_addr) -> List[CFGJob]:
2023
+ def _scan_irsb(self, cfg_job, current_func_addr) -> list[CFGJob]:
2024
2024
  """
2025
2025
  Generate a list of successors (generating them each as entries) to IRSB.
2026
2026
  Updates previous CFG nodes with edges.
@@ -2161,7 +2161,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2161
2161
 
2162
2162
  def _create_jobs(
2163
2163
  self, target, jumpkind, current_function_addr, irsb, addr, cfg_node, ins_addr, stmt_idx
2164
- ) -> List[CFGJob]:
2164
+ ) -> list[CFGJob]:
2165
2165
  """
2166
2166
  Given a node and details of a successor, makes a list of CFGJobs
2167
2167
  and if it is a call or exit marks it appropriately so in the CFG
@@ -2176,7 +2176,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2176
2176
  :param int stmt_idx: ID of the source statement.
2177
2177
  :return: a list of CFGJobs
2178
2178
  """
2179
- target_addr: Optional[int]
2179
+ target_addr: int | None
2180
2180
  if type(target) is pyvex.IRExpr.Const: # pylint: disable=unidiomatic-typecheck
2181
2181
  target_addr = target.con.value
2182
2182
  elif type(target) in (
@@ -2201,7 +2201,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2201
2201
  else:
2202
2202
  raise AngrCFGError("This shouldn't be possible")
2203
2203
 
2204
- jobs: List[CFGJob] = []
2204
+ jobs: list[CFGJob] = []
2205
2205
  is_syscall = jumpkind.startswith("Ijk_Sys")
2206
2206
 
2207
2207
  # Special handling:
@@ -2410,10 +2410,10 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2410
2410
  stmt_idx: int,
2411
2411
  ins_addr: int,
2412
2412
  current_function_addr: int,
2413
- target_addr: Optional[int],
2413
+ target_addr: int | None,
2414
2414
  jumpkind: str,
2415
2415
  is_syscall: bool = False,
2416
- ) -> List[CFGJob]:
2416
+ ) -> list[CFGJob]:
2417
2417
  """
2418
2418
  Generate a CFGJob for target address, also adding to _pending_entries
2419
2419
  if returning to succeeding position (if irsb arg is populated)
@@ -2430,7 +2430,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2430
2430
  :return: A list of CFGJobs
2431
2431
  """
2432
2432
 
2433
- jobs: List[CFGJob] = []
2433
+ jobs: list[CFGJob] = []
2434
2434
 
2435
2435
  if is_syscall:
2436
2436
  # Fix the target_addr for syscalls
@@ -2531,7 +2531,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2531
2531
  if callee_might_return:
2532
2532
  func_edges = []
2533
2533
  if return_site is not None:
2534
- call_returning: Optional[bool]
2534
+ call_returning: bool | None
2535
2535
  if callee_function is not None:
2536
2536
  call_returning = self._is_call_returning(cfg_node, callee_function.addr)
2537
2537
  else:
@@ -2899,8 +2899,8 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2899
2899
  stmt_idx: int,
2900
2900
  insn_addr: int,
2901
2901
  data_addr: int,
2902
- data_size: Optional[int] = None,
2903
- data_type: Optional[MemoryDataSort] = None,
2902
+ data_size: int | None = None,
2903
+ data_type: MemoryDataSort | None = None,
2904
2904
  ) -> None:
2905
2905
  """
2906
2906
  Checks addresses are in the correct segments and creates or updates
@@ -2995,7 +2995,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
2995
2995
 
2996
2996
  return False
2997
2997
 
2998
- def _indirect_jump_resolved(self, jump: IndirectJump, jump_addr, resolved_by, targets: List[int]):
2998
+ def _indirect_jump_resolved(self, jump: IndirectJump, jump_addr, resolved_by, targets: list[int]):
2999
2999
  """
3000
3000
  Called when an indirect jump is successfully resolved.
3001
3001
 
@@ -3546,7 +3546,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
3546
3546
 
3547
3547
  del self._function_returns[nonreturning_function.addr]
3548
3548
 
3549
- def _pop_pending_job(self, returning=True) -> Optional[CFGJob]:
3549
+ def _pop_pending_job(self, returning=True) -> CFGJob | None:
3550
3550
  while self._pending_jobs:
3551
3551
  job = self._pending_jobs.pop_job(returning=returning)
3552
3552
  if job is not None and job.job_type == CFGJobType.DATAREF_HINTS and self._seg_list.is_occupied(job.addr):
@@ -3563,7 +3563,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
3563
3563
  #
3564
3564
 
3565
3565
  def _graph_add_edge(
3566
- self, cfg_node: CFGNode, src_node: Optional[CFGNode], src_jumpkind: str, src_ins_addr: int, src_stmt_idx: int
3566
+ self, cfg_node: CFGNode, src_node: CFGNode | None, src_jumpkind: str, src_ins_addr: int, src_stmt_idx: int
3567
3567
  ):
3568
3568
  """
3569
3569
  Add edge between nodes, or add node if entry point
@@ -4061,7 +4061,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
4061
4061
  # Initial registers
4062
4062
  #
4063
4063
 
4064
- def _get_initial_registers(self, addr, cfg_job, current_function_addr) -> Optional[List[Tuple[int, int, int]]]:
4064
+ def _get_initial_registers(self, addr, cfg_job, current_function_addr) -> list[tuple[int, int, int]] | None:
4065
4065
  initial_regs = None
4066
4066
  if self.project.arch.name in {"MIPS64", "MIPS32"}:
4067
4067
  initial_regs = [
@@ -4533,7 +4533,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
4533
4533
  return None, None, None, None
4534
4534
 
4535
4535
  def _process_block_arch_specific(
4536
- self, addr: int, cfg_node: CFGNode, irsb: pyvex.IRSB, func_addr: int, caller_gp: Optional[int] = None
4536
+ self, addr: int, cfg_node: CFGNode, irsb: pyvex.IRSB, func_addr: int, caller_gp: int | None = None
4537
4537
  ) -> None: # pylint: disable=unused-argument
4538
4538
  """
4539
4539
  According to arch types ['ARMEL', 'ARMHF', 'MIPS32', 'X86'] does different
@@ -4704,7 +4704,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
4704
4704
  func = self.kb.functions.get_by_addr(func_addr)
4705
4705
  func.info["bp_as_gpr"] = rbp_as_gpr
4706
4706
 
4707
- def _extract_node_cluster_by_dependency(self, addr, include_successors=False) -> Set[int]:
4707
+ def _extract_node_cluster_by_dependency(self, addr, include_successors=False) -> set[int]:
4708
4708
  to_remove = {addr}
4709
4709
  queue = [addr]
4710
4710
  while queue:
@@ -4840,7 +4840,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
4840
4840
  # the ARM node and the THUMB node no longer exist.
4841
4841
  self._traced_addresses.discard(assumption.addr)
4842
4842
 
4843
- def _mips_determine_function_gp(self, addr: int, irsb: pyvex.IRSB, func_addr: int) -> Optional[int]:
4843
+ def _mips_determine_function_gp(self, addr: int, irsb: pyvex.IRSB, func_addr: int) -> int | None:
4844
4844
  # check if gp is being written to
4845
4845
  last_gp_setting_insn_id = None
4846
4846
  insn_ctr = 0
@@ -4900,7 +4900,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
4900
4900
 
4901
4901
  return result
4902
4902
 
4903
- def _x86_gcc_pie_find_pc_register_adjustment(self, addr: int, reg_offset: int) -> Optional[int]:
4903
+ def _x86_gcc_pie_find_pc_register_adjustment(self, addr: int, reg_offset: int) -> int | None:
4904
4904
  """
4905
4905
  Match against a single instruction that adds or subtracts a constant from a specified register.
4906
4906
 
@@ -4958,7 +4958,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
4958
4958
  return stmt2.data.args[1].con.value
4959
4959
  return None
4960
4960
 
4961
- def _is_call_returning(self, callsite_cfgnode: CFGNode, callee_func_addr: int) -> Optional[bool]:
4961
+ def _is_call_returning(self, callsite_cfgnode: CFGNode, callee_func_addr: int) -> bool | None:
4962
4962
  """
4963
4963
  Determine if a function call is returning or not, with a special care for DYNAMIC_RET functions.
4964
4964
 
@@ -1,7 +1,6 @@
1
1
  import logging
2
2
 
3
3
  from collections import defaultdict
4
- from typing import List
5
4
 
6
5
  from sortedcontainers import SortedDict
7
6
  from copy import copy
@@ -380,7 +379,7 @@ class CFGFastSoot(CFGFast):
380
379
 
381
380
  return stmts_count
382
381
 
383
- def _scan_block(self, cfg_job) -> List[CFGJob]:
382
+ def _scan_block(self, cfg_job) -> list[CFGJob]:
384
383
  """
385
384
  Scan a basic block starting at a specific address
386
385
 
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import TYPE_CHECKING, Optional
2
+ from typing import TYPE_CHECKING
3
3
 
4
4
  from archinfo.arch_soot import SootAddressDescriptor
5
5
 
@@ -131,7 +131,7 @@ class CFGJobBase:
131
131
  src_block_id=None,
132
132
  src_exit_stmt_idx=None,
133
133
  src_ins_addr=None,
134
- jumpkind: Optional[str] = None,
134
+ jumpkind: str | None = None,
135
135
  call_stack=None,
136
136
  is_narrowing=False,
137
137
  skip=False,
@@ -1,6 +1,7 @@
1
1
  # pylint:disable=wrong-import-position,wrong-import-order
2
2
  import enum
3
- from typing import Tuple, Optional, Dict, Sequence, Set, List, TYPE_CHECKING
3
+ from typing import TYPE_CHECKING
4
+ from collections.abc import Sequence
4
5
  import logging
5
6
  import functools
6
7
  from collections import defaultdict, OrderedDict
@@ -75,7 +76,7 @@ class AddressTransformation:
75
76
  Describe and record an address transformation operation.
76
77
  """
77
78
 
78
- def __init__(self, op: AddressTransformationTypes, operands: List, first_load: bool = False):
79
+ def __init__(self, op: AddressTransformationTypes, operands: list, first_load: bool = False):
79
80
  self.op = op
80
81
  self.operands = operands
81
82
  self.first_load = first_load
@@ -295,7 +296,7 @@ class JumpTableProcessor(
295
296
  not be able to recover all jump targets later in block 0x4051b0.
296
297
  """
297
298
 
298
- def __init__(self, project, indirect_jump_node_pred_addrs: Set[int], bp_sp_diff=0x100):
299
+ def __init__(self, project, indirect_jump_node_pred_addrs: set[int], bp_sp_diff=0x100):
299
300
  super().__init__()
300
301
  self.project = project
301
302
  self._bp_sp_diff = bp_sp_diff # bp - sp
@@ -303,7 +304,7 @@ class JumpTableProcessor(
303
304
  self._indirect_jump_node_pred_addrs = indirect_jump_node_pred_addrs
304
305
 
305
306
  self._SPOFFSET_BASE = claripy.BVS("SpOffset", self.project.arch.bits, explicit_name=True)
306
- self._REGOFFSET_BASE: Dict[int, claripy.ast.BV] = {}
307
+ self._REGOFFSET_BASE: dict[int, claripy.ast.BV] = {}
307
308
 
308
309
  def _top(self, size: int):
309
310
  return None
@@ -320,7 +321,7 @@ class JumpTableProcessor(
320
321
  return v
321
322
 
322
323
  @staticmethod
323
- def _extract_spoffset_from_expr(expr: claripy.ast.Base) -> Optional[SpOffset]:
324
+ def _extract_spoffset_from_expr(expr: claripy.ast.Base) -> SpOffset | None:
324
325
  if expr.op == "BVS":
325
326
  for anno in expr.annotations:
326
327
  if isinstance(anno, RegOffsetAnnotation):
@@ -351,7 +352,7 @@ class JumpTableProcessor(
351
352
  return v
352
353
 
353
354
  @staticmethod
354
- def _extract_regoffset_from_expr(expr: claripy.ast.Base) -> Optional[RegisterOffset]:
355
+ def _extract_regoffset_from_expr(expr: claripy.ast.Base) -> RegisterOffset | None:
355
356
  if expr.op == "BVS":
356
357
  for anno in expr.annotations:
357
358
  if isinstance(anno, RegOffsetAnnotation):
@@ -902,10 +903,10 @@ class JumpTableResolver(IndirectJumpResolver):
902
903
  addr: int,
903
904
  func: "Function",
904
905
  b: Blade,
905
- cv_manager: Optional[ConstantValueManager],
906
+ cv_manager: ConstantValueManager | None,
906
907
  potential_call_table: bool = False,
907
908
  func_graph_complete: bool = True,
908
- ) -> Tuple[bool, Optional[Sequence[int]]]:
909
+ ) -> tuple[bool, Sequence[int] | None]:
909
910
  """
910
911
  Internal method for resolving jump tables.
911
912
 
@@ -1173,7 +1174,7 @@ class JumpTableResolver(IndirectJumpResolver):
1173
1174
  # initialization
1174
1175
  load_stmt_loc, load_stmt, load_size = None, None, None
1175
1176
  stmts_to_remove = [stmt_loc]
1176
- stmts_adding_base_addr: List[JumpTargetBaseAddr] = []
1177
+ stmts_adding_base_addr: list[JumpTargetBaseAddr] = []
1177
1178
  # All temporary variables that hold indirect addresses loaded out of the memory
1178
1179
  # Obviously, load_stmt.tmp must be here
1179
1180
  # if there are additional data transferring statements between the Load statement and the base-address-adding
@@ -1189,7 +1190,7 @@ class JumpTableResolver(IndirectJumpResolver):
1189
1190
  # all_addr_holders will be {(0x4c64c4, 11): (AddressTransferringTypes.SignedExtension, 32, 64,),
1190
1191
  # (0x4c64c4, 12); (AddressTransferringTypes.Assignment,),
1191
1192
  # }
1192
- transformations: Dict[Tuple[int, int], AddressTransformation] = OrderedDict()
1193
+ transformations: dict[tuple[int, int], AddressTransformation] = OrderedDict()
1193
1194
 
1194
1195
  initial_block_addr = stmt_loc[0]
1195
1196
  all_load_stmts = sorted(self._all_qualified_load_stmts_in_slice(b, stmt_loc[0]))
@@ -1480,7 +1481,7 @@ class JumpTableResolver(IndirectJumpResolver):
1480
1481
 
1481
1482
  return load_stmt_loc, load_stmt, load_size, stmts_to_remove, stmts_adding_base_addr, transformations
1482
1483
 
1483
- def _find_load_pc_ite_statement(self, b: Blade, stmt_loc: Tuple[int, int]):
1484
+ def _find_load_pc_ite_statement(self, b: Blade, stmt_loc: tuple[int, int]):
1484
1485
  """
1485
1486
  Find the location of the final ITE statement that loads indirect jump targets into a tmp.
1486
1487
 
@@ -1658,7 +1659,7 @@ class JumpTableResolver(IndirectJumpResolver):
1658
1659
  load_stmt,
1659
1660
  load_size,
1660
1661
  stmts_adding_base_addr,
1661
- transformations: Dict[Tuple[int, int], AddressTransformation],
1662
+ transformations: dict[tuple[int, int], AddressTransformation],
1662
1663
  potential_call_table: bool = False,
1663
1664
  ):
1664
1665
  """
@@ -2302,7 +2303,7 @@ class JumpTableResolver(IndirectJumpResolver):
2302
2303
  or self.project.loader.find_section_containing(addr) is not None
2303
2304
  )
2304
2305
 
2305
- def _all_qualified_load_stmts_in_slice(self, b: Blade, addr: int) -> List[int]:
2306
+ def _all_qualified_load_stmts_in_slice(self, b: Blade, addr: int) -> list[int]:
2306
2307
  """
2307
2308
  Recognize all qualified load statements in a slice. A qualified load statements refers to those that are
2308
2309
  loading jump targets (or jump offsets) from a jump table, or loading jump table offsets from a jump-table
@@ -1,5 +1,5 @@
1
1
  # pylint:disable=too-many-boolean-expressions,global-statement
2
- from typing import Dict, Optional, Tuple, TYPE_CHECKING
2
+ from typing import TYPE_CHECKING
3
3
  import logging
4
4
 
5
5
  import pyvex
@@ -203,7 +203,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
203
203
  l.info("Indirect jump at %#x cannot be resolved by %s.", addr, repr(self))
204
204
  return False, []
205
205
 
206
- def _try_handle_simple_case_0(self, gp: int, blade: Blade) -> Optional[int]:
206
+ def _try_handle_simple_case_0(self, gp: int, blade: Blade) -> int | None:
207
207
  # we only attempt to support the following case:
208
208
  # + A | t37 = GET:I32(gp)
209
209
  # + B | t36 = Add32(t37,0xffff8624)
@@ -307,7 +307,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
307
307
  except KeyError:
308
308
  return None
309
309
 
310
- def _try_handle_simple_case_1(self, gp: int, blade: Blade) -> Optional[int]:
310
+ def _try_handle_simple_case_1(self, gp: int, blade: Blade) -> int | None:
311
311
  # we only attempt to support the following case:
312
312
  # + A | t22 = GET:I32(gp)
313
313
  # + B | t21 = Add32(t22,0xffff8020)
@@ -456,7 +456,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
456
456
  return None
457
457
 
458
458
  @staticmethod
459
- def _previous_node(blade: Blade, curr_node: Tuple[int, int]) -> Optional[Tuple[int, int]]:
459
+ def _previous_node(blade: Blade, curr_node: tuple[int, int]) -> tuple[int, int] | None:
460
460
  if blade.slice.in_degree(curr_node) != 1:
461
461
  return None
462
462
  nn = next(iter(blade.slice.predecessors(curr_node)))
@@ -493,7 +493,7 @@ class MipsElfFastResolver(IndirectJumpResolver):
493
493
  @staticmethod
494
494
  def _is_gp_used_on_slice(project, b: Blade) -> bool:
495
495
  gp_offset = project.arch.registers["gp"][0]
496
- blocks_on_slice: Dict[int, "Block"] = {}
496
+ blocks_on_slice: dict[int, "Block"] = {}
497
497
  for block_addr, block_stmt_idx in b.slice.nodes():
498
498
  if block_addr not in blocks_on_slice:
499
499
  blocks_on_slice[block_addr] = project.factory.block(block_addr, cross_insn_opt=False)
@@ -1,4 +1,4 @@
1
- from typing import Optional, Set, Any, List
1
+ from typing import Any
2
2
  from functools import reduce
3
3
 
4
4
  from .transitions import merge_transitions
@@ -56,7 +56,7 @@ class CFGSliceToSink:
56
56
  return set(reduce(lambda acc, destinations: acc + destinations, self._transitions.values(), []))
57
57
 
58
58
  @property
59
- def nodes(self) -> List[int]:
59
+ def nodes(self) -> list[int]:
60
60
  """
61
61
  :return: The complete list of addresses present in the slice.
62
62
  """
@@ -91,7 +91,7 @@ class CFGSliceToSink:
91
91
  """
92
92
  return not bool(self._transitions)
93
93
 
94
- def path_between(self, source: int, destination: int, visited: Optional[Set[Any]] = None) -> bool:
94
+ def path_between(self, source: int, destination: int, visited: set[Any] | None = None) -> bool:
95
95
  """
96
96
  Check the existence of a path in the slice between two given node adresses.
97
97
 
@@ -1,5 +1,6 @@
1
1
  # pylint:disable=import-outside-toplevel
2
- from typing import Tuple, Optional, Callable, Iterable, Dict, Set, TYPE_CHECKING
2
+ from typing import Optional, TYPE_CHECKING
3
+ from collections.abc import Callable, Iterable
3
4
  import queue
4
5
  import threading
5
6
  import time
@@ -40,17 +41,17 @@ class CompleteCallingConventionsAnalysis(Analysis):
40
41
  recover_variables=False,
41
42
  low_priority=False,
42
43
  force=False,
43
- cfg: Optional[CFGModel] = None,
44
+ cfg: CFGModel | None = None,
44
45
  analyze_callsites: bool = False,
45
46
  skip_signature_matched_functions: bool = False,
46
- max_function_blocks: Optional[int] = None,
47
- max_function_size: Optional[int] = None,
47
+ max_function_blocks: int | None = None,
48
+ max_function_size: int | None = None,
48
49
  workers: int = 0,
49
- cc_callback: Optional[Callable] = None,
50
- prioritize_func_addrs: Optional[Iterable[int]] = None,
50
+ cc_callback: Callable | None = None,
51
+ prioritize_func_addrs: Iterable[int] | None = None,
51
52
  skip_other_funcs: bool = False,
52
53
  auto_start: bool = True,
53
- func_graphs: Optional[Dict[int, "networkx.DiGraph"]] = None,
54
+ func_graphs: dict[int, "networkx.DiGraph"] | None = None,
54
55
  ):
55
56
  """
56
57
 
@@ -84,7 +85,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
84
85
  self._auto_start = auto_start
85
86
  self._total_funcs = None
86
87
  self._func_graphs = {} if not func_graphs else func_graphs
87
- self.prototype_libnames: Set[str] = set()
88
+ self.prototype_libnames: set[str] = set()
88
89
 
89
90
  self._func_addrs = [] # a list that holds addresses of all functions to be analyzed
90
91
  self._results = []
@@ -160,7 +161,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
160
161
  self._prioritize_func_addrs = None # no longer useful
161
162
 
162
163
  def _set_function_prototype(
163
- self, func: "Function", prototype: Optional["SimTypeFunction"], prototype_libname: Optional[str]
164
+ self, func: "Function", prototype: Optional["SimTypeFunction"], prototype_libname: str | None
164
165
  ) -> None:
165
166
  if func.prototype is None or func.is_prototype_guessed or self._force:
166
167
  func.is_prototype_guessed = True
@@ -294,7 +295,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
294
295
  continue
295
296
 
296
297
  if callee_info is not None:
297
- callee_info: Dict[int, Tuple[Optional["SimCC"], Optional["SimTypeFunction"], Optional[str]]]
298
+ callee_info: dict[int, tuple[Optional["SimCC"], Optional["SimTypeFunction"], str | None]]
298
299
  for callee, (callee_cc, callee_proto, callee_proto_libname) in callee_info.items():
299
300
  callee_func = self.kb.functions.get_by_addr(callee)
300
301
  callee_func.calling_convention = callee_cc
@@ -315,7 +316,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
315
316
 
316
317
  def _analyze_core(
317
318
  self, func_addr: int
318
- ) -> Tuple[Optional["SimCC"], Optional["SimTypeFunction"], Optional["str"], Optional["VariableManagerInternal"]]:
319
+ ) -> tuple[Optional["SimCC"], Optional["SimTypeFunction"], Optional["str"], Optional["VariableManagerInternal"]]:
319
320
  func = self.kb.functions.get_by_addr(func_addr)
320
321
  if func.ran_cca:
321
322
  return (
@@ -384,7 +385,7 @@ class CompleteCallingConventionsAnalysis(Analysis):
384
385
 
385
386
  def _get_callees_cc_prototypes(
386
387
  self, caller_func_addr: int
387
- ) -> Dict[int, Tuple[Optional["SimCC"], Optional["SimTypeFunction"], Optional[str]]]:
388
+ ) -> dict[int, tuple[Optional["SimCC"], Optional["SimTypeFunction"], str | None]]:
388
389
  d = {}
389
390
  for callee in self.kb.functions.callgraph.successors(caller_func_addr):
390
391
  if callee != caller_func_addr and callee not in d: