angr 9.2.158__cp310-abi3-macosx_11_0_arm64.whl → 9.2.160__cp310-abi3-macosx_11_0_arm64.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 (195) hide show
  1. angr/__init__.py +1 -1
  2. angr/ailment/__init__.py +81 -0
  3. angr/ailment/block.py +81 -0
  4. angr/ailment/block_walker.py +845 -0
  5. angr/ailment/constant.py +3 -0
  6. angr/ailment/converter_common.py +11 -0
  7. angr/ailment/converter_pcode.py +623 -0
  8. angr/ailment/converter_vex.py +798 -0
  9. angr/ailment/expression.py +1639 -0
  10. angr/ailment/manager.py +33 -0
  11. angr/ailment/statement.py +978 -0
  12. angr/ailment/tagged_object.py +61 -0
  13. angr/ailment/utils.py +114 -0
  14. angr/analyses/calling_convention/calling_convention.py +6 -2
  15. angr/analyses/decompiler/ail_simplifier.py +5 -5
  16. angr/analyses/decompiler/block_io_finder.py +4 -4
  17. angr/analyses/decompiler/block_similarity.py +2 -2
  18. angr/analyses/decompiler/block_simplifier.py +4 -4
  19. angr/analyses/decompiler/callsite_maker.py +2 -2
  20. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -1
  21. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +1 -1
  22. angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +1 -1
  23. angr/analyses/decompiler/clinic.py +5 -2
  24. angr/analyses/decompiler/condition_processor.py +1 -1
  25. angr/analyses/decompiler/counters/boolean_counter.py +4 -4
  26. angr/analyses/decompiler/counters/call_counter.py +4 -4
  27. angr/analyses/decompiler/counters/expression_counters.py +5 -5
  28. angr/analyses/decompiler/counters/seq_cf_structure_counter.py +1 -1
  29. angr/analyses/decompiler/decompiler.py +17 -12
  30. angr/analyses/decompiler/dephication/dephication_base.py +12 -1
  31. angr/analyses/decompiler/dephication/graph_dephication.py +12 -5
  32. angr/analyses/decompiler/dephication/graph_rewriting.py +6 -10
  33. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +109 -72
  34. angr/analyses/decompiler/dephication/rewriting_engine.py +32 -9
  35. angr/analyses/decompiler/dephication/seqnode_dephication.py +32 -10
  36. angr/analyses/decompiler/empty_node_remover.py +2 -2
  37. angr/analyses/decompiler/expression_narrower.py +6 -6
  38. angr/analyses/decompiler/goto_manager.py +2 -2
  39. angr/analyses/decompiler/jump_target_collector.py +1 -1
  40. angr/analyses/decompiler/label_collector.py +1 -1
  41. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +25 -25
  42. angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +1 -1
  43. angr/analyses/decompiler/optimization_passes/code_motion.py +2 -2
  44. angr/analyses/decompiler/optimization_passes/condition_constprop.py +3 -3
  45. angr/analyses/decompiler/optimization_passes/const_derefs.py +3 -3
  46. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +4 -4
  47. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +2 -2
  48. angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +3 -3
  49. angr/analyses/decompiler/optimization_passes/div_simplifier.py +1 -1
  50. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +2 -2
  51. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +4 -4
  52. angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +1 -1
  53. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +4 -4
  54. angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +3 -3
  55. angr/analyses/decompiler/optimization_passes/engine_base.py +1 -1
  56. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +3 -3
  57. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
  58. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +2 -2
  59. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +3 -3
  60. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +3 -3
  61. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +4 -4
  62. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +1 -1
  63. angr/analyses/decompiler/optimization_passes/optimization_pass.py +25 -1
  64. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +1 -1
  65. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +1 -1
  66. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +2 -2
  67. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +4 -4
  68. angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +2 -2
  69. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
  70. angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +3 -3
  71. angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +3 -3
  72. angr/analyses/decompiler/optimization_passes/tag_slicer.py +1 -1
  73. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -1
  74. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +1 -1
  75. angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +1 -1
  76. angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +1 -1
  77. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +1 -1
  78. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +1 -1
  79. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +1 -1
  80. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div_const_mul_const.py +1 -1
  81. angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +1 -1
  82. angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +1 -1
  83. angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +1 -1
  84. angr/analyses/decompiler/peephole_optimizations/base.py +3 -3
  85. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +1 -1
  86. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +1 -1
  87. angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +1 -1
  88. angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +1 -1
  89. angr/analyses/decompiler/peephole_optimizations/bswap.py +2 -2
  90. angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +2 -2
  91. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +2 -2
  92. angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +1 -1
  93. angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +2 -2
  94. angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -1
  95. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +1 -1
  96. angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +1 -1
  97. angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +1 -1
  98. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
  99. angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +1 -1
  100. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +2 -2
  101. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +2 -2
  102. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +2 -2
  103. angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +1 -1
  104. angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +1 -1
  105. angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +1 -1
  106. angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +2 -2
  107. angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +2 -2
  108. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +1 -1
  109. angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +1 -1
  110. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +1 -1
  111. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +1 -1
  112. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +1 -1
  113. angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +1 -1
  114. angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +1 -1
  115. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +1 -1
  116. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +1 -1
  117. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +1 -1
  118. angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +1 -1
  119. angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +3 -3
  120. angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +1 -1
  121. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +2 -2
  122. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -1
  123. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +1 -1
  124. angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +1 -1
  125. angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +1 -1
  126. angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +1 -1
  127. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +2 -2
  128. angr/analyses/decompiler/peephole_optimizations/utils.py +1 -1
  129. angr/analyses/decompiler/redundant_label_remover.py +1 -1
  130. angr/analyses/decompiler/region_identifier.py +4 -4
  131. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -1
  132. angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +1 -1
  133. angr/analyses/decompiler/region_simplifiers/expr_folding.py +37 -8
  134. angr/analyses/decompiler/region_simplifiers/goto.py +1 -1
  135. angr/analyses/decompiler/region_simplifiers/if_.py +1 -1
  136. angr/analyses/decompiler/region_simplifiers/loop.py +1 -1
  137. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -1
  138. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +14 -2
  139. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +3 -3
  140. angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +1 -1
  141. angr/analyses/decompiler/return_maker.py +1 -1
  142. angr/analyses/decompiler/seq_to_blocks.py +1 -1
  143. angr/analyses/decompiler/sequence_walker.py +2 -2
  144. angr/analyses/decompiler/ssailification/rewriting.py +4 -4
  145. angr/analyses/decompiler/ssailification/rewriting_engine.py +4 -4
  146. angr/analyses/decompiler/ssailification/rewriting_state.py +3 -3
  147. angr/analyses/decompiler/ssailification/ssailification.py +2 -2
  148. angr/analyses/decompiler/ssailification/traversal.py +1 -1
  149. angr/analyses/decompiler/ssailification/traversal_engine.py +11 -2
  150. angr/analyses/decompiler/structured_codegen/c.py +3 -3
  151. angr/analyses/decompiler/structuring/dream.py +1 -1
  152. angr/analyses/decompiler/structuring/phoenix.py +3 -3
  153. angr/analyses/decompiler/structuring/structurer_base.py +1 -1
  154. angr/analyses/decompiler/structuring/structurer_nodes.py +1 -2
  155. angr/analyses/decompiler/utils.py +1 -1
  156. angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +1 -1
  157. angr/analyses/deobfuscator/string_obf_opt_passes.py +3 -3
  158. angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +2 -2
  159. angr/analyses/propagator/propagator.py +1 -1
  160. angr/analyses/proximity_graph.py +2 -2
  161. angr/analyses/reaching_definitions/engine_ail.py +1 -1
  162. angr/analyses/reaching_definitions/reaching_definitions.py +1 -1
  163. angr/analyses/reaching_definitions/subject.py +1 -1
  164. angr/analyses/s_liveness.py +2 -2
  165. angr/analyses/s_propagator.py +3 -3
  166. angr/analyses/s_reaching_definitions/s_rda_model.py +1 -1
  167. angr/analyses/s_reaching_definitions/s_rda_view.py +3 -3
  168. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -3
  169. angr/analyses/typehoon/simple_solver.py +231 -29
  170. angr/analyses/typehoon/typehoon.py +10 -2
  171. angr/analyses/variable_recovery/engine_ail.py +10 -22
  172. angr/analyses/variable_recovery/engine_base.py +1 -1
  173. angr/analyses/variable_recovery/variable_recovery_base.py +1 -1
  174. angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
  175. angr/engines/light/data.py +1 -1
  176. angr/engines/light/engine.py +1 -1
  177. angr/knowledge_plugins/key_definitions/atoms.py +1 -1
  178. angr/knowledge_plugins/propagations/prop_value.py +1 -1
  179. angr/knowledge_plugins/propagations/propagation_model.py +1 -1
  180. angr/knowledge_plugins/propagations/states.py +1 -1
  181. angr/knowledge_plugins/variables/variable_manager.py +1 -1
  182. angr/rustylib.abi3.so +0 -0
  183. angr/state_plugins/unicorn_engine.py +4 -4
  184. angr/{lib/angr_native.dylib → unicornlib.dylib} +0 -0
  185. angr/utils/ail.py +4 -4
  186. angr/utils/endness.py +1 -1
  187. angr/utils/ssa/__init__.py +14 -4
  188. angr/utils/ssa/tmp_uses_collector.py +4 -4
  189. angr/utils/ssa/vvar_uses_collector.py +4 -4
  190. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/METADATA +6 -7
  191. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/RECORD +195 -183
  192. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/WHEEL +0 -0
  193. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/entry_points.txt +0 -0
  194. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/licenses/LICENSE +0 -0
  195. {angr-9.2.158.dist-info → angr-9.2.160.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ from collections import defaultdict, OrderedDict
7
7
  import networkx
8
8
 
9
9
  import claripy
10
- import ailment
10
+ import angr.ailment as ailment
11
11
 
12
12
  from angr.utils.graph import GraphUtils
13
13
  from angr.knowledge_plugins.cfg import IndirectJumpType
@@ -9,9 +9,9 @@ import logging
9
9
  import networkx
10
10
 
11
11
  import claripy
12
- from ailment.block import Block
13
- from ailment.statement import Statement, ConditionalJump, Jump, Label, Return
14
- from ailment.expression import Const, UnaryOp, MultiStatementExpression
12
+ from angr.ailment.block import Block
13
+ from angr.ailment.statement import Statement, ConditionalJump, Jump, Label, Return
14
+ from angr.ailment.expression import Const, UnaryOp, MultiStatementExpression
15
15
 
16
16
  from angr.utils.graph import GraphUtils
17
17
  from angr.utils.ail import is_phi_assignment, is_head_controlled_loop_block
@@ -6,7 +6,7 @@ import logging
6
6
 
7
7
  import networkx
8
8
 
9
- import ailment
9
+ import angr.ailment as ailment
10
10
  import claripy
11
11
 
12
12
  from angr.analyses import Analysis
@@ -4,8 +4,7 @@ from typing import Any
4
4
  from collections import OrderedDict
5
5
 
6
6
  import claripy
7
- import ailment
8
- import ailment.utils
7
+ import angr.ailment as ailment
9
8
 
10
9
 
11
10
  INDENT_DELTA = 2
@@ -7,7 +7,7 @@ from collections.abc import Iterable
7
7
  import logging
8
8
 
9
9
  import networkx
10
- import ailment
10
+ import angr.ailment as ailment
11
11
 
12
12
  import angr
13
13
  from angr.analyses.decompiler.counters.call_counter import AILBlockCallCounter
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from ailment.expression import Const, Load
2
+ from angr.ailment.expression import Const, Load
3
3
 
4
4
  from angr import SIM_LIBRARIES
5
5
  from angr.calling_conventions import default_cc
@@ -3,9 +3,9 @@ from __future__ import annotations
3
3
 
4
4
  import archinfo
5
5
 
6
- from ailment import Block
7
- from ailment.statement import Statement, Call, Assignment
8
- from ailment.expression import Const, Register, VirtualVariable
6
+ from angr.ailment import Block
7
+ from angr.ailment.statement import Statement, Call, Assignment
8
+ from angr.ailment.expression import Const, Register, VirtualVariable
9
9
 
10
10
  from angr.analyses.decompiler.optimization_passes.optimization_pass import OptimizationPass, OptimizationPassStage
11
11
  from angr.analyses.decompiler.optimization_passes import register_optimization_pass
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
- from ailment.statement import Call
3
- from ailment.expression import Const
2
+ from angr.ailment.statement import Call
3
+ from angr.ailment.expression import Const
4
4
  import claripy
5
5
 
6
6
  from angr.analyses.decompiler.peephole_optimizations.base import PeepholeOptimizationExprBase
@@ -6,7 +6,7 @@ import time
6
6
  import contextlib
7
7
 
8
8
  import claripy
9
- import ailment
9
+ import angr.ailment as ailment
10
10
  import pyvex
11
11
 
12
12
  from angr.code_location import CodeLocation
@@ -4,8 +4,8 @@ import logging
4
4
 
5
5
  import networkx
6
6
 
7
- import ailment
8
- from ailment import AILBlockWalker
7
+ import angr.ailment as ailment
8
+ from angr.ailment import AILBlockWalker
9
9
 
10
10
  from angr.codenode import BlockNode
11
11
  from angr.sim_variable import SimMemoryVariable
@@ -7,7 +7,7 @@ from typing import cast
7
7
 
8
8
  from archinfo.types import RegisterOffset
9
9
  import claripy
10
- import ailment
10
+ import angr.ailment as ailment
11
11
  from claripy import FSORT_DOUBLE, FSORT_FLOAT
12
12
 
13
13
  from angr.engines.light import SpOffset
@@ -4,7 +4,7 @@ from typing import Any
4
4
  from collections.abc import Iterable
5
5
  from collections import defaultdict
6
6
 
7
- import ailment
7
+ import angr.ailment as ailment
8
8
  import pyvex
9
9
 
10
10
  from angr.analyses import ForwardAnalysis
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
  from enum import Enum
3
3
 
4
- import ailment
4
+ import angr.ailment as ailment
5
5
 
6
6
  from angr.block import Block
7
7
  from angr.knowledge_plugins.functions.function_manager import Function
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import networkx
4
- from ailment.expression import VirtualVariable
5
- from ailment.statement import Assignment, Call, ConditionalJump
4
+ from angr.ailment.expression import VirtualVariable
5
+ from angr.ailment.statement import Assignment, Call, ConditionalJump
6
6
 
7
7
  from angr.analyses import Analysis, register_analysis
8
8
  from angr.utils.ail import is_head_controlled_loop_block, is_phi_assignment
@@ -6,8 +6,8 @@ from collections import defaultdict
6
6
 
7
7
  import networkx
8
8
 
9
- from ailment.block import Block
10
- from ailment.expression import (
9
+ from angr.ailment.block import Block
10
+ from angr.ailment.expression import (
11
11
  Const,
12
12
  VirtualVariable,
13
13
  VirtualVariableCategory,
@@ -16,7 +16,7 @@ from ailment.expression import (
16
16
  Convert,
17
17
  Expression,
18
18
  )
19
- from ailment.statement import Assignment, Store, Return, Jump, ConditionalJump
19
+ from angr.ailment.statement import Assignment, Store, Return, Jump, ConditionalJump
20
20
 
21
21
  from angr.knowledge_plugins.functions import Function
22
22
  from angr.code_location import CodeLocation, ExternalCodeLocation
@@ -4,7 +4,7 @@ from collections import defaultdict
4
4
  from collections.abc import Generator
5
5
  from typing import Any, Literal, overload
6
6
 
7
- from ailment.expression import VirtualVariable, Tmp
7
+ from angr.ailment.expression import VirtualVariable, Tmp
8
8
 
9
9
  from angr.knowledge_plugins.key_definitions import atoms, Definition
10
10
  from angr.code_location import CodeLocation
@@ -4,9 +4,9 @@ import logging
4
4
  from collections.abc import Callable
5
5
  from collections import defaultdict
6
6
 
7
- from ailment import Block
8
- from ailment.statement import Statement, Assignment, Call, Label
9
- from ailment.expression import VirtualVariable, VirtualVariableCategory, Expression
7
+ from angr.ailment import Block
8
+ from angr.ailment.statement import Statement, Assignment, Call, Label
9
+ from angr.ailment.expression import VirtualVariable, VirtualVariableCategory, Expression
10
10
 
11
11
  from angr.utils.ail import is_phi_assignment
12
12
  from angr.utils.graph import GraphUtils
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from ailment.block import Block
4
- from ailment.statement import Assignment, Call, Return
5
- from ailment.expression import VirtualVariable
3
+ from angr.ailment.block import Block
4
+ from angr.ailment.statement import Assignment, Call, Return
5
+ from angr.ailment.expression import VirtualVariable
6
6
  import networkx
7
7
 
8
8
  from angr.knowledge_plugins.functions import Function
@@ -1,4 +1,4 @@
1
- # pylint:disable=missing-class-docstring
1
+ # pylint:disable=missing-class-docstring,too-many-boolean-expressions
2
2
  from __future__ import annotations
3
3
  import enum
4
4
  from collections import defaultdict
@@ -432,7 +432,14 @@ class SimpleSolver:
432
432
  improvements.
433
433
  """
434
434
 
435
- def __init__(self, bits: int, constraints, typevars, stackvar_max_sizes: dict[TypeVariable, int] | None = None):
435
+ def __init__(
436
+ self,
437
+ bits: int,
438
+ constraints,
439
+ typevars,
440
+ constraint_set_degradation_threshold: int = 150,
441
+ stackvar_max_sizes: dict[TypeVariable, int] | None = None,
442
+ ):
436
443
  if bits not in (32, 64):
437
444
  raise ValueError(f"Pointer size {bits} is not supported. Expect 32 or 64.")
438
445
 
@@ -440,6 +447,7 @@ class SimpleSolver:
440
447
  self._constraints: dict[TypeVariable, set[TypeConstraint]] = constraints
441
448
  self._typevars: set[TypeVariable] = typevars
442
449
  self.stackvar_max_sizes = stackvar_max_sizes if stackvar_max_sizes is not None else {}
450
+ self._constraint_set_degradation_threshold = constraint_set_degradation_threshold
443
451
  self._base_lattice = BASE_LATTICES[bits]
444
452
  self._base_lattice_inverted = networkx.DiGraph()
445
453
  for src, dst in self._base_lattice.edges:
@@ -459,7 +467,11 @@ class SimpleSolver:
459
467
  self.processed_constraints_count += len(self._constraints[typevar])
460
468
 
461
469
  self._constraints[typevar] |= self._eq_constraints_from_add(typevar)
462
- self._constraints[typevar] = self._handle_equivalence(typevar)
470
+ self._constraints[typevar] |= self._discover_equivalence(self._constraints[typevar])
471
+ new_constraints, replacements = self._handle_equivalence(self._constraints[typevar])
472
+ self._equivalence |= replacements
473
+ self._constraints[typevar] = new_constraints
474
+ self._constraints[typevar] = self._filter_constraints(self._constraints[typevar])
463
475
 
464
476
  self.simplified_constraints_count += len(self._constraints[typevar])
465
477
 
@@ -517,11 +529,18 @@ class SimpleSolver:
517
529
 
518
530
  _, sketches = self.infer_shapes(typevars, constraints)
519
531
  constraintset2tvs = defaultdict(set)
532
+ tvs_seen = set()
520
533
  for idx, tv in enumerate(constrained_typevars):
521
534
  _l.debug("Collecting constraints for type variable %r (%d/%d)", tv, idx + 1, len(constrained_typevars))
535
+ if tv in tvs_seen:
536
+ continue
522
537
  # build a sub constraint set for the type variable
523
- constraint_subset = frozenset(self._generate_constraint_subset(constraints, {tv}))
524
- constraintset2tvs[constraint_subset].add(tv)
538
+ constraint_subset, related_tvs = self._generate_constraint_subset(constraints, {tv})
539
+ # drop all type vars outside constrained_typevars
540
+ related_tvs = related_tvs.intersection(constrained_typevars)
541
+ tvs_seen |= related_tvs
542
+ frozen_constraint_subset = frozenset(constraint_subset)
543
+ constraintset2tvs[frozen_constraint_subset] = related_tvs
525
544
 
526
545
  for idx, (constraint_subset, tvs) in enumerate(constraintset2tvs.items()):
527
546
  _l.debug(
@@ -534,8 +553,31 @@ class SimpleSolver:
534
553
  )
535
554
  self.eqclass_constraints_count.append(len(constraint_subset))
536
555
 
537
- while True:
538
- base_constraint_graph = self._generate_constraint_graph(constraint_subset, tvs | PRIMITIVE_TYPES)
556
+ if len(constraint_subset) > self._constraint_set_degradation_threshold:
557
+ _l.debug(
558
+ "Constraint subset contains %d constraints, which is over the limit of %d. Enter degradation.",
559
+ len(constraint_subset),
560
+ self._constraint_set_degradation_threshold,
561
+ )
562
+ constraint_subset = self._degrade_constraint_set(constraint_subset)
563
+ _l.debug("Degraded constraint subset to %d constraints.", len(constraint_subset))
564
+
565
+ while constraint_subset:
566
+
567
+ _l.debug("Working with %d constraints.", len(constraint_subset))
568
+
569
+ # remove constraints that are a <: b where a only appears once; in this case, the solution fo a is
570
+ # entirely determined by the solution of b (which is the upper bound of a)
571
+ filtered_constraint_subset, ub_subtypes = self._filter_leaf_typevars(constraint_subset, tvs)
572
+ _l.debug(
573
+ "Filtered %d leaf typevars; %d constraints remain.",
574
+ len(ub_subtypes),
575
+ len(filtered_constraint_subset),
576
+ )
577
+
578
+ base_constraint_graph = self._generate_constraint_graph(
579
+ filtered_constraint_subset, tvs | PRIMITIVE_TYPES
580
+ )
539
581
  primitive_constraints = self._generate_primitive_constraints(tvs, base_constraint_graph)
540
582
  tvs_with_primitive_constraints = set()
541
583
  for primitive_constraint in primitive_constraints:
@@ -546,12 +588,22 @@ class SimpleSolver:
546
588
  solutions = {}
547
589
  self.determine(sketches, tvs_with_primitive_constraints, solutions)
548
590
  _l.debug("Determined solutions for %d type variable(s).", len(tvs_with_primitive_constraints))
591
+
592
+ leaf_solutions = 0
593
+ for tv_, ub_tv in ub_subtypes.items():
594
+ if ub_tv in solutions:
595
+ solutions[tv_] = solutions[ub_tv]
596
+ leaf_solutions += 1
597
+ elif isinstance(ub_tv, TypeConstant):
598
+ solutions[tv_] = ub_tv
599
+ leaf_solutions += 1
600
+ _l.debug("Determined solutions for %d leaf type variable(s).", leaf_solutions)
601
+
549
602
  if not solutions:
550
603
  break
551
-
552
604
  self.solution |= solutions
553
605
 
554
- tvs = {tv for tv in tvs if tv not in tvs_with_primitive_constraints}
606
+ tvs = {tv for tv in tvs if tv not in solutions}
555
607
  if not tvs:
556
608
  break
557
609
  # rewrite existing constraints
@@ -559,7 +611,7 @@ class SimpleSolver:
559
611
  for constraint in constraint_subset:
560
612
  rewritten = self._rewrite_constraint(constraint, solutions)
561
613
  new_constraint_subset.add(rewritten)
562
- constraint_subset = new_constraint_subset
614
+ constraint_subset = self._filter_constraints(new_constraint_subset)
563
615
 
564
616
  # set the solution for missing type vars to TOP
565
617
  self.determine(sketches, set(sketches).difference(set(self.solution)), self.solution)
@@ -775,14 +827,45 @@ class SimpleSolver:
775
827
  new_constraints.add(Equivalence(constraint.type_1, constraint.type_r))
776
828
  return new_constraints
777
829
 
778
- def _handle_equivalence(self, typevar: TypeVariable):
830
+ @staticmethod
831
+ def _discover_equivalence(constraints: set[TypeConstraint]) -> set[Equivalence]:
832
+ """
833
+ a <:b && b <: a ==> a == b
834
+ """
835
+
836
+ new_eq_constraints: set[Equivalence] = set()
837
+ subtypes = defaultdict(set)
838
+ for constraint in constraints:
839
+ if isinstance(constraint, Subtype):
840
+ sub_type = constraint.sub_type
841
+ super_type = constraint.super_type
842
+ subtypes[sub_type].add(super_type)
843
+
844
+ # check everything
845
+ seen = set()
846
+ for tv, tv_supers in subtypes.items():
847
+ for tv_super in tv_supers:
848
+ if tv_super in subtypes and tv in subtypes[tv_super]: # noqa: SIM102
849
+ # we have a pair of subtypes that are equivalent
850
+ if (tv, tv_super) not in seen and (tv_super, tv) not in seen:
851
+ new_eq_constraints.add(Equivalence(tv, tv_super))
852
+ seen.add((tv, tv_super))
853
+
854
+ _l.debug(
855
+ "Discovered %d equivalence constraints from %d constraints.", len(new_eq_constraints), len(constraints)
856
+ )
857
+ return new_eq_constraints
858
+
859
+ @staticmethod
860
+ def _handle_equivalence(
861
+ constraint_set: set[TypeConstraint],
862
+ ) -> tuple[set[TypeConstraint], dict[TypeVariable, TypeVariable | TypeConstant]]:
779
863
  graph = networkx.Graph()
780
864
 
781
- replacements = {}
782
- constraints = set()
865
+ replacements: dict[TypeVariable, TypeVariable | TypeConstant] = {}
783
866
 
784
867
  # collect equivalence relations
785
- for constraint in self._constraints[typevar]:
868
+ for constraint in constraint_set:
786
869
  if isinstance(constraint, Equivalence):
787
870
  # | type_a == type_b
788
871
  # we apply unification and removes one of them
@@ -803,15 +886,30 @@ class SimpleSolver:
803
886
  for tv in components_lst[1:]:
804
887
  replacements[tv] = representative
805
888
 
806
- # replace
807
- for constraint in self._constraints[typevar]:
889
+ constraints = SimpleSolver._rewrite_constraints_with_replacements(constraint_set, replacements)
890
+
891
+ # import pprint
892
+ # print("Replacements")
893
+ # pprint.pprint(replacements)
894
+ # print("Constraints (after replacement)")
895
+ # pprint.pprint(constraints)
896
+
897
+ return constraints, replacements
898
+
899
+ @staticmethod
900
+ def _rewrite_constraints_with_replacements(
901
+ constraints: set[TypeConstraint], replacements: dict[TypeVariable, TypeVariable]
902
+ ) -> set[TypeConstraint]:
903
+ # replace constraints according to a dictionary of type variable replacements
904
+ replaced_constraints = set()
905
+ for constraint in constraints:
808
906
  if isinstance(constraint, Existence):
809
907
  replaced, new_constraint = constraint.replace(replacements)
810
908
 
811
909
  if replaced:
812
- constraints.add(new_constraint)
910
+ replaced_constraints.add(new_constraint)
813
911
  else:
814
- constraints.add(constraint)
912
+ replaced_constraints.add(constraint)
815
913
 
816
914
  elif isinstance(constraint, Subtype):
817
915
  # subtype <: supertype
@@ -819,18 +917,122 @@ class SimpleSolver:
819
917
  replaced, new_constraint = constraint.replace(replacements)
820
918
 
821
919
  if replaced:
822
- constraints.add(new_constraint)
920
+ replaced_constraints.add(new_constraint)
823
921
  else:
824
- constraints.add(constraint)
922
+ replaced_constraints.add(constraint)
923
+ return replaced_constraints
825
924
 
826
- # import pprint
827
- # print("Replacements")
828
- # pprint.pprint(replacements)
829
- # print("Constraints (after replacement)")
830
- # pprint.pprint(constraints)
925
+ @staticmethod
926
+ def _filter_constraints(constraints: set[TypeConstraint]) -> set[TypeConstraint]:
927
+ """
928
+ Filter out constraints that we don't yet support.
929
+ """
930
+
931
+ filtered_constraints = set()
932
+ for constraint in constraints:
933
+ dropped = False
934
+ if isinstance(constraint, Subtype) and (
935
+ (isinstance(constraint.sub_type, TypeConstant) and isinstance(constraint.super_type, TypeConstant))
936
+ or (
937
+ isinstance(constraint.sub_type, DerivedTypeVariable)
938
+ and isinstance(constraint.sub_type.labels[-1], ConvertTo)
939
+ )
940
+ or (
941
+ isinstance(constraint.sub_type, TypeVariable)
942
+ and isinstance(constraint.super_type, TypeVariable)
943
+ and constraint.sub_type == constraint.super_type
944
+ )
945
+ ):
946
+ dropped = True
831
947
 
832
- self._equivalence = replacements
833
- return constraints
948
+ if not dropped:
949
+ filtered_constraints.add(constraint)
950
+
951
+ return filtered_constraints
952
+
953
+ @staticmethod
954
+ def _filter_leaf_typevars(
955
+ constraints: set[TypeConstraint], tvs_to_solve: set[TypeVariable]
956
+ ) -> tuple[set[TypeConstraint], dict[TypeVariable, TypeVariable]]:
957
+ """
958
+ Filter out leaf type variables that only appear once in the constraints. These type variables are not
959
+ interesting and can be removed from the constraints.
960
+ """
961
+
962
+ sub_typevars = defaultdict(set)
963
+ tv_to_dtvs: dict[TypeVariable, set[TypeVariable | DerivedTypeVariable]] = defaultdict(set)
964
+ for constraint in constraints:
965
+ if isinstance(constraint, Subtype):
966
+ if isinstance(constraint.sub_type, TypeVariable):
967
+ sub_typevars[constraint.sub_type].add(constraint.super_type)
968
+ for tv in [constraint.sub_type, constraint.super_type]:
969
+ if isinstance(tv, DerivedTypeVariable):
970
+ tv_to_dtvs[tv.type_var].add(constraint.sub_type)
971
+ elif isinstance(tv, TypeVariable):
972
+ tv_to_dtvs[tv].add(constraint.sub_type)
973
+
974
+ ub_subtypes: dict[TypeVariable, TypeVariable] = {}
975
+ for tv, dtvs in tv_to_dtvs.items():
976
+ if len(dtvs) == 1 and tv in sub_typevars and len(sub_typevars[tv]) == 1:
977
+ ub = next(iter(sub_typevars[tv]))
978
+ if ub in tvs_to_solve:
979
+ ub_subtypes[tv] = ub
980
+
981
+ filtered_constraints = set()
982
+ for constraint in constraints:
983
+ if isinstance(constraint, Subtype) and constraint.sub_type in ub_subtypes:
984
+ continue
985
+ filtered_constraints.add(constraint)
986
+
987
+ return filtered_constraints, ub_subtypes
988
+
989
+ def _degrade_constraint_set(self, constraints: set[TypeConstraint]) -> set[TypeConstraint]:
990
+ """
991
+ Degrade the constraint set to a smaller set of constraints to speed up the DFA generation process.
992
+ """
993
+
994
+ tv_with_ls = defaultdict(set) # tv_with_ls are type variables with Loads or Stores
995
+ graph = networkx.Graph()
996
+
997
+ for constraint in constraints:
998
+ if isinstance(constraint, Subtype):
999
+ if isinstance(constraint.sub_type, DerivedTypeVariable) and isinstance(
1000
+ constraint.sub_type.labels[0], (Load, Store)
1001
+ ):
1002
+ tv_with_ls[constraint.sub_type.type_var].add(constraint.sub_type)
1003
+ if type(constraint.sub_type) is TypeVariable and type(constraint.super_type) is TypeVariable:
1004
+ graph.add_edge(constraint.sub_type, constraint.super_type)
1005
+
1006
+ tv_to_degrade = set()
1007
+ for tv, dtvs in tv_with_ls.items():
1008
+ if len(dtvs) > 5:
1009
+ # degrade all subtype relationships involving this type variable to equivalence
1010
+ tv_to_degrade.add(tv)
1011
+
1012
+ replacements = {}
1013
+ for components in networkx.connected_components(graph):
1014
+ if len(components) == 1:
1015
+ continue
1016
+ if any(tv in tv_to_degrade for tv in components):
1017
+ components_lst = sorted(components, key=str)
1018
+ representative = components_lst[0]
1019
+ for tv in components_lst[1:]:
1020
+ replacements[tv] = representative
1021
+
1022
+ degraded_constraints = self._rewrite_constraints_with_replacements(constraints, replacements)
1023
+
1024
+ # discover more equivalence relations
1025
+ eq_constraints = self._discover_equivalence(degraded_constraints)
1026
+ _l.debug("Discovered %d equivalence constraints from degraded constraints.", len(eq_constraints))
1027
+ if eq_constraints:
1028
+ degraded_constraints, eq_replacements = self._handle_equivalence(degraded_constraints | eq_constraints)
1029
+ self._equivalence |= eq_replacements
1030
+
1031
+ # filter them
1032
+ degraded_constraints = self._filter_constraints(degraded_constraints)
1033
+
1034
+ self._equivalence |= replacements
1035
+ return degraded_constraints
834
1036
 
835
1037
  def _convert_arrays(self, constraints):
836
1038
  for constraint in constraints:
@@ -860,7 +1062,7 @@ class SimpleSolver:
860
1062
  @staticmethod
861
1063
  def _generate_constraint_subset(
862
1064
  constraints: set[TypeConstraint], typevars: set[TypeVariable]
863
- ) -> set[TypeConstraint]:
1065
+ ) -> tuple[set[TypeConstraint], set[TypeVariable]]:
864
1066
  subset = set()
865
1067
  related_typevars = set(typevars)
866
1068
  while True:
@@ -890,7 +1092,7 @@ class SimpleSolver:
890
1092
  if not new:
891
1093
  break
892
1094
  subset |= new
893
- return subset
1095
+ return subset, related_typevars
894
1096
 
895
1097
  def _generate_constraint_graph(
896
1098
  self, constraints: set[TypeConstraint], interesting_variables: set[DerivedTypeVariable]
@@ -40,6 +40,7 @@ class Typehoon(Analysis):
40
40
  must_struct: set[TypeVariable] | None = None,
41
41
  stackvar_max_sizes: dict[TypeVariable, int] | None = None,
42
42
  stack_offset_tvs: dict[int, TypeVariable] | None = None,
43
+ constraint_set_degradation_threshold: int = 150,
43
44
  ):
44
45
  """
45
46
 
@@ -57,6 +58,7 @@ class Typehoon(Analysis):
57
58
  self._must_struct = must_struct
58
59
  self._stackvar_max_sizes = stackvar_max_sizes if stackvar_max_sizes is not None else {}
59
60
  self._stack_offset_tvs = stack_offset_tvs if stack_offset_tvs is not None else {}
61
+ self._constraint_set_degradation_threshold = constraint_set_degradation_threshold
60
62
 
61
63
  self.bits = self.project.arch.bits
62
64
  self.solution = None
@@ -193,7 +195,7 @@ class Typehoon(Analysis):
193
195
  self.simtypes_solution.update(self._ground_truth)
194
196
 
195
197
  @staticmethod
196
- def _resolve_derived(tv):
198
+ def _resolve_derived(tv: TypeVariable | DerivedTypeVariable) -> TypeVariable:
197
199
  return tv.type_var if isinstance(tv, DerivedTypeVariable) else tv
198
200
 
199
201
  def _solve(self):
@@ -211,7 +213,13 @@ class Typehoon(Analysis):
211
213
  if isinstance(constraint.super_type, TypeVariable):
212
214
  typevars.add(self._resolve_derived(constraint.super_type))
213
215
 
214
- solver = SimpleSolver(self.bits, self._constraints, typevars, stackvar_max_sizes=self._stackvar_max_sizes)
216
+ solver = SimpleSolver(
217
+ self.bits,
218
+ self._constraints,
219
+ typevars,
220
+ stackvar_max_sizes=self._stackvar_max_sizes,
221
+ constraint_set_degradation_threshold=self._constraint_set_degradation_threshold,
222
+ )
215
223
  self.solution = solver.solution
216
224
  self.processed_constraints_count = solver.processed_constraints_count
217
225
  self.eqclass_constraints_count = solver.eqclass_constraints_count