angr 9.2.131__py3-none-manylinux2014_aarch64.whl → 9.2.133__py3-none-manylinux2014_aarch64.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 (264) hide show
  1. angr/__init__.py +128 -128
  2. angr/analyses/__init__.py +38 -38
  3. angr/analyses/analysis.py +6 -2
  4. angr/analyses/backward_slice.py +3 -4
  5. angr/analyses/binary_optimizer.py +5 -12
  6. angr/analyses/bindiff.py +3 -6
  7. angr/analyses/calling_convention.py +3 -4
  8. angr/analyses/cfg/__init__.py +3 -3
  9. angr/analyses/cfg/cfg_base.py +1 -1
  10. angr/analyses/cfg/cfg_emulated.py +5 -5
  11. angr/analyses/cfg/cfg_fast.py +19 -17
  12. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +5 -5
  13. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +1 -1
  14. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +148 -101
  15. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
  16. angr/analyses/data_dep/__init__.py +4 -4
  17. angr/analyses/datagraph_meta.py +1 -1
  18. angr/analyses/ddg.py +16 -17
  19. angr/analyses/decompiler/__init__.py +12 -12
  20. angr/analyses/decompiler/ail_simplifier.py +24 -12
  21. angr/analyses/decompiler/block_similarity.py +2 -4
  22. angr/analyses/decompiler/block_simplifier.py +10 -21
  23. angr/analyses/decompiler/callsite_maker.py +1 -1
  24. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
  25. angr/analyses/decompiler/clinic.py +122 -41
  26. angr/analyses/decompiler/condition_processor.py +57 -39
  27. angr/analyses/decompiler/counters/__init__.py +3 -3
  28. angr/analyses/decompiler/decompilation_cache.py +7 -7
  29. angr/analyses/decompiler/dephication/__init__.py +1 -1
  30. angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
  31. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +11 -3
  32. angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
  33. angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
  34. angr/analyses/decompiler/expression_narrower.py +1 -1
  35. angr/analyses/decompiler/graph_region.py +8 -8
  36. angr/analyses/decompiler/optimization_passes/__init__.py +20 -20
  37. angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
  38. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +1 -2
  39. angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
  40. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +8 -7
  41. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +1 -3
  42. angr/analyses/decompiler/optimization_passes/engine_base.py +262 -84
  43. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +175 -39
  44. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +2 -5
  45. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +5 -5
  46. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +12 -3
  47. angr/analyses/decompiler/optimization_passes/optimization_pass.py +42 -19
  48. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +9 -5
  49. angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -1
  50. angr/analyses/decompiler/peephole_optimizations/base.py +6 -6
  51. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +2 -0
  52. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
  53. angr/analyses/decompiler/presets/__init__.py +1 -1
  54. angr/analyses/decompiler/region_simplifiers/expr_folding.py +3 -3
  55. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +8 -12
  56. angr/analyses/decompiler/ssailification/rewriting.py +1 -2
  57. angr/analyses/decompiler/ssailification/rewriting_engine.py +139 -56
  58. angr/analyses/decompiler/ssailification/ssailification.py +2 -1
  59. angr/analyses/decompiler/ssailification/traversal.py +4 -6
  60. angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
  61. angr/analyses/decompiler/structured_codegen/__init__.py +5 -5
  62. angr/analyses/decompiler/structured_codegen/base.py +3 -3
  63. angr/analyses/decompiler/structured_codegen/c.py +39 -40
  64. angr/analyses/decompiler/structuring/__init__.py +3 -3
  65. angr/analyses/decompiler/structuring/phoenix.py +45 -29
  66. angr/analyses/decompiler/structuring/structurer_base.py +2 -2
  67. angr/analyses/decompiler/structuring/structurer_nodes.py +23 -14
  68. angr/analyses/deobfuscator/__init__.py +3 -3
  69. angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
  70. angr/analyses/deobfuscator/string_obf_finder.py +2 -2
  71. angr/analyses/deobfuscator/string_obf_opt_passes.py +1 -1
  72. angr/analyses/disassembly.py +4 -4
  73. angr/analyses/forward_analysis/__init__.py +1 -1
  74. angr/analyses/forward_analysis/visitors/graph.py +6 -6
  75. angr/analyses/init_finder.py +47 -22
  76. angr/analyses/loop_analysis.py +1 -1
  77. angr/analyses/loopfinder.py +1 -1
  78. angr/analyses/propagator/engine_base.py +21 -14
  79. angr/analyses/propagator/engine_vex.py +149 -179
  80. angr/analyses/propagator/outdated_definition_walker.py +12 -6
  81. angr/analyses/propagator/propagator.py +10 -28
  82. angr/analyses/propagator/top_checker_mixin.py +211 -5
  83. angr/analyses/propagator/vex_vars.py +4 -4
  84. angr/analyses/reaching_definitions/__init__.py +9 -9
  85. angr/analyses/reaching_definitions/call_trace.py +2 -2
  86. angr/analyses/reaching_definitions/dep_graph.py +1 -1
  87. angr/analyses/reaching_definitions/engine_ail.py +304 -329
  88. angr/analyses/reaching_definitions/engine_vex.py +243 -229
  89. angr/analyses/reaching_definitions/function_handler.py +3 -3
  90. angr/analyses/reaching_definitions/function_handler_library/__init__.py +1 -1
  91. angr/analyses/reaching_definitions/rd_state.py +47 -42
  92. angr/analyses/reassembler.py +26 -31
  93. angr/analyses/s_liveness.py +8 -0
  94. angr/analyses/s_propagator.py +18 -3
  95. angr/analyses/s_reaching_definitions/s_rda_view.py +2 -5
  96. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
  97. angr/analyses/stack_pointer_tracker.py +4 -4
  98. angr/analyses/typehoon/simple_solver.py +14 -14
  99. angr/analyses/typehoon/translator.py +10 -2
  100. angr/analyses/typehoon/typeconsts.py +11 -3
  101. angr/analyses/typehoon/typevars.py +26 -26
  102. angr/analyses/unpacker/__init__.py +1 -1
  103. angr/analyses/variable_recovery/engine_ail.py +299 -259
  104. angr/analyses/variable_recovery/engine_base.py +138 -121
  105. angr/analyses/variable_recovery/engine_vex.py +175 -185
  106. angr/analyses/variable_recovery/irsb_scanner.py +49 -38
  107. angr/analyses/variable_recovery/variable_recovery.py +28 -5
  108. angr/analyses/variable_recovery/variable_recovery_base.py +33 -34
  109. angr/analyses/variable_recovery/variable_recovery_fast.py +4 -8
  110. angr/analyses/veritesting.py +2 -2
  111. angr/analyses/vfg.py +5 -5
  112. angr/analyses/xrefs.py +46 -19
  113. angr/angrdb/serializers/__init__.py +1 -1
  114. angr/annocfg.py +20 -15
  115. angr/blade.py +2 -2
  116. angr/block.py +20 -25
  117. angr/calling_conventions.py +12 -14
  118. angr/code_location.py +6 -10
  119. angr/codenode.py +3 -3
  120. angr/engines/__init__.py +12 -14
  121. angr/engines/engine.py +24 -61
  122. angr/engines/light/__init__.py +13 -5
  123. angr/engines/light/data.py +1 -1
  124. angr/engines/light/engine.py +1003 -1185
  125. angr/engines/pcode/__init__.py +1 -1
  126. angr/engines/pcode/behavior.py +1 -1
  127. angr/engines/pcode/cc.py +2 -0
  128. angr/engines/pcode/lifter.py +13 -15
  129. angr/engines/soot/expressions/__init__.py +12 -12
  130. angr/engines/soot/statements/__init__.py +6 -6
  131. angr/engines/soot/values/__init__.py +6 -6
  132. angr/engines/soot/values/arrayref.py +2 -2
  133. angr/engines/soot/values/constants.py +1 -1
  134. angr/engines/soot/values/instancefieldref.py +1 -1
  135. angr/engines/soot/values/paramref.py +1 -1
  136. angr/engines/soot/values/staticfieldref.py +1 -1
  137. angr/engines/successors.py +15 -14
  138. angr/engines/vex/__init__.py +5 -5
  139. angr/engines/vex/claripy/ccall.py +2 -2
  140. angr/engines/vex/claripy/datalayer.py +1 -1
  141. angr/engines/vex/claripy/irop.py +19 -19
  142. angr/engines/vex/heavy/__init__.py +2 -2
  143. angr/engines/vex/heavy/actions.py +1 -3
  144. angr/engines/vex/heavy/heavy.py +4 -6
  145. angr/engines/vex/lifter.py +2 -4
  146. angr/engines/vex/light/light.py +0 -2
  147. angr/engines/vex/light/slicing.py +5 -5
  148. angr/exploration_techniques/__init__.py +19 -142
  149. angr/exploration_techniques/base.py +126 -0
  150. angr/exploration_techniques/bucketizer.py +1 -1
  151. angr/exploration_techniques/dfs.py +3 -1
  152. angr/exploration_techniques/director.py +2 -3
  153. angr/exploration_techniques/driller_core.py +1 -1
  154. angr/exploration_techniques/explorer.py +4 -2
  155. angr/exploration_techniques/lengthlimiter.py +2 -1
  156. angr/exploration_techniques/local_loop_seer.py +2 -1
  157. angr/exploration_techniques/loop_seer.py +5 -5
  158. angr/exploration_techniques/manual_mergepoint.py +2 -1
  159. angr/exploration_techniques/memory_watcher.py +3 -1
  160. angr/exploration_techniques/oppologist.py +4 -5
  161. angr/exploration_techniques/slicecutor.py +4 -2
  162. angr/exploration_techniques/spiller.py +1 -1
  163. angr/exploration_techniques/stochastic.py +2 -1
  164. angr/exploration_techniques/stub_stasher.py +2 -1
  165. angr/exploration_techniques/suggestions.py +3 -1
  166. angr/exploration_techniques/symbion.py +3 -1
  167. angr/exploration_techniques/tech_builder.py +2 -1
  168. angr/exploration_techniques/threading.py +2 -11
  169. angr/exploration_techniques/timeout.py +4 -2
  170. angr/exploration_techniques/tracer.py +4 -3
  171. angr/exploration_techniques/unique.py +3 -2
  172. angr/exploration_techniques/veritesting.py +1 -1
  173. angr/factory.py +36 -6
  174. angr/keyed_region.py +4 -4
  175. angr/knowledge_base.py +1 -1
  176. angr/knowledge_plugins/__init__.py +11 -11
  177. angr/knowledge_plugins/cfg/__init__.py +5 -5
  178. angr/knowledge_plugins/cfg/cfg_manager.py +2 -2
  179. angr/knowledge_plugins/cfg/cfg_model.py +8 -8
  180. angr/knowledge_plugins/cfg/cfg_node.py +19 -19
  181. angr/knowledge_plugins/cfg/indirect_jump.py +6 -6
  182. angr/knowledge_plugins/cfg/memory_data.py +5 -7
  183. angr/knowledge_plugins/functions/function.py +48 -52
  184. angr/knowledge_plugins/functions/function_parser.py +4 -4
  185. angr/knowledge_plugins/key_definitions/__init__.py +3 -3
  186. angr/knowledge_plugins/key_definitions/atoms.py +8 -8
  187. angr/knowledge_plugins/key_definitions/definition.py +1 -1
  188. angr/knowledge_plugins/key_definitions/live_definitions.py +30 -27
  189. angr/knowledge_plugins/labels.py +1 -1
  190. angr/knowledge_plugins/propagations/__init__.py +1 -1
  191. angr/knowledge_plugins/propagations/prop_value.py +2 -2
  192. angr/knowledge_plugins/propagations/propagation_model.py +7 -8
  193. angr/knowledge_plugins/propagations/states.py +44 -39
  194. angr/knowledge_plugins/variables/variable_access.py +2 -2
  195. angr/knowledge_plugins/variables/variable_manager.py +24 -10
  196. angr/knowledge_plugins/xrefs/xref.py +5 -8
  197. angr/misc/__init__.py +4 -4
  198. angr/misc/hookset.py +4 -5
  199. angr/misc/loggers.py +2 -2
  200. angr/misc/telemetry.py +1 -1
  201. angr/procedures/__init__.py +1 -1
  202. angr/procedures/cgc/fdwait.py +2 -2
  203. angr/procedures/definitions/__init__.py +2 -2
  204. angr/procedures/definitions/linux_kernel.py +0 -1
  205. angr/procedures/definitions/parse_syscalls_from_local_system.py +1 -1
  206. angr/procedures/definitions/parse_win32json.py +0 -1
  207. angr/procedures/ntdll/exceptions.py +1 -1
  208. angr/procedures/stubs/format_parser.py +3 -3
  209. angr/procedures/win32/dynamic_loading.py +1 -1
  210. angr/protos/__init__.py +3 -3
  211. angr/sim_manager.py +3 -5
  212. angr/sim_state.py +40 -42
  213. angr/sim_state_options.py +3 -3
  214. angr/sim_type.py +15 -14
  215. angr/sim_variable.py +42 -45
  216. angr/simos/__init__.py +4 -4
  217. angr/simos/cgc.py +1 -1
  218. angr/simos/simos.py +1 -1
  219. angr/simos/userland.py +1 -1
  220. angr/slicer.py +4 -7
  221. angr/state_plugins/__init__.py +34 -34
  222. angr/state_plugins/callstack.py +5 -12
  223. angr/state_plugins/heap/__init__.py +2 -2
  224. angr/state_plugins/heap/heap_brk.py +2 -4
  225. angr/state_plugins/heap/heap_ptmalloc.py +1 -1
  226. angr/state_plugins/jni_references.py +3 -2
  227. angr/state_plugins/scratch.py +1 -1
  228. angr/state_plugins/sim_action.py +1 -4
  229. angr/state_plugins/sim_event.py +1 -1
  230. angr/state_plugins/solver.py +7 -9
  231. angr/state_plugins/uc_manager.py +1 -1
  232. angr/state_plugins/view.py +2 -2
  233. angr/storage/__init__.py +1 -1
  234. angr/storage/file.py +10 -10
  235. angr/storage/memory_mixins/__init__.py +46 -46
  236. angr/storage/memory_mixins/default_filler_mixin.py +1 -3
  237. angr/storage/memory_mixins/javavm_memory_mixin.py +2 -2
  238. angr/storage/memory_mixins/name_resolution_mixin.py +2 -2
  239. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -3
  240. angr/storage/memory_mixins/paged_memory/pages/__init__.py +6 -6
  241. angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
  242. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +1 -1
  243. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
  244. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
  245. angr/storage/memory_mixins/regioned_memory/__init__.py +3 -3
  246. angr/storage/memory_mixins/regioned_memory/region_data.py +5 -5
  247. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +7 -9
  248. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +4 -4
  249. angr/storage/memory_object.py +4 -4
  250. angr/utils/__init__.py +3 -3
  251. angr/utils/bits.py +12 -0
  252. angr/utils/dynamic_dictlist.py +1 -1
  253. angr/utils/graph.py +1 -1
  254. angr/utils/orderedset.py +4 -1
  255. angr/utils/segment_list.py +2 -2
  256. angr/utils/ssa/__init__.py +33 -8
  257. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/METADATA +6 -6
  258. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/RECORD +262 -263
  259. angr/analyses/propagator/engine_ail.py +0 -1562
  260. angr/storage/memory_mixins/__init__.pyi +0 -48
  261. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/LICENSE +0 -0
  262. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/WHEEL +0 -0
  263. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/entry_points.txt +0 -0
  264. {angr-9.2.131.dist-info → angr-9.2.133.dist-info}/top_level.txt +0 -0
@@ -1,13 +1,14 @@
1
- # pylint:disable=arguments-renamed,too-many-boolean-expressions,no-self-use
1
+ # pylint:disable=arguments-renamed,too-many-boolean-expressions,no-self-use,unused-argument
2
2
  from __future__ import annotations
3
3
  from typing import Any
4
+ from collections.abc import Callable
4
5
  from collections import defaultdict
5
6
 
6
7
  from archinfo import Endness
7
8
  from ailment.expression import (
8
9
  Const,
9
10
  Register,
10
- Load,
11
+ Expression,
11
12
  StackBaseOffset,
12
13
  Convert,
13
14
  BinaryOp,
@@ -19,7 +20,8 @@ from ailment.expression import (
19
20
  from ailment.statement import ConditionalJump, Jump, Assignment
20
21
  import claripy
21
22
 
22
- from angr.engines.light import SimEngineLightAILMixin
23
+ from angr.utils.bits import zeroextend_on_demand
24
+ from angr.engines.light import SimEngineNostmtAIL
23
25
  from angr.storage.memory_mixins import (
24
26
  SimpleInterfaceMixin,
25
27
  DefaultFillerMixin,
@@ -31,6 +33,19 @@ from angr.errors import SimMemoryMissingError
31
33
  from .optimization_pass import OptimizationPass, OptimizationPassStage
32
34
 
33
35
 
36
+ def _make_binop(compute: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]):
37
+ def inner(self, expr: BinaryOp) -> claripy.ast.BV | None:
38
+ a, b = self._expr(expr.operands[0]), self._expr(expr.operands[1])
39
+ if a is None or b is None:
40
+ return None
41
+ try:
42
+ return compute(a, b)
43
+ except (ZeroDivisionError, claripy.ClaripyZeroDivisionError):
44
+ return None
45
+
46
+ return inner
47
+
48
+
34
49
  class FasterMemory(
35
50
  SimpleInterfaceMixin,
36
51
  DefaultFillerMixin,
@@ -61,12 +76,12 @@ class InlinedStringTransformationState:
61
76
  def _get_weakref(self):
62
77
  return self
63
78
 
64
- def reg_store(self, reg: Register, value: claripy.ast.Bits) -> None:
79
+ def reg_store(self, reg: Register, value: claripy.ast.BV) -> None:
65
80
  self.registers.store(
66
81
  reg.reg_offset, value, size=value.size() // self.arch.byte_width, endness=str(self.arch.register_endness)
67
82
  )
68
83
 
69
- def reg_load(self, reg: Register) -> claripy.ast.Bits | None:
84
+ def reg_load(self, reg: Register) -> claripy.ast.BV | None:
70
85
  try:
71
86
  return self.registers.load(
72
87
  reg.reg_offset, size=reg.size, endness=self.arch.register_endness, fill_missing=False
@@ -77,7 +92,7 @@ class InlinedStringTransformationState:
77
92
  def mem_store(self, addr: int, value: claripy.ast.Bits, endness: str) -> None:
78
93
  self.memory.store(addr, value, size=value.size() // self.arch.byte_width, endness=endness)
79
94
 
80
- def mem_load(self, addr: int, size: int, endness) -> claripy.ast.Bits | None:
95
+ def mem_load(self, addr: int, size: int, endness) -> claripy.ast.BV | None:
81
96
  try:
82
97
  return self.memory.load(addr, size=size, endness=str(endness), fill_missing=False)
83
98
  except SimMemoryMissingError:
@@ -86,21 +101,21 @@ class InlinedStringTransformationState:
86
101
  def vvar_store(self, vvar: VirtualVariable, value: claripy.ast.Bits | None) -> None:
87
102
  self.virtual_variables[vvar.varid] = value
88
103
 
89
- def vvar_load(self, vvar: VirtualVariable) -> claripy.ast.Bits | None:
104
+ def vvar_load(self, vvar: VirtualVariable) -> claripy.ast.BV | None:
90
105
  if vvar.varid in self.virtual_variables:
91
106
  return self.virtual_variables[vvar.varid]
92
107
  return None
93
108
 
94
109
 
95
- class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
110
+ class InlinedStringTransformationAILEngine(
111
+ SimEngineNostmtAIL[InlinedStringTransformationState, claripy.ast.BV | None, None, None],
112
+ ):
96
113
  """
97
114
  A simple AIL execution engine
98
115
  """
99
116
 
100
117
  def __init__(self, project, nodes: dict[int, Any], start: int, end: int, step_limit: int):
101
- super().__init__()
102
-
103
- self.arch = project.arch
118
+ super().__init__(project)
104
119
  self.nodes: dict[int, Any] = nodes
105
120
  self.start: int = start
106
121
  self.end: int = end
@@ -121,7 +136,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
121
136
  # jumped to a node that we do not know about
122
137
  break
123
138
  block = self.nodes[self.pc]
124
- self._process(state, None, block=block)
139
+ self._process(state, block=block, whitelist=None)
125
140
  if self.pc is None:
126
141
  # not sure where to jump...
127
142
  break
@@ -131,8 +146,18 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
131
146
  break
132
147
  i += 1
133
148
 
134
- def _process_address(self, addr: Const | StackBaseOffset) -> tuple[int, str] | None:
149
+ def _top(self, bits):
150
+ assert False, "Should not be reachable"
151
+
152
+ def _is_top(self, expr):
153
+ assert False, "Should not be reachable"
154
+
155
+ def _process_block_end(self, block, stmt_data, whitelist):
156
+ pass
157
+
158
+ def _process_address(self, addr: Expression) -> tuple[int, str] | None:
135
159
  if isinstance(addr, Const):
160
+ assert isinstance(addr.value, int)
136
161
  return addr.value, "mem"
137
162
  if isinstance(addr, StackBaseOffset):
138
163
  return (addr.offset + self.STACK_BASE) & self.MASK, "stack"
@@ -145,7 +170,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
145
170
  return (v0 + v1.concrete_value) & self.MASK, "stack"
146
171
  return None
147
172
 
148
- def _handle_Assignment(self, stmt):
173
+ def _handle_stmt_Assignment(self, stmt):
149
174
  if isinstance(stmt.dst, VirtualVariable):
150
175
  if stmt.dst.was_reg:
151
176
  val = self._expr(stmt.src)
@@ -163,7 +188,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
163
188
  byte_off = val.size() // self.arch.byte_width - i - 1
164
189
  self.stack_accesses[addr + i].append(("store", self._codeloc(), val.get_byte(byte_off)))
165
190
 
166
- def _handle_Store(self, stmt):
191
+ def _handle_stmt_Store(self, stmt):
167
192
  addr_and_type = self._process_address(stmt.addr)
168
193
  if addr_and_type is not None:
169
194
  addr, addr_type = addr_and_type
@@ -178,14 +203,14 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
178
203
  byte_off = val.size() // self.arch.byte_width - i - 1
179
204
  self.stack_accesses[addr + i].append(("store", self._codeloc(), val.get_byte(byte_off)))
180
205
 
181
- def _handle_Jump(self, stmt):
206
+ def _handle_stmt_Jump(self, stmt):
182
207
  self.last_pc = self.pc
183
208
  if isinstance(stmt.target, Const):
184
209
  self.pc = stmt.target.value
185
210
  else:
186
211
  self.pc = None
187
212
 
188
- def _handle_ConditionalJump(self, stmt):
213
+ def _handle_stmt_ConditionalJump(self, stmt):
189
214
  self.last_pc = self.pc
190
215
  self.pc = None
191
216
  if isinstance(stmt.true_target, Const) and isinstance(stmt.false_target, Const):
@@ -196,10 +221,12 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
196
221
  elif isinstance(cond, claripy.ast.Bits) and cond.concrete_value == 0:
197
222
  self.pc = stmt.false_target.value
198
223
 
199
- def _handle_Const(self, expr):
200
- return claripy.BVV(expr.value, expr.bits)
224
+ def _handle_expr_Const(self, expr):
225
+ if isinstance(expr.value, int):
226
+ return claripy.BVV(expr.value, expr.bits)
227
+ return None
201
228
 
202
- def _handle_Load(self, expr: Load):
229
+ def _handle_expr_Load(self, expr):
203
230
  addr_and_type = self._process_address(expr.addr)
204
231
  if addr_and_type is not None:
205
232
  addr, addr_type = addr_and_type
@@ -214,14 +241,14 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
214
241
  return v
215
242
  return None
216
243
 
217
- def _handle_Register(self, expr: Register):
244
+ def _handle_expr_Register(self, expr: Register):
218
245
  return self.state.reg_load(expr)
219
246
 
220
- def _handle_VirtualVariable(self, expr: VirtualVariable):
247
+ def _handle_expr_VirtualVariable(self, expr: VirtualVariable):
221
248
  if expr.was_stack:
222
249
  addr = (expr.stack_offset + self.STACK_BASE) & self.MASK
223
250
  v = self.state.mem_load(addr, expr.size, self.arch.memory_endness)
224
- if isinstance(v, claripy.ast.Bits):
251
+ if v is not None:
225
252
  # log it
226
253
  for i in range(expr.size):
227
254
  byte_off = i
@@ -233,25 +260,43 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
233
260
  return self.state.vvar_load(expr)
234
261
  return None
235
262
 
236
- def _handle_Phi(self, expr: Phi):
263
+ def _handle_expr_Phi(self, expr: Phi):
237
264
  for src, vvar in expr.src_and_vvars:
238
265
  if src[0] == self.last_pc and vvar is not None:
239
266
  return self.state.vvar_load(vvar)
240
267
  return None
241
268
 
242
- def _handle_Neg(self, expr: UnaryOp):
269
+ def _handle_unop_Neg(self, expr: UnaryOp):
243
270
  v = self._expr(expr.operand)
244
271
  if isinstance(v, claripy.ast.Bits):
245
272
  return -v
246
273
  return None
247
274
 
248
- def _handle_BitwiseNeg(self, expr: UnaryOp):
275
+ def _handle_unop_Not(self, expr: UnaryOp):
276
+ v = self._expr(expr.operand)
277
+ if isinstance(v, claripy.ast.Bits):
278
+ return ~v
279
+ return None
280
+
281
+ def _handle_unop_BitwiseNeg(self, expr: UnaryOp):
249
282
  v = self._expr(expr.operand)
250
283
  if isinstance(v, claripy.ast.Bits):
251
284
  return ~v
252
285
  return None
253
286
 
254
- def _handle_Convert(self, expr: Convert):
287
+ def _handle_unop_Default(self, expr: UnaryOp):
288
+ return None
289
+
290
+ _handle_unop_Clz = _handle_unop_Default
291
+ _handle_unop_Ctz = _handle_unop_Default
292
+ _handle_unop_Dereference = _handle_unop_Default
293
+ _handle_unop_Reference = _handle_unop_Default
294
+ _handle_unop_GetMSBs = _handle_unop_Default
295
+ _handle_unop_unpack = _handle_unop_Default
296
+ _handle_unop_Sqrt = _handle_unop_Default
297
+ _handle_unop_RSqrtEst = _handle_unop_Default
298
+
299
+ def _handle_expr_Convert(self, expr: Convert):
255
300
  v = self._expr(expr.operand)
256
301
  if isinstance(v, claripy.ast.Bits):
257
302
  if expr.to_bits > expr.from_bits:
@@ -263,48 +308,139 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
263
308
  return v
264
309
  return None
265
310
 
266
- def _handle_CmpEQ(self, expr):
311
+ def _handle_binop_CmpEQ(self, expr):
267
312
  op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
268
313
  if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
269
314
  return claripy.BVV(1, 1) if op0.concrete_value == op1.concrete_value else claripy.BVV(0, 1)
270
315
  return None
271
316
 
272
- def _handle_CmpNE(self, expr):
317
+ def _handle_binop_CmpNE(self, expr):
273
318
  op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
274
319
  if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
275
320
  return claripy.BVV(1, 1) if op0.concrete_value != op1.concrete_value else claripy.BVV(0, 1)
276
321
  return None
277
322
 
278
- def _handle_CmpLT(self, expr):
323
+ def _handle_binop_CmpLT(self, expr):
279
324
  op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
280
325
  if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
281
326
  return claripy.BVV(1, 1) if op0.concrete_value < op1.concrete_value else claripy.BVV(0, 1)
282
327
  return None
283
328
 
284
- def _handle_CmpLE(self, expr):
329
+ def _handle_binop_CmpLE(self, expr):
285
330
  op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
286
331
  if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
287
332
  return claripy.BVV(1, 1) if op0.concrete_value <= op1.concrete_value else claripy.BVV(0, 1)
288
333
  return None
289
334
 
290
- def _handle_CmpGT(self, expr):
335
+ def _handle_binop_CmpGT(self, expr):
291
336
  op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
292
337
  if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
293
338
  return claripy.BVV(1, 1) if op0.concrete_value > op1.concrete_value else claripy.BVV(0, 1)
294
339
  return None
295
340
 
296
- def _handle_CmpGE(self, expr):
341
+ def _handle_binop_CmpGE(self, expr):
297
342
  op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
298
343
  if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
299
344
  return claripy.BVV(1, 1) if op0.concrete_value >= op1.concrete_value else claripy.BVV(0, 1)
300
345
  return None
301
346
 
302
- def _handle_Call(self, stmt):
347
+ def _handle_stmt_Call(self, stmt):
303
348
  pass
304
349
 
305
- def _ail_handle_CallExpr(self, expr):
350
+ def _handle_expr_Call(self, expr):
306
351
  pass
307
352
 
353
+ def _handle_expr_BasePointerOffset(self, expr):
354
+ return None
355
+
356
+ def _handle_expr_DirtyExpression(self, expr):
357
+ return None
358
+
359
+ def _handle_expr_ITE(self, expr):
360
+ return None
361
+
362
+ def _handle_expr_MultiStatementExpression(self, expr):
363
+ return None
364
+
365
+ def _handle_expr_Reinterpret(self, expr):
366
+ return None
367
+
368
+ def _handle_expr_StackBaseOffset(self, expr):
369
+ return None
370
+
371
+ def _handle_expr_Tmp(self, expr):
372
+ try:
373
+ return self.tmps[expr.tmp_idx]
374
+ except KeyError:
375
+ return None
376
+
377
+ def _handle_expr_VEXCCallExpression(self, expr):
378
+ return None
379
+
380
+ def _handle_binop_Default(self, expr):
381
+ self._expr(expr.operands[0])
382
+ self._expr(expr.operands[1])
383
+
384
+ _handle_binop_Add = _make_binop(lambda a, b: a + b)
385
+ _handle_binop_And = _make_binop(lambda a, b: a & b)
386
+ _handle_binop_Concat = _make_binop(lambda a, b: a.concat(b))
387
+ _handle_binop_Div = _make_binop(lambda a, b: a // b)
388
+ _handle_binop_LogicalAnd = _make_binop(lambda a, b: a & b)
389
+ _handle_binop_LogicalOr = _make_binop(lambda a, b: a | b)
390
+ _handle_binop_Mod = _make_binop(lambda a, b: a % b)
391
+ _handle_binop_Mul = _make_binop(lambda a, b: a * b)
392
+ _handle_binop_Or = _make_binop(lambda a, b: a | b)
393
+ _handle_binop_Rol = _make_binop(lambda a, b: claripy.RotateLeft(a, zeroextend_on_demand(a, b)))
394
+ _handle_binop_Ror = _make_binop(lambda a, b: claripy.RotateRight(a, zeroextend_on_demand(a, b)))
395
+ _handle_binop_Sar = _make_binop(lambda a, b: a >> zeroextend_on_demand(a, b))
396
+ _handle_binop_Shl = _make_binop(lambda a, b: a << zeroextend_on_demand(a, b))
397
+ _handle_binop_Shr = _make_binop(lambda a, b: a.LShR(zeroextend_on_demand(a, b)))
398
+ _handle_binop_Sub = _make_binop(lambda a, b: a - b)
399
+ _handle_binop_Xor = _make_binop(lambda a, b: a ^ b)
400
+
401
+ def _handle_binop_Mull(self, expr):
402
+ a, b = self._expr(expr.operands[0]), self._expr(expr.operands[1])
403
+ if a is None or b is None:
404
+ return None
405
+ xt = a.size()
406
+ if expr.signed:
407
+ return a.sign_extend(xt) * b.sign_extend(xt)
408
+ return a.zero_extend(xt) * b.zero_extend(xt)
409
+
410
+ _handle_binop_AddF = _handle_binop_Default
411
+ _handle_binop_AddV = _handle_binop_Default
412
+ _handle_binop_Carry = _handle_binop_Default
413
+ _handle_binop_CmpF = _handle_binop_Default
414
+ _handle_binop_DivF = _handle_binop_Default
415
+ _handle_binop_DivV = _handle_binop_Default
416
+ _handle_binop_InterleaveLOV = _handle_binop_Default
417
+ _handle_binop_InterleaveHIV = _handle_binop_Default
418
+ _handle_binop_CasCmpEQ = _handle_binop_Default
419
+ _handle_binop_CasCmpNE = _handle_binop_Default
420
+ _handle_binop_ExpCmpNE = _handle_binop_Default
421
+ _handle_binop_SarNV = _handle_binop_Default
422
+ _handle_binop_ShrNV = _handle_binop_Default
423
+ _handle_binop_ShlNV = _handle_binop_Default
424
+ _handle_binop_CmpEQV = _handle_binop_Default
425
+ _handle_binop_CmpNEV = _handle_binop_Default
426
+ _handle_binop_CmpGEV = _handle_binop_Default
427
+ _handle_binop_CmpGTV = _handle_binop_Default
428
+ _handle_binop_CmpLEV = _handle_binop_Default
429
+ _handle_binop_CmpLTV = _handle_binop_Default
430
+ _handle_binop_MulF = _handle_binop_Default
431
+ _handle_binop_MulV = _handle_binop_Default
432
+ _handle_binop_MulHiV = _handle_binop_Default
433
+ _handle_binop_SBorrow = _handle_binop_Default
434
+ _handle_binop_SCarry = _handle_binop_Default
435
+ _handle_binop_SubF = _handle_binop_Default
436
+ _handle_binop_SubV = _handle_binop_Default
437
+ _handle_binop_MinV = _handle_binop_Default
438
+ _handle_binop_MaxV = _handle_binop_Default
439
+ _handle_binop_QAddV = _handle_binop_Default
440
+ _handle_binop_QNarrowBinV = _handle_binop_Default
441
+ _handle_binop_PermV = _handle_binop_Default
442
+ _handle_binop_Set = _handle_binop_Default
443
+
308
444
 
309
445
  class InlineStringTransformationDescriptor:
310
446
  """
@@ -387,6 +523,7 @@ class InlinedStringTransformationSimplifier(OptimizationPass):
387
523
 
388
524
  # remote the loop node
389
525
  # since the loop node has exactly one external predecessor and one external successor, we can get rid of it
526
+ assert self.out_graph is not None
390
527
  pred = next(iter(nn for nn in self.out_graph.predecessors(desc.loop_body) if nn is not desc.loop_body))
391
528
  succ = next(iter(nn for nn in self.out_graph.successors(desc.loop_body) if nn is not desc.loop_body))
392
529
 
@@ -404,16 +541,15 @@ class InlinedStringTransformationSimplifier(OptimizationPass):
404
541
  def _find_string_transformation_loops(self):
405
542
  # find self loops
406
543
  self_loops = []
544
+ assert self._graph is not None
407
545
  for node in self._graph.nodes:
408
546
  preds = list(self._graph.predecessors(node))
409
547
  succs = list(self._graph.successors(node))
410
548
  if len(preds) == 2 and len(succs) == 2 and node in preds and node in succs:
411
549
  pred = next(iter(nn for nn in preds if nn is not node))
412
550
  succ = next(iter(nn for nn in succs if nn is not node))
413
- if (
414
- self._graph.out_degree[pred] == 1
415
- and self._graph.in_degree[succ] == 1
416
- or self._graph.out_degree[pred] == 2
551
+ if (self._graph.out_degree[pred] == 1 and self._graph.in_degree[succ] == 1) or (
552
+ self._graph.out_degree[pred] == 2
417
553
  and self._graph.in_degree[succ] == 2
418
554
  and self._graph.has_edge(pred, succ)
419
555
  ):
@@ -314,9 +314,6 @@ class ITERegionConverter(OptimizationPass):
314
314
 
315
315
  @staticmethod
316
316
  def _is_assigning_to_vvar(stmt: Statement) -> bool:
317
- return (
318
- isinstance(stmt, Assignment)
319
- and isinstance(stmt.dst, VirtualVariable)
320
- or isinstance(stmt, Call)
321
- and isinstance(stmt.ret_expr, VirtualVariable)
317
+ return (isinstance(stmt, Assignment) and isinstance(stmt.dst, VirtualVariable)) or (
318
+ isinstance(stmt, Call) and isinstance(stmt.ret_expr, VirtualVariable)
322
319
  )
@@ -31,14 +31,14 @@ class Case:
31
31
  """
32
32
 
33
33
  __slots__ = (
34
- "original_node",
35
- "node_type",
36
- "variable_hash",
37
34
  "expr",
38
- "value",
35
+ "next_addr",
36
+ "node_type",
37
+ "original_node",
39
38
  "target",
40
39
  "target_idx",
41
- "next_addr",
40
+ "value",
41
+ "variable_hash",
42
42
  )
43
43
 
44
44
  def __init__(
@@ -12,7 +12,7 @@ _l.addFilter(UniqueLogFilter())
12
12
 
13
13
 
14
14
  class ModSimplifierAILEngine(SimplifierAILEngine):
15
- def _ail_handle_Sub(self, expr):
15
+ def _handle_binop_Sub(self, expr):
16
16
  operand_0 = self._expr(expr.operands[0])
17
17
  operand_1 = self._expr(expr.operands[1])
18
18
 
@@ -41,7 +41,15 @@ class ModSimplifierAILEngine(SimplifierAILEngine):
41
41
  c_0 = operand_1.operands[1]
42
42
  c_1 = operand_1.operands[0].operand.operands[1]
43
43
 
44
- if x_0 is not None and x_1 is not None and x_0.likes(x_1) and c_0.value == c_1.value:
44
+ # pylint: disable=too-many-boolean-expressions
45
+ if (
46
+ x_0 is not None
47
+ and x_1 is not None
48
+ and c_0 is not None
49
+ and c_1 is not None
50
+ and x_0.likes(x_1)
51
+ and c_0.value == c_1.value
52
+ ):
45
53
  return Expr.BinaryOp(expr.idx, "Mod", [x_0, c_0], expr.signed, **expr.tags)
46
54
 
47
55
  if (operand_0, operand_1) != (expr.operands[0], expr.operands[1]):
@@ -70,7 +78,7 @@ class ModSimplifier(OptimizationPass):
70
78
  super().__init__(func, **kwargs)
71
79
 
72
80
  self.state = SimplifierAILState(self.project.arch)
73
- self.engine = ModSimplifierAILEngine()
81
+ self.engine = ModSimplifierAILEngine(self.project)
74
82
 
75
83
  self.analyze()
76
84
 
@@ -78,6 +86,7 @@ class ModSimplifier(OptimizationPass):
78
86
  return True, None
79
87
 
80
88
  def _analyze(self, cache=None):
89
+ assert self._graph is not None
81
90
  for block in list(self._graph.nodes()):
82
91
  new_block = block
83
92
  old_block = None
@@ -5,15 +5,17 @@ from typing import Any, TYPE_CHECKING
5
5
  from collections.abc import Generator
6
6
  from enum import Enum
7
7
 
8
- import networkx # pylint:disable=unused-import
8
+ import networkx
9
+
9
10
  import ailment
10
11
 
11
12
  from angr.analyses.decompiler import RegionIdentifier
12
13
  from angr.analyses.decompiler.condition_processor import ConditionProcessor
13
- from angr.analyses.decompiler.goto_manager import GotoManager
14
+ from angr.analyses.decompiler.goto_manager import Goto, GotoManager
14
15
  from angr.analyses.decompiler.structuring import RecursiveStructurer, SAILRStructurer
15
16
  from angr.analyses.decompiler.utils import add_labels
16
17
  from angr.analyses.decompiler.counters import ControlFlowStructureCounter
18
+ from angr.project import Project
17
19
 
18
20
  if TYPE_CHECKING:
19
21
  from angr.knowledge_plugins.functions import Function
@@ -60,8 +62,10 @@ class BaseOptimizationPass:
60
62
 
61
63
  ARCHES = [] # strings of supported architectures
62
64
  PLATFORMS = [] # strings of supported platforms. Can be one of the following: "win32", "linux"
63
- STAGE: int = None # Specifies when this optimization pass should be executed
64
- STRUCTURING: str | None = None # specifies if this optimization pass is specific to a certain structuring algorithm
65
+ STAGE: OptimizationPassStage # Specifies when this optimization pass should be executed
66
+ STRUCTURING: list[str] | None = (
67
+ None # specifies if this optimization pass is specific to a certain structuring algorithm
68
+ )
65
69
  NAME = "N/A"
66
70
  DESCRIPTION = "N/A"
67
71
 
@@ -69,7 +73,8 @@ class BaseOptimizationPass:
69
73
  self._func: Function = func
70
74
 
71
75
  @property
72
- def project(self):
76
+ def project(self) -> Project:
77
+ assert self._func.project is not None
73
78
  return self._func.project
74
79
 
75
80
  @property
@@ -115,17 +120,18 @@ class OptimizationPass(BaseOptimizationPass):
115
120
  variable_kb=None,
116
121
  region_identifier=None,
117
122
  reaching_definitions=None,
118
- vvar_id_start=None,
123
+ vvar_id_start: int = 0,
119
124
  entry_node_addr=None,
120
125
  scratch: dict[str, Any] | None = None,
121
126
  force_loop_single_exit: bool = True,
122
127
  complete_successors: bool = False,
128
+ avoid_vvar_ids: set[int] | None = None,
123
129
  **kwargs,
124
130
  ):
125
131
  super().__init__(func)
126
132
  # self._blocks is just a cache
127
- self._blocks_by_addr: dict[int, set[ailment.Block]] = blocks_by_addr
128
- self._blocks_by_addr_and_idx: dict[tuple[int, int | None], ailment.Block] = blocks_by_addr_and_idx
133
+ self._blocks_by_addr: dict[int, set[ailment.Block]] = blocks_by_addr or {}
134
+ self._blocks_by_addr_and_idx: dict[tuple[int, int | None], ailment.Block] = blocks_by_addr_and_idx or {}
129
135
  self._graph: networkx.DiGraph | None = graph
130
136
  self._variable_kb = variable_kb
131
137
  self._ri = region_identifier
@@ -138,6 +144,7 @@ class OptimizationPass(BaseOptimizationPass):
138
144
  )
139
145
  self._force_loop_single_exit = force_loop_single_exit
140
146
  self._complete_successors = complete_successors
147
+ self._avoid_vvar_ids = avoid_vvar_ids or set()
141
148
 
142
149
  # output
143
150
  self.out_graph: networkx.DiGraph | None = None
@@ -164,10 +171,23 @@ class OptimizationPass(BaseOptimizationPass):
164
171
  self._new_block_addrs.add(new_addr)
165
172
  return new_addr
166
173
 
167
- def _get_block(self, addr, idx=None) -> ailment.Block | None:
174
+ def _get_block(self, addr, **kwargs) -> ailment.Block | None:
175
+ """
176
+ Get exactly one block by its address and optionally, also considering its block ID. An exception,
177
+ MultipleBlocksException, will be raised if there are more than one block satisfying the specified criteria.
178
+
179
+ :param addr: The address of the block.
180
+ :param kwargs: Optionally, you can specify "idx" to consider the block ID. If "idx" is not specified, this
181
+ method will return the only block at the specified address, None if there is no block at
182
+ that address, or raise an exception if there are more than one block at that address.
183
+ :return: The requested block or None if no block matching the specified criteria exists.
184
+ """
185
+
168
186
  if not self._blocks_by_addr:
169
187
  return None
170
- if idx is None:
188
+ idx_specified = "idx" in kwargs
189
+ idx = kwargs.get("idx")
190
+ if not idx_specified:
171
191
  blocks = self._blocks_by_addr.get(addr, None)
172
192
  else:
173
193
  blocks = [self._blocks_by_addr_and_idx.get((addr, idx), None)]
@@ -175,8 +195,12 @@ class OptimizationPass(BaseOptimizationPass):
175
195
  return None
176
196
  if len(blocks) == 1:
177
197
  return next(iter(blocks))
198
+ if idx_specified:
199
+ raise MultipleBlocksException(
200
+ f"There are {len(blocks)} blocks at address {addr:#x}.{idx} but only one is requested."
201
+ )
178
202
  raise MultipleBlocksException(
179
- "There are %d blocks at address %#x.%s but only one is requested." % (len(blocks), addr, idx)
203
+ f"There are {len(blocks)} blocks at address {addr:#x} (block ID ignored) but only one is requested."
180
204
  )
181
205
 
182
206
  def _get_blocks(self, addr, idx=None) -> Generator[ailment.Block]:
@@ -195,6 +219,7 @@ class OptimizationPass(BaseOptimizationPass):
195
219
  def _update_block(self, old_block, new_block):
196
220
  if self.out_graph is None:
197
221
  self.out_graph = self._graph # we do not make copy here for performance reasons. we can change it if needed
222
+ assert self.out_graph is not None
198
223
 
199
224
  if old_block not in self.out_graph:
200
225
  return
@@ -220,6 +245,7 @@ class OptimizationPass(BaseOptimizationPass):
220
245
  def _remove_block(self, block):
221
246
  if self.out_graph is None:
222
247
  self.out_graph = self._graph
248
+ assert self.out_graph is not None
223
249
 
224
250
  if block in self.out_graph:
225
251
  self.out_graph.remove_node(block)
@@ -244,6 +270,7 @@ class OptimizationPass(BaseOptimizationPass):
244
270
  func_graph=graph,
245
271
  use_callee_saved_regs_at_return=False,
246
272
  gp=self._func.info.get("gp", None) if self.project.arch.name in {"MIPS32", "MIPS64"} else None,
273
+ avoid_vvar_ids=self._avoid_vvar_ids,
247
274
  )
248
275
  if simp.simplified:
249
276
  graph = simp.func_graph
@@ -270,10 +297,6 @@ class SequenceOptimizationPass(BaseOptimizationPass):
270
297
  The base class for any sequence node optimization pass.
271
298
  """
272
299
 
273
- ARCHES = [] # strings of supported architectures
274
- PLATFORMS = [] # strings of supported platforms. Can be one of the following: "win32", "linux"
275
- STAGE: int = None # Specifies when this optimization pass should be executed
276
-
277
300
  def __init__(self, func, seq=None, **kwargs):
278
301
  super().__init__(func)
279
302
  self.seq = seq
@@ -298,6 +321,10 @@ class StructuringOptimizationPass(OptimizationPass):
298
321
  STRUCTURING = [SAILRStructurer.NAME]
299
322
  STAGE = OptimizationPassStage.DURING_REGION_IDENTIFICATION
300
323
 
324
+ _initial_gotos: set[Goto]
325
+ _goto_manager: GotoManager
326
+ _prev_graph: networkx.DiGraph
327
+
301
328
  def __init__(
302
329
  self,
303
330
  func,
@@ -321,10 +348,6 @@ class StructuringOptimizationPass(OptimizationPass):
321
348
  self._must_improve_rel_quality = must_improve_rel_quality
322
349
  self._readd_labels = readd_labels
323
350
 
324
- self._initial_gotos = None
325
- self._goto_manager: GotoManager | None = None
326
- self._prev_graph: networkx.DiGraph | None = None
327
-
328
351
  # relative quality metrics (excludes gotos)
329
352
  self._initial_structure_counter = None
330
353
  self._current_structure_counter = None