angr 9.2.132__py3-none-manylinux2014_x86_64.whl → 9.2.133__py3-none-manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of angr might be problematic. Click here for more details.

Files changed (202) hide show
  1. angr/__init__.py +128 -128
  2. angr/analyses/__init__.py +38 -38
  3. angr/analyses/backward_slice.py +3 -4
  4. angr/analyses/binary_optimizer.py +5 -12
  5. angr/analyses/bindiff.py +3 -6
  6. angr/analyses/calling_convention.py +3 -4
  7. angr/analyses/cfg/__init__.py +3 -3
  8. angr/analyses/cfg/cfg_base.py +1 -1
  9. angr/analyses/cfg/cfg_fast.py +17 -15
  10. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +5 -5
  11. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +1 -1
  12. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +9 -7
  13. angr/analyses/data_dep/__init__.py +4 -4
  14. angr/analyses/datagraph_meta.py +1 -1
  15. angr/analyses/ddg.py +2 -6
  16. angr/analyses/decompiler/__init__.py +12 -12
  17. angr/analyses/decompiler/ail_simplifier.py +21 -10
  18. angr/analyses/decompiler/block_similarity.py +2 -4
  19. angr/analyses/decompiler/callsite_maker.py +1 -1
  20. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
  21. angr/analyses/decompiler/clinic.py +14 -7
  22. angr/analyses/decompiler/condition_processor.py +45 -29
  23. angr/analyses/decompiler/counters/__init__.py +3 -3
  24. angr/analyses/decompiler/decompilation_cache.py +7 -7
  25. angr/analyses/decompiler/dephication/__init__.py +1 -1
  26. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +11 -3
  27. angr/analyses/decompiler/expression_narrower.py +1 -1
  28. angr/analyses/decompiler/graph_region.py +8 -8
  29. angr/analyses/decompiler/optimization_passes/__init__.py +20 -20
  30. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +1 -2
  31. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +8 -7
  32. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +1 -3
  33. angr/analyses/decompiler/optimization_passes/engine_base.py +1 -1
  34. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +2 -4
  35. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +2 -5
  36. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +5 -5
  37. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +9 -3
  38. angr/analyses/decompiler/optimization_passes/optimization_pass.py +3 -0
  39. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +9 -5
  40. angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -1
  41. angr/analyses/decompiler/peephole_optimizations/base.py +6 -6
  42. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
  43. angr/analyses/decompiler/presets/__init__.py +1 -1
  44. angr/analyses/decompiler/region_simplifiers/expr_folding.py +3 -3
  45. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +8 -12
  46. angr/analyses/decompiler/ssailification/rewriting_engine.py +1 -1
  47. angr/analyses/decompiler/structured_codegen/__init__.py +5 -5
  48. angr/analyses/decompiler/structured_codegen/base.py +3 -3
  49. angr/analyses/decompiler/structured_codegen/c.py +34 -37
  50. angr/analyses/decompiler/structuring/__init__.py +3 -3
  51. angr/analyses/decompiler/structuring/phoenix.py +19 -20
  52. angr/analyses/decompiler/structuring/structurer_base.py +2 -2
  53. angr/analyses/decompiler/structuring/structurer_nodes.py +14 -14
  54. angr/analyses/deobfuscator/__init__.py +3 -3
  55. angr/analyses/deobfuscator/string_obf_opt_passes.py +1 -1
  56. angr/analyses/disassembly.py +4 -4
  57. angr/analyses/forward_analysis/__init__.py +1 -1
  58. angr/analyses/forward_analysis/visitors/graph.py +6 -6
  59. angr/analyses/loop_analysis.py +1 -1
  60. angr/analyses/loopfinder.py +1 -1
  61. angr/analyses/propagator/outdated_definition_walker.py +12 -6
  62. angr/analyses/propagator/vex_vars.py +3 -3
  63. angr/analyses/reaching_definitions/__init__.py +9 -9
  64. angr/analyses/reaching_definitions/call_trace.py +2 -2
  65. angr/analyses/reaching_definitions/function_handler_library/__init__.py +1 -1
  66. angr/analyses/reaching_definitions/rd_state.py +10 -10
  67. angr/analyses/reassembler.py +26 -31
  68. angr/analyses/s_liveness.py +8 -0
  69. angr/analyses/s_reaching_definitions/s_rda_view.py +2 -5
  70. angr/analyses/stack_pointer_tracker.py +4 -4
  71. angr/analyses/typehoon/simple_solver.py +7 -9
  72. angr/analyses/typehoon/translator.py +2 -2
  73. angr/analyses/typehoon/typeconsts.py +1 -1
  74. angr/analyses/typehoon/typevars.py +17 -19
  75. angr/analyses/unpacker/__init__.py +1 -1
  76. angr/analyses/variable_recovery/engine_base.py +3 -4
  77. angr/analyses/variable_recovery/variable_recovery_base.py +1 -1
  78. angr/analyses/variable_recovery/variable_recovery_fast.py +2 -6
  79. angr/analyses/veritesting.py +2 -2
  80. angr/analyses/vfg.py +5 -5
  81. angr/angrdb/serializers/__init__.py +1 -1
  82. angr/annocfg.py +1 -1
  83. angr/blade.py +2 -2
  84. angr/block.py +16 -16
  85. angr/calling_conventions.py +11 -13
  86. angr/code_location.py +6 -10
  87. angr/codenode.py +3 -3
  88. angr/engines/__init__.py +12 -14
  89. angr/engines/engine.py +1 -54
  90. angr/engines/light/__init__.py +4 -4
  91. angr/engines/light/data.py +1 -1
  92. angr/engines/pcode/__init__.py +1 -1
  93. angr/engines/pcode/behavior.py +1 -1
  94. angr/engines/pcode/lifter.py +13 -15
  95. angr/engines/soot/expressions/__init__.py +12 -12
  96. angr/engines/soot/statements/__init__.py +6 -6
  97. angr/engines/soot/values/__init__.py +6 -6
  98. angr/engines/soot/values/arrayref.py +2 -2
  99. angr/engines/soot/values/constants.py +1 -1
  100. angr/engines/soot/values/instancefieldref.py +1 -1
  101. angr/engines/soot/values/paramref.py +1 -1
  102. angr/engines/soot/values/staticfieldref.py +1 -1
  103. angr/engines/successors.py +2 -5
  104. angr/engines/vex/__init__.py +5 -5
  105. angr/engines/vex/claripy/ccall.py +2 -2
  106. angr/engines/vex/claripy/irop.py +18 -18
  107. angr/engines/vex/heavy/__init__.py +2 -2
  108. angr/engines/vex/heavy/actions.py +1 -3
  109. angr/engines/vex/heavy/heavy.py +4 -6
  110. angr/engines/vex/lifter.py +2 -4
  111. angr/engines/vex/light/light.py +0 -2
  112. angr/engines/vex/light/slicing.py +3 -3
  113. angr/exploration_techniques/__init__.py +18 -18
  114. angr/exploration_techniques/threading.py +0 -6
  115. angr/factory.py +36 -6
  116. angr/keyed_region.py +4 -4
  117. angr/knowledge_base.py +1 -1
  118. angr/knowledge_plugins/__init__.py +11 -11
  119. angr/knowledge_plugins/cfg/__init__.py +5 -5
  120. angr/knowledge_plugins/cfg/cfg_manager.py +2 -2
  121. angr/knowledge_plugins/cfg/cfg_model.py +8 -8
  122. angr/knowledge_plugins/cfg/cfg_node.py +19 -19
  123. angr/knowledge_plugins/cfg/indirect_jump.py +6 -6
  124. angr/knowledge_plugins/cfg/memory_data.py +5 -7
  125. angr/knowledge_plugins/functions/function.py +48 -52
  126. angr/knowledge_plugins/functions/function_parser.py +4 -4
  127. angr/knowledge_plugins/key_definitions/__init__.py +3 -3
  128. angr/knowledge_plugins/key_definitions/atoms.py +6 -6
  129. angr/knowledge_plugins/key_definitions/definition.py +1 -1
  130. angr/knowledge_plugins/key_definitions/live_definitions.py +14 -14
  131. angr/knowledge_plugins/labels.py +1 -1
  132. angr/knowledge_plugins/propagations/__init__.py +1 -1
  133. angr/knowledge_plugins/propagations/prop_value.py +2 -2
  134. angr/knowledge_plugins/propagations/propagation_model.py +7 -8
  135. angr/knowledge_plugins/propagations/states.py +31 -31
  136. angr/knowledge_plugins/variables/variable_access.py +2 -2
  137. angr/knowledge_plugins/variables/variable_manager.py +1 -1
  138. angr/knowledge_plugins/xrefs/xref.py +5 -8
  139. angr/misc/__init__.py +4 -4
  140. angr/misc/hookset.py +4 -5
  141. angr/misc/loggers.py +2 -2
  142. angr/misc/telemetry.py +1 -1
  143. angr/procedures/__init__.py +1 -1
  144. angr/procedures/cgc/fdwait.py +2 -2
  145. angr/procedures/definitions/__init__.py +2 -2
  146. angr/procedures/definitions/linux_kernel.py +0 -1
  147. angr/procedures/definitions/parse_syscalls_from_local_system.py +1 -1
  148. angr/procedures/definitions/parse_win32json.py +0 -1
  149. angr/procedures/ntdll/exceptions.py +1 -1
  150. angr/procedures/stubs/format_parser.py +3 -3
  151. angr/procedures/win32/dynamic_loading.py +1 -1
  152. angr/protos/__init__.py +3 -3
  153. angr/sim_manager.py +2 -2
  154. angr/sim_state.py +1 -1
  155. angr/sim_state_options.py +3 -3
  156. angr/sim_type.py +10 -14
  157. angr/sim_variable.py +13 -17
  158. angr/simos/__init__.py +4 -4
  159. angr/simos/cgc.py +1 -1
  160. angr/simos/simos.py +1 -1
  161. angr/simos/userland.py +1 -1
  162. angr/slicer.py +4 -7
  163. angr/state_plugins/__init__.py +34 -34
  164. angr/state_plugins/callstack.py +5 -12
  165. angr/state_plugins/heap/__init__.py +2 -2
  166. angr/state_plugins/heap/heap_brk.py +2 -4
  167. angr/state_plugins/heap/heap_ptmalloc.py +1 -1
  168. angr/state_plugins/jni_references.py +3 -2
  169. angr/state_plugins/scratch.py +1 -1
  170. angr/state_plugins/sim_action.py +1 -4
  171. angr/state_plugins/sim_event.py +1 -1
  172. angr/state_plugins/solver.py +7 -9
  173. angr/state_plugins/uc_manager.py +1 -1
  174. angr/state_plugins/view.py +2 -2
  175. angr/storage/__init__.py +1 -1
  176. angr/storage/file.py +10 -10
  177. angr/storage/memory_mixins/__init__.py +46 -46
  178. angr/storage/memory_mixins/default_filler_mixin.py +1 -3
  179. angr/storage/memory_mixins/javavm_memory_mixin.py +2 -2
  180. angr/storage/memory_mixins/name_resolution_mixin.py +2 -2
  181. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -3
  182. angr/storage/memory_mixins/paged_memory/pages/__init__.py +6 -6
  183. angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
  184. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +1 -1
  185. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
  186. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
  187. angr/storage/memory_mixins/regioned_memory/__init__.py +3 -3
  188. angr/storage/memory_mixins/regioned_memory/region_data.py +5 -5
  189. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +7 -9
  190. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +4 -4
  191. angr/storage/memory_object.py +4 -4
  192. angr/utils/__init__.py +3 -3
  193. angr/utils/dynamic_dictlist.py +1 -1
  194. angr/utils/graph.py +1 -1
  195. angr/utils/segment_list.py +2 -2
  196. angr/utils/ssa/__init__.py +12 -5
  197. {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/METADATA +6 -6
  198. {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/RECORD +202 -202
  199. {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/LICENSE +0 -0
  200. {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/WHEEL +0 -0
  201. {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/entry_points.txt +0 -0
  202. {angr-9.2.132.dist-info → angr-9.2.133.dist-info}/top_level.txt +0 -0
@@ -143,10 +143,10 @@ class ConstantValueManager:
143
143
  """
144
144
 
145
145
  __slots__ = (
146
- "project",
147
- "kb",
148
146
  "func",
147
+ "kb",
149
148
  "mapping",
149
+ "project",
150
150
  )
151
151
 
152
152
  def __init__(self, project: Project, kb, func: Function):
@@ -240,13 +240,13 @@ class JumpTableProcessorState:
240
240
  """
241
241
 
242
242
  __slots__ = (
243
- "arch",
244
243
  "_registers",
245
244
  "_stack",
246
245
  "_tmpvar_source",
246
+ "arch",
247
247
  "is_jumptable",
248
- "stmts_to_instrument",
249
248
  "regs_to_initialize",
249
+ "stmts_to_instrument",
250
250
  )
251
251
 
252
252
  def __init__(self, arch):
@@ -2175,10 +2175,12 @@ class JumpTableResolver(IndirectJumpResolver):
2175
2175
  stmt_taken = i in stmt_ids
2176
2176
  display = stmt_taken if in_slice_stmts_only else True
2177
2177
  if display:
2178
- s = "%s %x:%02d | " % ("+" if stmt_taken else " ", addr, i)
2179
- s += f"{stmt.pp_str(arch=self.project.arch, tyenv=irsb.tyenv)} "
2178
+ s = (
2179
+ f"{'+' if stmt_taken else ' '} {addr:x}:{i:02d} | "
2180
+ f"{stmt.pp_str(arch=self.project.arch, tyenv=irsb.tyenv)} "
2181
+ )
2180
2182
  if stmt_taken:
2181
- s += "IN: %d" % blade.slice.in_degree((addr, i))
2183
+ s += f"IN: {blade.slice.in_degree((addr, i))}"
2182
2184
  print(s)
2183
2185
 
2184
2186
  # the default exit
@@ -5,12 +5,12 @@ from .dep_nodes import DepNodeTypes, BaseDepNode, VarDepNode, MemDepNode, Consta
5
5
 
6
6
 
7
7
  __all__ = (
8
+ "BaseDepNode",
9
+ "ConstantDepNode",
8
10
  "DataDependencyGraphAnalysis",
9
11
  "DepNodeTypes",
10
- "BaseDepNode",
11
- "VarDepNode",
12
12
  "MemDepNode",
13
- "ConstantDepNode",
14
- "TmpDepNode",
15
13
  "RegDepNode",
14
+ "TmpDepNode",
15
+ "VarDepNode",
16
16
  )
@@ -51,7 +51,7 @@ class DataGraphMeta:
51
51
  pp = []
52
52
  for stmt in e:
53
53
  # true case is a SimProcedure
54
- s = "(0x%x, %d)" % (stmt[0], stmt[1]) if imarks is False or stmt[1] == -1 else f"[0x{self._imarks[stmt]:x}]"
54
+ s = f"(0x{stmt[0]:x}, {stmt[1]})" if imarks is False or stmt[1] == -1 else f"[0x{self._imarks[stmt]:x}]"
55
55
  pp.append(s)
56
56
 
57
57
  print(pp[0] + " -> " + pp[1] + " : " + str(data))
angr/analyses/ddg.py CHANGED
@@ -95,7 +95,7 @@ class DDGJob:
95
95
  self.call_depth = call_depth
96
96
 
97
97
  def __repr__(self):
98
- return "<DDGJob %s, call_depth %d>" % (self.cfg_node, self.call_depth)
98
+ return f"<DDGJob {self.cfg_node}, call_depth {self.call_depth}>"
99
99
 
100
100
 
101
101
  class LiveDefinitions:
@@ -342,11 +342,7 @@ class DDGViewItem:
342
342
  return None
343
343
 
344
344
  def __repr__(self):
345
- return "[%s, %d dependents, depends on %d]" % (
346
- self._variable,
347
- len(self.dependents),
348
- len(self.depends_on),
349
- )
345
+ return f"[{self._variable}, {len(self.dependents)} dependents, depends on {len(self.depends_on)}]"
350
346
 
351
347
  def __eq__(self, other):
352
348
  return (
@@ -20,22 +20,22 @@ StructuredCodeGenerator = CStructuredCodeGenerator
20
20
 
21
21
 
22
22
  __all__ = (
23
- "RegionIdentifier",
23
+ "DECOMPILATION_PRESETS",
24
+ "AILSimplifier",
25
+ "BlockSimplifier",
24
26
  "CStructuredCodeGenerator",
25
- "ImportSourceCode",
27
+ "CallSiteMaker",
26
28
  "Clinic",
27
- "RegionSimplifier",
28
29
  "Decompiler",
29
- "options",
30
- "options_by_category",
31
- "BlockSimplifier",
32
- "CallSiteMaker",
33
- "AILSimplifier",
34
- "Ssailification",
35
30
  "GraphDephication",
31
+ "ImportSourceCode",
32
+ "RegionIdentifier",
33
+ "RegionSimplifier",
36
34
  "SeqNodeDephication",
37
- "DECOMPILATION_PRESETS",
38
- "structuring",
39
- "optimization_passes",
35
+ "Ssailification",
40
36
  "StructuredCodeGenerator",
37
+ "optimization_passes",
38
+ "options",
39
+ "options_by_category",
40
+ "structuring",
41
41
  )
@@ -97,6 +97,7 @@ class AILSimplifier(Analysis):
97
97
  rewrite_ccalls=True,
98
98
  removed_vvar_ids: set[int] | None = None,
99
99
  arg_vvars: dict[int, tuple[VirtualVariable, SimVariable]] | None = None,
100
+ avoid_vvar_ids: set[int] | None = None,
100
101
  ):
101
102
  self.func = func
102
103
  self.func_graph = func_graph if func_graph is not None else func.graph
@@ -115,6 +116,7 @@ class AILSimplifier(Analysis):
115
116
  self._should_rewrite_ccalls = rewrite_ccalls
116
117
  self._removed_vvar_ids = removed_vvar_ids if removed_vvar_ids is not None else set()
117
118
  self._arg_vvars = arg_vvars
119
+ self._avoid_vvar_ids = avoid_vvar_ids
118
120
 
119
121
  self._calls_to_remove: set[CodeLocation] = set()
120
122
  self._assignments_to_remove: set[CodeLocation] = set()
@@ -552,7 +554,9 @@ class AILSimplifier(Analysis):
552
554
  if (
553
555
  first_op.op == "And"
554
556
  and isinstance(first_op.operands[1], Const)
555
- and (second_op is None or isinstance(second_op, BinaryOp) and isinstance(second_op.operands[1], Const))
557
+ and (
558
+ second_op is None or (isinstance(second_op, BinaryOp) and isinstance(second_op.operands[1], Const))
559
+ )
556
560
  ):
557
561
  mask = first_op.operands[1].value
558
562
  if mask == 0xFF:
@@ -615,6 +619,17 @@ class AILSimplifier(Analysis):
615
619
  stmt.ins_addr for stmt in block.statements
616
620
  }.intersection(insn_addrs_using_stack_args)
617
621
 
622
+ # remove virtual variables in the avoid list
623
+ if self._avoid_vvar_ids:
624
+ filtered_reps = {}
625
+ for loc, rep_dict in reps.items():
626
+ filtered_reps[loc] = {
627
+ k: v
628
+ for k, v in rep_dict.items()
629
+ if not (isinstance(k, VirtualVariable) and k.varid in self._avoid_vvar_ids)
630
+ }
631
+ reps = filtered_reps
632
+
618
633
  r, new_block = BlockSimplifier._replace_and_build(block, reps, gp=self._gp, replace_loads=replace_loads)
619
634
  replaced |= r
620
635
  self.blocks[block] = new_block
@@ -748,10 +763,8 @@ class AILSimplifier(Analysis):
748
763
  # the definition is in a callee function
749
764
  continue
750
765
 
751
- if (
752
- isinstance(the_def.codeloc, ExternalCodeLocation)
753
- or isinstance(eq.atom1, VirtualVariable)
754
- and eq.atom1.was_parameter
766
+ if isinstance(the_def.codeloc, ExternalCodeLocation) or (
767
+ isinstance(eq.atom1, VirtualVariable) and eq.atom1.was_parameter
755
768
  ):
756
769
  # this is a function argument. we enter a slightly different logic and try to eliminate copies of this
757
770
  # argument if
@@ -765,10 +778,8 @@ class AILSimplifier(Analysis):
765
778
 
766
779
  if defs and len(defs) == 1:
767
780
  arg_copy_def = defs[0]
768
- if (
769
- isinstance(arg_copy_def.atom, atoms.VirtualVariable)
770
- and arg_copy_def.atom.was_stack
771
- or (isinstance(arg_copy_def.atom, atoms.VirtualVariable) and arg_copy_def.atom.was_reg)
781
+ if (isinstance(arg_copy_def.atom, atoms.VirtualVariable) and arg_copy_def.atom.was_stack) or (
782
+ isinstance(arg_copy_def.atom, atoms.VirtualVariable) and arg_copy_def.atom.was_reg
772
783
  ):
773
784
  # found the copied definition (either a stack variable or a register variable)
774
785
 
@@ -919,7 +930,7 @@ class AILSimplifier(Analysis):
919
930
  continue
920
931
  block = addr_and_idx_to_block[(use_loc.block_addr, use_loc.block_idx)]
921
932
  stmt = block.statements[use_loc.stmt_idx]
922
- if isinstance(stmt, Assignment) or isinstance(replace_with, Load) and isinstance(stmt, Store):
933
+ if isinstance(stmt, Assignment) or (isinstance(replace_with, Load) and isinstance(stmt, Store)):
923
934
  assignment_ctr += 1
924
935
  if assignment_ctr > 1:
925
936
  continue
@@ -127,10 +127,8 @@ def _kmp_search_ail_obj(search_pattern, stmt_seq, graph=None, partial=True):
127
127
  start_pos = 0
128
128
  match_len = 0
129
129
  for c in stmt_seq:
130
- while (
131
- match_len == len(search_pattern)
132
- or match_len >= 0
133
- and not is_similar(search_pattern[match_len], c, graph=graph, partial=partial)
130
+ while match_len == len(search_pattern) or (
131
+ match_len >= 0 and not is_similar(search_pattern[match_len], c, graph=graph, partial=partial)
134
132
  ):
135
133
  start_pos += shifts[match_len]
136
134
  match_len -= shifts[match_len]
@@ -392,7 +392,7 @@ class CallSiteMaker(Analysis):
392
392
  return s
393
393
 
394
394
  def _determine_variadic_arguments(self, func: Function | None, cc: SimCC, call_stmt) -> int | None:
395
- if func is not None and "printf" in func.name or "scanf" in func.name:
395
+ if (func is not None and "printf" in func.name) or "scanf" in func.name:
396
396
  return self._determine_variadic_arguments_for_format_strings(func, cc, call_stmt)
397
397
  return None
398
398
 
@@ -8,8 +8,8 @@ class CCallRewriterBase:
8
8
  """
9
9
 
10
10
  __slots__ = (
11
- "result",
12
11
  "arch",
12
+ "result",
13
13
  )
14
14
 
15
15
  def __init__(self, ccall: ailment.Expr.VEXCCallExpression, arch):
@@ -600,7 +600,7 @@ class Clinic(Analysis):
600
600
  arg_list.append(arg_vvars[idx][1])
601
601
 
602
602
  # Get virtual variable mapping that can de-phi the SSA representation
603
- vvar2vvar = self._collect_dephi_vvar_mapping_and_rewrite_blocks(ail_graph)
603
+ vvar2vvar, copied_vvar_ids = self._collect_dephi_vvar_mapping_and_rewrite_blocks(ail_graph, arg_vvars)
604
604
 
605
605
  # Recover variables on AIL blocks
606
606
  self._update_progress(80.0, text="Recovering variables")
@@ -608,7 +608,11 @@ class Clinic(Analysis):
608
608
 
609
609
  # Run simplification passes
610
610
  self._update_progress(85.0, text="Running simplifications 4")
611
- ail_graph = self._run_simplification_passes(ail_graph, stage=OptimizationPassStage.AFTER_VARIABLE_RECOVERY)
611
+ ail_graph = self._run_simplification_passes(
612
+ ail_graph,
613
+ stage=OptimizationPassStage.AFTER_VARIABLE_RECOVERY,
614
+ avoid_vvar_ids=copied_vvar_ids,
615
+ )
612
616
 
613
617
  # Make function prototype
614
618
  self._update_progress(90.0, text="Making function prototype")
@@ -1389,16 +1393,19 @@ class Clinic(Analysis):
1389
1393
  return ssailification.out_graph
1390
1394
 
1391
1395
  @timethis
1392
- def _collect_dephi_vvar_mapping_and_rewrite_blocks(self, ail_graph: networkx.DiGraph) -> dict[int, int]:
1396
+ def _collect_dephi_vvar_mapping_and_rewrite_blocks(
1397
+ self, ail_graph: networkx.DiGraph, arg_vvars: dict[int, tuple[ailment.Expr.VirtualVariable, SimVariable]]
1398
+ ) -> tuple[dict[int, int], set[int]]:
1393
1399
  dephication = self.project.analyses.GraphDephicationVVarMapping(
1394
1400
  self.function,
1395
1401
  ail_graph,
1396
1402
  fail_fast=self._fail_fast,
1397
1403
  entry=next(iter(bb for bb in ail_graph if (bb.addr, bb.idx) == self.entry_node_addr)),
1398
1404
  vvar_id_start=self.vvar_id_start,
1405
+ arg_vvars=[arg_vvar for arg_vvar, _ in arg_vvars.values()],
1399
1406
  )
1400
1407
  self.vvar_id_start = dephication.vvar_id_start + 1
1401
- return dephication.vvar_to_vvar_mapping
1408
+ return dephication.vvar_to_vvar_mapping, dephication.copied_vvar_ids
1402
1409
 
1403
1410
  @timethis
1404
1411
  def _make_argument_list(self) -> list[SimVariable]:
@@ -1412,7 +1419,7 @@ class Clinic(Analysis):
1412
1419
  argvar = SimRegisterVariable(
1413
1420
  self.project.arch.registers[arg.reg_name][0],
1414
1421
  arg.size,
1415
- ident="arg_%d" % idx,
1422
+ ident=f"arg_{idx}",
1416
1423
  name=arg_names[idx],
1417
1424
  region=self.function.addr,
1418
1425
  )
@@ -1421,13 +1428,13 @@ class Clinic(Analysis):
1421
1428
  arg.stack_offset,
1422
1429
  arg.size,
1423
1430
  base="bp",
1424
- ident="arg_%d" % idx,
1431
+ ident=f"arg_{idx}",
1425
1432
  name=arg_names[idx],
1426
1433
  region=self.function.addr,
1427
1434
  )
1428
1435
  else:
1429
1436
  argvar = SimVariable(
1430
- ident="arg_%d" % idx,
1437
+ ident=f"arg_{idx}",
1431
1438
  name=arg_names[idx],
1432
1439
  region=self.function.addr,
1433
1440
  size=arg.size,
@@ -113,41 +113,53 @@ _ail2claripy_op_mapping = {
113
113
  "LogicalOr": lambda expr, conv, _, ia: claripy.Or(
114
114
  conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
115
115
  ),
116
- "CmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) == conv(expr.operands[1], ins_addr=ia),
117
- "CmpNE": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) != conv(expr.operands[1], ins_addr=ia),
118
- "CmpLE": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) <= conv(expr.operands[1], ins_addr=ia),
116
+ "CmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
117
+ == conv(expr.operands[1], nobool=True, ins_addr=ia),
118
+ "CmpNE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
119
+ != conv(expr.operands[1], nobool=True, ins_addr=ia),
120
+ "CmpLE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
121
+ <= conv(expr.operands[1], nobool=True, ins_addr=ia),
119
122
  "CmpLE (signed)": lambda expr, conv, _, ia: claripy.SLE(
120
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
123
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
121
124
  ),
122
- "CmpLT": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) < conv(expr.operands[1], ins_addr=ia),
125
+ "CmpLT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
126
+ < conv(expr.operands[1], nobool=True, ins_addr=ia),
123
127
  "CmpLT (signed)": lambda expr, conv, _, ia: claripy.SLT(
124
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
128
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
125
129
  ),
126
- "CmpGE": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) >= conv(expr.operands[1], ins_addr=ia),
130
+ "CmpGE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
131
+ >= conv(expr.operands[1], nobool=True, ins_addr=ia),
127
132
  "CmpGE (signed)": lambda expr, conv, _, ia: claripy.SGE(
128
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
133
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
129
134
  ),
130
- "CmpGT": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) > conv(expr.operands[1], ins_addr=ia),
135
+ "CmpGT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
136
+ > conv(expr.operands[1], nobool=True, ins_addr=ia),
131
137
  "CmpGT (signed)": lambda expr, conv, _, ia: claripy.SGT(
132
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
138
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
133
139
  ),
134
- "CasCmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) == conv(expr.operands[1], ins_addr=ia),
135
- "CasCmpNE": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) != conv(expr.operands[1], ins_addr=ia),
136
- "CasCmpLE": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) <= conv(expr.operands[1], ins_addr=ia),
140
+ "CasCmpEQ": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
141
+ == conv(expr.operands[1], nobool=True, ins_addr=ia),
142
+ "CasCmpNE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
143
+ != conv(expr.operands[1], nobool=True, ins_addr=ia),
144
+ "CasCmpLE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
145
+ <= conv(expr.operands[1], nobool=True, ins_addr=ia),
137
146
  "CasCmpLE (signed)": lambda expr, conv, _, ia: claripy.SLE(
138
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
147
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
139
148
  ),
140
- "CasCmpLT": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) < conv(expr.operands[1], ins_addr=ia),
149
+ "CasCmpLT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
150
+ < conv(expr.operands[1], nobool=True, ins_addr=ia),
141
151
  "CasCmpLT (signed)": lambda expr, conv, _, ia: claripy.SLT(
142
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
152
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
143
153
  ),
144
- "CasCmpGE": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) >= conv(expr.operands[1], ins_addr=ia),
154
+ "CasCmpGE": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
155
+ >= conv(expr.operands[1], nobool=True, ins_addr=ia),
145
156
  "CasCmpGE (signed)": lambda expr, conv, _, ia: claripy.SGE(
146
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
157
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
147
158
  ),
148
- "CasCmpGT": lambda expr, conv, _, ia: conv(expr.operands[0], ins_addr=ia) > conv(expr.operands[1], ins_addr=ia),
159
+ "CasCmpGT": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
160
+ > conv(expr.operands[1], nobool=True, ins_addr=ia),
149
161
  "CasCmpGT (signed)": lambda expr, conv, _, ia: claripy.SGT(
150
- conv(expr.operands[0], ins_addr=ia), conv(expr.operands[1], ins_addr=ia)
162
+ conv(expr.operands[0], nobool=True, ins_addr=ia), conv(expr.operands[1], nobool=True, ins_addr=ia)
151
163
  ),
152
164
  "Add": lambda expr, conv, _, ia: conv(expr.operands[0], nobool=True, ins_addr=ia)
153
165
  + conv(expr.operands[1], nobool=True, ins_addr=ia),
@@ -802,9 +814,13 @@ class ConditionProcessor:
802
814
  f"Condition variable {cond} has an unsupported operator {cond.op}. Consider implementing."
803
815
  )
804
816
 
805
- def claripy_ast_from_ail_condition(self, condition, nobool: bool = False, *, ins_addr: int = 0) -> claripy.ast.Bool:
817
+ def claripy_ast_from_ail_condition(
818
+ self, condition, nobool: bool = False, *, ins_addr: int = 0
819
+ ) -> claripy.ast.Bool | claripy.ast.Bits:
806
820
  # Unpack a condition all the way to the leaves
807
- if isinstance(condition, claripy.ast.Base): # pylint:disable=isinstance-second-argument-not-valid-type
821
+ if isinstance(
822
+ condition, (claripy.ast.Bits, claripy.ast.Bool)
823
+ ): # pylint:disable=isinstance-second-argument-not-valid-type
808
824
  return condition
809
825
 
810
826
  if isinstance(
@@ -832,11 +848,11 @@ class ConditionProcessor:
832
848
  # convert is special. if it generates a 1-bit variable, it should be treated as a BoolS
833
849
  if condition.to_bits == 1:
834
850
  var_ = self.claripy_ast_from_ail_condition(condition.operands[0], ins_addr=ins_addr)
835
- name = "ailcond_Conv(%d->%d, %d)" % (condition.from_bits, condition.to_bits, hash(var_))
851
+ name = f"ailcond_Conv({condition.from_bits}->{condition.to_bits}, {hash(var_)})"
836
852
  var = claripy.BoolS(name, explicit_name=True)
837
853
  else:
838
854
  var_ = self.claripy_ast_from_ail_condition(condition.operands[0], ins_addr=ins_addr)
839
- name = "ailexpr_Conv(%d->%d, %d)" % (condition.from_bits, condition.to_bits, hash(var_))
855
+ name = f"ailexpr_Conv({condition.from_bits}->{condition.to_bits}, {hash(var_)})"
840
856
  var = claripy.BVS(name, condition.to_bits, explicit_name=True)
841
857
  self._condition_mapping[var.args[0]] = condition
842
858
  return var
@@ -851,17 +867,17 @@ class ConditionProcessor:
851
867
  if isinstance(condition, ailment.Expr.Tmp):
852
868
  l.warning("Left-over ailment.Tmp variable %s.", condition)
853
869
  if condition.bits == 1:
854
- var = claripy.BoolS("ailtmp_%d" % condition.tmp_idx, explicit_name=True)
870
+ var = claripy.BoolS(f"ailtmp_{condition.tmp_idx}", explicit_name=True)
855
871
  else:
856
- var = claripy.BVS("ailtmp_%d" % condition.tmp_idx, condition.bits, explicit_name=True)
872
+ var = claripy.BVS(f"ailtmp_{condition.tmp_idx}", condition.bits, explicit_name=True)
857
873
  self._condition_mapping[var.args[0]] = condition
858
874
  return var
859
875
  if isinstance(condition, ailment.Expr.MultiStatementExpression):
860
876
  # just cache it
861
877
  if condition.bits == 1:
862
- var = claripy.BoolS("mstmtexpr_%d" % hash(condition), explicit_name=True)
878
+ var = claripy.BoolS(f"mstmtexpr_{hash(condition)}", explicit_name=True)
863
879
  else:
864
- var = claripy.BVS("mstmtexpr_%d" % hash(condition), condition.bits, explicit_name=True)
880
+ var = claripy.BVS(f"mstmtexpr_{hash(condition)}", condition.bits, explicit_name=True)
865
881
  self._condition_mapping[var.args[0]] = condition
866
882
  return var
867
883
 
@@ -885,7 +901,7 @@ class ConditionProcessor:
885
901
  self._condition_mapping[r.args[0]] = condition
886
902
 
887
903
  if r is NotImplemented:
888
- if condition.bits == 1:
904
+ if condition.bits == 1 and not nobool:
889
905
  r = claripy.BoolS(f"ailexpr_{condition!r}", explicit_name=True)
890
906
  else:
891
907
  r = claripy.BVS(f"ailexpr_{condition!r}", condition.bits, explicit_name=True)
@@ -7,10 +7,10 @@ from .expression_counters import SingleExpressionCounter, RegisterExpressionCoun
7
7
 
8
8
 
9
9
  __all__ = (
10
- "BooleanCounter",
11
10
  "AILBlockCallCounter",
11
+ "BooleanCounter",
12
12
  "ControlFlowStructureCounter",
13
- "SingleExpressionCounter",
14
- "RegisterExpressionCounter",
15
13
  "OperatorCounter",
14
+ "RegisterExpressionCounter",
15
+ "SingleExpressionCounter",
16
16
  )
@@ -14,16 +14,16 @@ class DecompilationCache:
14
14
  """
15
15
 
16
16
  __slots__ = (
17
- "parameters",
18
17
  "addr",
19
- "type_constraints",
20
- "func_typevar",
21
- "var_to_typevar",
22
- "codegen",
23
- "clinic",
24
- "ite_exprs",
25
18
  "binop_operators",
19
+ "clinic",
20
+ "codegen",
26
21
  "errors",
22
+ "func_typevar",
23
+ "ite_exprs",
24
+ "parameters",
25
+ "type_constraints",
26
+ "var_to_typevar",
27
27
  )
28
28
 
29
29
  def __init__(self, addr):
@@ -3,4 +3,4 @@ from .graph_vvar_mapping import GraphDephicationVVarMapping
3
3
  from .graph_dephication import GraphDephication
4
4
  from .seqnode_dephication import SeqNodeDephication
5
5
 
6
- __all__ = ["GraphDephicationVVarMapping", "GraphDephication", "SeqNodeDephication"]
6
+ __all__ = ["GraphDephication", "GraphDephicationVVarMapping", "SeqNodeDephication"]
@@ -10,7 +10,7 @@ from angr.analyses import Analysis
10
10
  from angr.analyses.s_reaching_definitions import SRDAModel
11
11
  from angr.knowledge_plugins.functions import Function
12
12
  from angr.analyses import register_analysis
13
- from angr.utils.ssa import is_phi_assignment
13
+ from angr.utils.ssa import is_phi_assignment, DEPHI_VVAR_REG_OFFSET
14
14
 
15
15
  l = logging.getLogger(name=__name__)
16
16
 
@@ -30,6 +30,7 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
30
30
  ail_graph,
31
31
  entry=None,
32
32
  vvar_id_start: int = 0,
33
+ arg_vvars: list[VirtualVariable] | None = None,
33
34
  ):
34
35
  """
35
36
  :param func: The subject of the analysis: a function, or a single basic block
@@ -49,8 +50,10 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
49
50
  self._vvar_defloc = {}
50
51
  self.vvar_id_start = vvar_id_start
51
52
  self._stmts_to_prepend = defaultdict(list)
53
+ self._arg_vvars = arg_vvars or []
52
54
 
53
55
  self.vvar_to_vvar_mapping = None
56
+ self.copied_vvar_ids: set[int] = set()
54
57
  self._rd: SRDAModel = self.project.analyses.SReachingDefinitions(
55
58
  subject=self._function, func_graph=self._graph
56
59
  ).model
@@ -74,7 +77,9 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
74
77
  phi_congruence_class[varid] = {varid}
75
78
 
76
79
  # compute liveness
77
- liveness = self.project.analyses.SLiveness(self._function, func_graph=self._graph, entry=self._entry)
80
+ liveness = self.project.analyses.SLiveness(
81
+ self._function, func_graph=self._graph, entry=self._entry, arg_vvars=self._arg_vvars
82
+ )
78
83
 
79
84
  live_ins = liveness.model.live_ins
80
85
  live_outs = liveness.model.live_outs
@@ -136,6 +141,8 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
136
141
 
137
142
  if insertion_type == 0:
138
143
  for src, old_vvar_id, new_vvar_id in new_vvar_ids:
144
+ self.copied_vvar_ids.add(new_vvar_id)
145
+
139
146
  phi_congruence_class[new_vvar_id] = {new_vvar_id}
140
147
  live_outs[src].add(new_vvar_id)
141
148
 
@@ -153,6 +160,7 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
153
160
 
154
161
  else: # insertion_type == 1
155
162
  phi_block_loc, old_phi_varid, new_phi_varid = next(iter(new_vvar_ids))
163
+ self.copied_vvar_ids.add(new_phi_varid)
156
164
 
157
165
  phi_congruence_class[new_phi_varid] = {new_phi_varid}
158
166
 
@@ -217,7 +225,7 @@ class GraphDephicationVVarMapping(Analysis): # pylint:disable=abstract-method
217
225
  # it's a parameter, so we copy the variable into a dummy register vvar
218
226
  # a parameter vvar should never be assigned to
219
227
  new_category = VirtualVariableCategory.REGISTER
220
- new_oident = 4096
228
+ new_oident = DEPHI_VVAR_REG_OFFSET
221
229
  else:
222
230
  new_category = vvar.category
223
231
  new_oident = vvar.oident
@@ -31,7 +31,7 @@ class ExprNarrowingInfo:
31
31
  Stores the analysis result of _narrowing_needed().
32
32
  """
33
33
 
34
- __slots__ = ("narrowable", "to_size", "use_exprs", "phi_vars")
34
+ __slots__ = ("narrowable", "phi_vars", "to_size", "use_exprs")
35
35
 
36
36
  def __init__(
37
37
  self,
@@ -23,15 +23,15 @@ class GraphRegion:
23
23
  """
24
24
 
25
25
  __slots__ = (
26
- "head",
27
- "graph",
28
- "successors",
29
- "graph_with_successors",
30
- "cyclic",
31
- "full_graph",
32
- "cyclic_ancestor",
33
26
  "_node_to_replaced_regions",
34
27
  "_replaced_regions",
28
+ "cyclic",
29
+ "cyclic_ancestor",
30
+ "full_graph",
31
+ "graph",
32
+ "graph_with_successors",
33
+ "head",
34
+ "successors",
35
35
  )
36
36
 
37
37
  def __init__(
@@ -74,7 +74,7 @@ class GraphRegion:
74
74
  if addrs:
75
75
  s = f": {min(addrs):#x}-{max(addrs):#x}"
76
76
 
77
- return "<GraphRegion %r of %d nodes%s>" % (self.head, self.graph.number_of_nodes(), s)
77
+ return f"<GraphRegion {self.head!r} of {self.graph.number_of_nodes()} nodes{s}>"
78
78
 
79
79
  def copy(self) -> GraphRegion:
80
80
  return GraphRegion(