angr 9.2.131__py3-none-manylinux2014_aarch64.whl → 9.2.132__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 (111) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/analysis.py +6 -2
  3. angr/analyses/cfg/cfg_emulated.py +5 -5
  4. angr/analyses/cfg/cfg_fast.py +2 -2
  5. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +139 -94
  6. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
  7. angr/analyses/ddg.py +14 -11
  8. angr/analyses/decompiler/ail_simplifier.py +3 -2
  9. angr/analyses/decompiler/block_simplifier.py +10 -21
  10. angr/analyses/decompiler/clinic.py +108 -34
  11. angr/analyses/decompiler/condition_processor.py +12 -10
  12. angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
  13. angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
  14. angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
  15. angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
  16. angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
  17. angr/analyses/decompiler/optimization_passes/engine_base.py +261 -83
  18. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +173 -35
  19. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +5 -2
  20. angr/analyses/decompiler/optimization_passes/optimization_pass.py +39 -19
  21. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +2 -0
  22. angr/analyses/decompiler/ssailification/rewriting.py +1 -2
  23. angr/analyses/decompiler/ssailification/rewriting_engine.py +138 -55
  24. angr/analyses/decompiler/ssailification/ssailification.py +2 -1
  25. angr/analyses/decompiler/ssailification/traversal.py +4 -6
  26. angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
  27. angr/analyses/decompiler/structured_codegen/c.py +5 -3
  28. angr/analyses/decompiler/structuring/phoenix.py +26 -9
  29. angr/analyses/decompiler/structuring/structurer_nodes.py +9 -0
  30. angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
  31. angr/analyses/deobfuscator/string_obf_finder.py +2 -2
  32. angr/analyses/init_finder.py +47 -22
  33. angr/analyses/propagator/engine_base.py +21 -14
  34. angr/analyses/propagator/engine_vex.py +149 -179
  35. angr/analyses/propagator/propagator.py +10 -28
  36. angr/analyses/propagator/top_checker_mixin.py +211 -5
  37. angr/analyses/propagator/vex_vars.py +1 -1
  38. angr/analyses/reaching_definitions/dep_graph.py +1 -1
  39. angr/analyses/reaching_definitions/engine_ail.py +304 -329
  40. angr/analyses/reaching_definitions/engine_vex.py +243 -229
  41. angr/analyses/reaching_definitions/function_handler.py +3 -3
  42. angr/analyses/reaching_definitions/rd_state.py +37 -32
  43. angr/analyses/s_propagator.py +18 -3
  44. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
  45. angr/analyses/typehoon/simple_solver.py +7 -5
  46. angr/analyses/typehoon/translator.py +8 -0
  47. angr/analyses/typehoon/typeconsts.py +10 -2
  48. angr/analyses/typehoon/typevars.py +9 -7
  49. angr/analyses/variable_recovery/engine_ail.py +299 -259
  50. angr/analyses/variable_recovery/engine_base.py +135 -117
  51. angr/analyses/variable_recovery/engine_vex.py +175 -185
  52. angr/analyses/variable_recovery/irsb_scanner.py +49 -38
  53. angr/analyses/variable_recovery/variable_recovery.py +28 -5
  54. angr/analyses/variable_recovery/variable_recovery_base.py +32 -33
  55. angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
  56. angr/analyses/xrefs.py +46 -19
  57. angr/annocfg.py +19 -14
  58. angr/block.py +4 -9
  59. angr/calling_conventions.py +1 -1
  60. angr/engines/engine.py +30 -14
  61. angr/engines/light/__init__.py +11 -3
  62. angr/engines/light/engine.py +1003 -1185
  63. angr/engines/pcode/cc.py +2 -0
  64. angr/engines/successors.py +13 -9
  65. angr/engines/vex/claripy/datalayer.py +1 -1
  66. angr/engines/vex/claripy/irop.py +1 -1
  67. angr/engines/vex/light/slicing.py +2 -2
  68. angr/exploration_techniques/__init__.py +1 -124
  69. angr/exploration_techniques/base.py +126 -0
  70. angr/exploration_techniques/bucketizer.py +1 -1
  71. angr/exploration_techniques/dfs.py +3 -1
  72. angr/exploration_techniques/director.py +2 -3
  73. angr/exploration_techniques/driller_core.py +1 -1
  74. angr/exploration_techniques/explorer.py +4 -2
  75. angr/exploration_techniques/lengthlimiter.py +2 -1
  76. angr/exploration_techniques/local_loop_seer.py +2 -1
  77. angr/exploration_techniques/loop_seer.py +5 -5
  78. angr/exploration_techniques/manual_mergepoint.py +2 -1
  79. angr/exploration_techniques/memory_watcher.py +3 -1
  80. angr/exploration_techniques/oppologist.py +4 -5
  81. angr/exploration_techniques/slicecutor.py +4 -2
  82. angr/exploration_techniques/spiller.py +1 -1
  83. angr/exploration_techniques/stochastic.py +2 -1
  84. angr/exploration_techniques/stub_stasher.py +2 -1
  85. angr/exploration_techniques/suggestions.py +3 -1
  86. angr/exploration_techniques/symbion.py +3 -1
  87. angr/exploration_techniques/tech_builder.py +2 -1
  88. angr/exploration_techniques/threading.py +4 -7
  89. angr/exploration_techniques/timeout.py +4 -2
  90. angr/exploration_techniques/tracer.py +4 -3
  91. angr/exploration_techniques/unique.py +3 -2
  92. angr/exploration_techniques/veritesting.py +1 -1
  93. angr/knowledge_plugins/key_definitions/atoms.py +2 -2
  94. angr/knowledge_plugins/key_definitions/live_definitions.py +16 -13
  95. angr/knowledge_plugins/propagations/states.py +13 -8
  96. angr/knowledge_plugins/variables/variable_manager.py +23 -9
  97. angr/sim_manager.py +1 -3
  98. angr/sim_state.py +39 -41
  99. angr/sim_type.py +5 -0
  100. angr/sim_variable.py +29 -28
  101. angr/utils/bits.py +12 -0
  102. angr/utils/orderedset.py +4 -1
  103. angr/utils/ssa/__init__.py +21 -3
  104. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/METADATA +6 -6
  105. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/RECORD +109 -110
  106. angr/analyses/propagator/engine_ail.py +0 -1562
  107. angr/storage/memory_mixins/__init__.pyi +0 -48
  108. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/LICENSE +0 -0
  109. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/WHEEL +0 -0
  110. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/entry_points.txt +0 -0
  111. {angr-9.2.131.dist-info → angr-9.2.132.dist-info}/top_level.txt +0 -0
@@ -86,7 +86,7 @@ class FunctionCallData:
86
86
 
87
87
  callsite_codeloc: CodeLocation
88
88
  function_codeloc: CodeLocation
89
- address_multi: MultiValues | None
89
+ address_multi: MultiValues[claripy.ast.BV | claripy.ast.FP] | None
90
90
  address: int | None = None
91
91
  symbol: Symbol | None = None
92
92
  function: Function | None = None
@@ -94,12 +94,12 @@ class FunctionCallData:
94
94
  cc: SimCC | None = None
95
95
  prototype: SimTypeFunction | None = None
96
96
  args_atoms: list[set[Atom]] | None = None
97
- args_values: list[MultiValues] | None = None
97
+ args_values: list[MultiValues[claripy.ast.BV | claripy.ast.FP]] | None = None
98
98
  ret_atoms: set[Atom] | None = None
99
99
  redefine_locals: bool = True
100
100
  visited_blocks: set[int] | None = None
101
101
  effects: list[FunctionEffect] = field(default_factory=list)
102
- ret_values: MultiValues | None = None
102
+ ret_values: MultiValues[claripy.ast.BV | claripy.ast.FP] | None = None
103
103
  ret_values_deps: set[Definition] | None = None
104
104
  caller_will_handle_single_ret: bool = False
105
105
  guessed_cc: bool = False
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
- from typing import Any, TYPE_CHECKING, overload
2
+ from typing import Any, TYPE_CHECKING, cast, overload
3
3
  from collections.abc import Iterable, Iterator
4
4
  import logging
5
+ from typing_extensions import Self
5
6
 
6
7
  import archinfo
7
8
  import claripy
@@ -13,7 +14,7 @@ from angr.knowledge_plugins.key_definitions.heap_address import HeapAddress
13
14
  from angr.knowledge_plugins.key_definitions.definition import A
14
15
  from angr.engines.light import SpOffset
15
16
  from angr.code_location import CodeLocation
16
- from angr.storage.memory_mixins.paged_memory.pages.multi_values import MultiValues
17
+ from angr.storage.memory_mixins.paged_memory.pages.multi_values import MVType, MultiValues
17
18
  from angr.storage.memory_mixins import MultiValuedMemory
18
19
  from angr.knowledge_plugins.key_definitions import LiveDefinitions, DerefSize, Definition
19
20
  from angr.knowledge_plugins.key_definitions.atoms import Atom, GuardUse, Register, MemoryLocation, ConstantSrc
@@ -77,14 +78,14 @@ class ReachingDefinitionsState:
77
78
  codeloc: CodeLocation,
78
79
  arch: archinfo.Arch,
79
80
  subject: Subject,
81
+ analysis: ReachingDefinitionsAnalysis,
80
82
  track_tmps: bool = False,
81
83
  track_consts: bool = False,
82
- analysis: ReachingDefinitionsAnalysis | None = None,
83
84
  rtoc_value=None,
84
85
  live_definitions: LiveDefinitions | None = None,
85
86
  canonical_size: int = 8,
86
- heap_allocator: HeapAllocator = None,
87
- environment: Environment = None,
87
+ heap_allocator: HeapAllocator | None = None,
88
+ environment: Environment | None = None,
88
89
  sp_adjusted: bool = False,
89
90
  all_definitions: set[Definition[A]] | None = None,
90
91
  initializer: RDAStateInitializer | None = None,
@@ -102,12 +103,12 @@ class ReachingDefinitionsState:
102
103
  self._sp_adjusted: bool = sp_adjusted
103
104
  self._element_limit: int = element_limit
104
105
 
105
- self.all_definitions: set[Definition[A]] = set() if all_definitions is None else all_definitions
106
+ self.all_definitions: set[Definition[Any]] = set() if all_definitions is None else all_definitions
106
107
 
107
108
  self.heap_allocator = heap_allocator or HeapAllocator(canonical_size)
108
109
  self._environment: Environment = environment or Environment()
109
110
 
110
- self.codeloc_uses: set[Definition[A]] = set()
111
+ self.codeloc_uses: set[Definition[Any]] = set()
111
112
 
112
113
  # have we observed an exit statement or not during the analysis of the *last instruction* of a block? we should
113
114
  # not perform any sp updates if it is the case. this is for handling conditional returns in ARM binaries.
@@ -184,7 +185,7 @@ class ReachingDefinitionsState:
184
185
  return n - 2**self.arch.bits
185
186
  return n
186
187
 
187
- def annotate_with_def(self, symvar: claripy.ast.Base, definition: Definition[A]) -> claripy.ast.Base:
188
+ def annotate_with_def(self, symvar: MVType, definition: Definition[Any]) -> MVType:
188
189
  """
189
190
 
190
191
  :param symvar:
@@ -193,14 +194,14 @@ class ReachingDefinitionsState:
193
194
  """
194
195
  return self.live_definitions.annotate_with_def(symvar, definition)
195
196
 
196
- def annotate_mv_with_def(self, mv: MultiValues, definition: Definition[A]) -> MultiValues:
197
+ def annotate_mv_with_def(self, mv: MultiValues[MVType], definition: Definition[A]) -> MultiValues[MVType]:
197
198
  return MultiValues(
198
199
  offset_to_values={
199
200
  offset: {self.annotate_with_def(value, definition) for value in values} for offset, values in mv.items()
200
201
  }
201
202
  )
202
203
 
203
- def extract_defs(self, symvar: claripy.ast.Base) -> Iterator[Definition[A]]:
204
+ def extract_defs(self, symvar: claripy.ast.Base) -> Iterator[Definition[Any]]:
204
205
  yield from self.live_definitions.extract_defs(symvar)
205
206
 
206
207
  #
@@ -254,7 +255,7 @@ class ReachingDefinitionsState:
254
255
  def get_sp(self) -> int:
255
256
  return self.live_definitions.get_sp()
256
257
 
257
- def get_stack_address(self, offset: claripy.ast.Base) -> int:
258
+ def get_stack_address(self, offset: claripy.ast.Base) -> int | None:
258
259
  return self.live_definitions.get_stack_address(offset)
259
260
 
260
261
  @property
@@ -300,8 +301,8 @@ class ReachingDefinitionsState:
300
301
 
301
302
  return self
302
303
 
303
- def copy(self, discard_tmpdefs=False) -> ReachingDefinitionsState:
304
- return ReachingDefinitionsState(
304
+ def copy(self, discard_tmpdefs=False) -> Self:
305
+ return type(self)(
305
306
  self.codeloc,
306
307
  self.arch,
307
308
  self._subject,
@@ -317,9 +318,8 @@ class ReachingDefinitionsState:
317
318
  element_limit=self._element_limit,
318
319
  )
319
320
 
320
- def merge(self, *others) -> tuple[ReachingDefinitionsState, bool]:
321
+ def merge(self, *others: Self) -> tuple[Self, bool]:
321
322
  state = self.copy()
322
- others: Iterable[ReachingDefinitionsState]
323
323
 
324
324
  state.live_definitions, merged_0 = state.live_definitions.merge(*[other.live_definitions for other in others])
325
325
  state._environment, merged_1 = state.environment.merge(*[other.environment for other in others])
@@ -419,10 +419,12 @@ class ReachingDefinitionsState:
419
419
  for def_ in defs:
420
420
  if not def_.dummy:
421
421
  self._dep_graph.add_edge(used, def_)
422
+
423
+ cfg = self.analysis.project.kb.cfgs.get_most_accurate()
422
424
  self._dep_graph.add_dependencies_for_concrete_pointers_of(
423
425
  values,
424
426
  used,
425
- self.analysis.project.kb.cfgs.get_most_accurate(),
427
+ cfg,
426
428
  self.analysis.project.loader,
427
429
  )
428
430
  else:
@@ -491,7 +493,9 @@ class ReachingDefinitionsState:
491
493
  self.codeloc_uses.add(definition)
492
494
  self.live_definitions.add_memory_use_by_def(definition, self.codeloc, expr=expr)
493
495
 
494
- def get_definitions(self, atom: A | Definition[A] | Iterable[A] | Iterable[Definition[A]]) -> set[Definition[A]]:
496
+ def get_definitions(
497
+ self, atom: Atom | Definition[Atom] | Iterable[Atom] | Iterable[Definition[Atom]]
498
+ ) -> set[Definition[Atom]]:
495
499
  return self.live_definitions.get_definitions(atom)
496
500
 
497
501
  def get_values(self, spec: A | Definition[A] | Iterable[A]) -> MultiValues | None:
@@ -503,13 +507,15 @@ class ReachingDefinitionsState:
503
507
  return self.live_definitions.get_one_value(spec, strip_annotations=strip_annotations)
504
508
 
505
509
  @overload
506
- def get_concrete_value(self, spec: A | Definition[A] | Iterable[A], cast_to: type[int] = ...) -> int | None: ...
510
+ def get_concrete_value(self, spec: Atom | Definition[Atom] | Iterable[Atom], cast_to: type[int]) -> int | None: ...
507
511
 
508
512
  @overload
509
- def get_concrete_value(self, spec: A | Definition[A] | Iterable[A], cast_to: type[bytes] = ...) -> bytes | None: ...
513
+ def get_concrete_value(
514
+ self, spec: Atom | Definition[Atom] | Iterable[Atom], cast_to: type[bytes]
515
+ ) -> bytes | None: ...
510
516
 
511
517
  def get_concrete_value(
512
- self, spec: A | Definition[A] | Iterable[A], cast_to: type[int] | type[bytes] = int
518
+ self, spec: Atom | Definition[Atom] | Iterable[Atom], cast_to: type[int] | type[bytes] = int
513
519
  ) -> int | bytes | None:
514
520
  return self.live_definitions.get_concrete_value(spec, cast_to)
515
521
 
@@ -551,11 +557,10 @@ class ReachingDefinitionsState:
551
557
  return result
552
558
 
553
559
  @deprecated("deref")
554
- def pointer_to_atom(self, value: claripy.ast.base.Base, size: int, endness: str) -> MemoryLocation | None:
560
+ def pointer_to_atom(self, value: claripy.ast.BV, size: int, endness: str) -> MemoryLocation | None:
555
561
  if self.is_top(value):
556
562
  return None
557
563
 
558
- # TODO this can be simplified with the walrus operator
559
564
  stack_offset = self.get_stack_offset(value)
560
565
  if stack_offset is not None:
561
566
  addr = SpOffset(len(value), stack_offset)
@@ -564,7 +569,7 @@ class ReachingDefinitionsState:
564
569
  if heap_offset is not None:
565
570
  addr = HeapAddress(heap_offset)
566
571
  elif value.op == "BVV":
567
- addr = value.args[0]
572
+ addr = cast(int, value.args[0])
568
573
  else:
569
574
  # cannot resolve
570
575
  return None
@@ -574,9 +579,9 @@ class ReachingDefinitionsState:
574
579
  @overload
575
580
  def deref(
576
581
  self,
577
- pointer: int | claripy.ast.bv.BV | HeapAddress | SpOffset,
582
+ pointer: int | claripy.ast.BV | HeapAddress | SpOffset,
578
583
  size: int | DerefSize,
579
- endness: str = ...,
584
+ endness: archinfo.Endness = ...,
580
585
  ) -> MemoryLocation | None: ...
581
586
 
582
587
  @overload
@@ -584,23 +589,23 @@ class ReachingDefinitionsState:
584
589
  self,
585
590
  pointer: MultiValues | A | Definition | Iterable[A] | Iterable[Definition[A]],
586
591
  size: int | DerefSize,
587
- endness: str = ...,
592
+ endness: archinfo.Endness = ...,
588
593
  ) -> set[MemoryLocation]: ...
589
594
 
590
595
  def deref(
591
596
  self,
592
597
  pointer: (
593
- MultiValues
594
- | A
595
- | Definition
596
- | Iterable[A]
597
- | Iterable[Definition[A]]
598
+ MultiValues[claripy.ast.BV]
599
+ | Atom
600
+ | Definition[Atom]
601
+ | Iterable[Atom]
602
+ | Iterable[Definition[Atom]]
598
603
  | int
599
604
  | claripy.ast.BV
600
605
  | HeapAddress
601
606
  | SpOffset
602
607
  ),
603
608
  size: int | DerefSize,
604
- endness: str = archinfo.Endness.BE,
609
+ endness: archinfo.Endness = archinfo.Endness.BE,
605
610
  ):
606
611
  return self.live_definitions.deref(pointer, size, endness)
@@ -1,10 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import contextlib
4
+ from collections.abc import Mapping
4
5
  from collections import defaultdict
5
6
 
6
7
  from ailment.block import Block
7
- from ailment.expression import Const, VirtualVariable, VirtualVariableCategory, StackBaseOffset, Load, Convert
8
+ from ailment.expression import (
9
+ Const,
10
+ VirtualVariable,
11
+ VirtualVariableCategory,
12
+ StackBaseOffset,
13
+ Load,
14
+ Convert,
15
+ Expression,
16
+ )
8
17
  from ailment.statement import Assignment, Store, Return, Jump
9
18
 
10
19
  from angr.knowledge_plugins.functions import Function
@@ -31,7 +40,7 @@ class SPropagatorModel:
31
40
  """
32
41
 
33
42
  def __init__(self):
34
- self.replacements = {}
43
+ self.replacements: Mapping[CodeLocation, Mapping[Expression, Expression]] = {}
35
44
 
36
45
 
37
46
  class SPropagatorAnalysis(Analysis):
@@ -41,7 +50,7 @@ class SPropagatorAnalysis(Analysis):
41
50
 
42
51
  def __init__( # pylint: disable=too-many-positional-arguments
43
52
  self,
44
- subject,
53
+ subject: Block | Function,
45
54
  func_graph=None,
46
55
  only_consts: bool = True,
47
56
  immediate_stmt_removal: bool = False,
@@ -86,10 +95,13 @@ class SPropagatorAnalysis(Analysis):
86
95
  return self.model.replacements
87
96
 
88
97
  def _analyze(self):
98
+ blocks: dict[tuple[int, int | None], Block]
89
99
  match self.mode:
90
100
  case "block":
101
+ assert self.block is not None
91
102
  blocks = {(self.block.addr, self.block.idx): self.block}
92
103
  case "function":
104
+ assert self.func_graph is not None
93
105
  blocks = {(block.addr, block.idx): block for block in self.func_graph}
94
106
  case _:
95
107
  raise NotImplementedError
@@ -120,11 +132,14 @@ class SPropagatorAnalysis(Analysis):
120
132
 
121
133
  vvarid_to_vvar[vvar.varid] = vvar
122
134
  defloc = vvar_deflocs[vvar]
135
+ assert defloc.block_addr is not None
136
+ assert defloc.stmt_idx is not None
123
137
  block = blocks[(defloc.block_addr, defloc.block_idx)]
124
138
  stmt = block.statements[defloc.stmt_idx]
125
139
  r, v = is_const_assignment(stmt)
126
140
  if r:
127
141
  # replace wherever it's used
142
+ assert v is not None
128
143
  const_vvars[vvar.varid] = v
129
144
  for vvar_at_use, useloc in vvar_uselocs[vvar.varid]:
130
145
  replacements[useloc][vvar_at_use] = v
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from ailment.block import Block
4
4
  from ailment.statement import Assignment, Call, Return
5
+ import networkx
5
6
 
6
7
  from angr.knowledge_plugins.functions import Function
7
8
  from angr.knowledge_plugins.key_definitions.constants import ObservationPointType
@@ -22,9 +23,8 @@ class SReachingDefinitionsAnalysis(Analysis):
22
23
  self,
23
24
  subject,
24
25
  func_addr: int | None = None,
25
- func_graph=None,
26
+ func_graph: networkx.DiGraph[Block] | None = None,
26
27
  track_tmps: bool = False,
27
- stack_pointer_tracker=None,
28
28
  ):
29
29
  if isinstance(subject, Block):
30
30
  self.block = subject
@@ -40,7 +40,6 @@ class SReachingDefinitionsAnalysis(Analysis):
40
40
  self.func_graph = func_graph
41
41
  self.func_addr = func_addr if func_addr is not None else self.func.addr if self.func is not None else None
42
42
  self._track_tmps = track_tmps
43
- self._sp_tracker = stack_pointer_tracker # FIXME: Is it still used?
44
43
 
45
44
  self._bp_as_gpr = False
46
45
  if self.func is not None:
@@ -53,8 +52,10 @@ class SReachingDefinitionsAnalysis(Analysis):
53
52
  def _analyze(self):
54
53
  match self.mode:
55
54
  case "block":
55
+ assert self.block is not None
56
56
  blocks = {(self.block.addr, self.block.idx): self.block}
57
57
  case "function":
58
+ assert self.func_graph is not None
58
59
  blocks = {(block.addr, block.idx): block for block in self.func_graph}
59
60
  case _:
60
61
  raise NotImplementedError
@@ -115,9 +116,10 @@ class SReachingDefinitionsAnalysis(Analysis):
115
116
  stmt = block.statements[stmt_idx]
116
117
  assert isinstance(stmt, (Call, Assignment, Return))
117
118
 
118
- call: Call = (
119
+ call = (
119
120
  stmt if isinstance(stmt, Call) else stmt.src if isinstance(stmt, Assignment) else stmt.ret_exprs[0]
120
121
  )
122
+ assert isinstance(call, Call)
121
123
  if call.prototype is None:
122
124
  # without knowing the prototype, we must conservatively add uses to all registers that are
123
125
  # potentially used here
@@ -126,7 +128,9 @@ class SReachingDefinitionsAnalysis(Analysis):
126
128
  else:
127
129
  # just use all registers in the default calling convention because we don't know anything about
128
130
  # the calling convention yet
129
- cc = default_cc(self.project.arch.name)(self.project.arch)
131
+ cc_cls = default_cc(self.project.arch.name)
132
+ assert cc_cls is not None
133
+ cc = cc_cls(self.project.arch)
130
134
 
131
135
  codeloc = CodeLocation(block_addr, stmt_idx, block_idx=block_idx, ins_addr=stmt.ins_addr)
132
136
  arg_locs = cc.ARG_REGS
@@ -127,8 +127,8 @@ class SketchNode(SketchNodeBase):
127
127
 
128
128
  def __init__(self, typevar: TypeVariable | DerivedTypeVariable):
129
129
  self.typevar: TypeVariable | DerivedTypeVariable = typevar
130
- self.upper_bound = TopType()
131
- self.lower_bound = BottomType()
130
+ self.upper_bound: TypeConstant = TopType()
131
+ self.lower_bound: TypeConstant = BottomType()
132
132
 
133
133
  def __repr__(self):
134
134
  return f"{self.lower_bound} <: {self.typevar} <: {self.upper_bound}"
@@ -202,7 +202,7 @@ class Sketch:
202
202
  node = self.lookup(node.target)
203
203
  return node
204
204
 
205
- def add_edge(self, src: SketchNodeBase, dst: SketchNodeBase, label):
205
+ def add_edge(self, src: SketchNodeBase, dst: SketchNodeBase, label) -> None:
206
206
  self.graph.add_edge(src, dst, label=label)
207
207
 
208
208
  def add_constraint(self, constraint: TypeConstraint) -> None:
@@ -214,13 +214,15 @@ class Sketch:
214
214
  if SimpleSolver._typevar_inside_set(subtype, PRIMITIVE_TYPES) and not SimpleSolver._typevar_inside_set(
215
215
  supertype, PRIMITIVE_TYPES
216
216
  ):
217
- super_node: SketchNode | None = self.lookup(supertype)
217
+ super_node = self.lookup(supertype)
218
+ assert super_node is None or isinstance(super_node, SketchNode)
218
219
  if super_node is not None:
219
220
  super_node.lower_bound = self.solver.join(super_node.lower_bound, subtype)
220
221
  elif SimpleSolver._typevar_inside_set(supertype, PRIMITIVE_TYPES) and not SimpleSolver._typevar_inside_set(
221
222
  subtype, PRIMITIVE_TYPES
222
223
  ):
223
- sub_node: SketchNode | None = self.lookup(subtype)
224
+ sub_node = self.lookup(subtype)
225
+ assert sub_node is None or isinstance(sub_node, SketchNode)
224
226
  # assert sub_node is not None
225
227
  if sub_node is not None:
226
228
  sub_node.upper_bound = self.solver.meet(sub_node.upper_bound, supertype)
@@ -151,6 +151,9 @@ class TypeTranslator:
151
151
  def _translate_Int256(self, tc): # pylint:disable=unused-argument
152
152
  return sim_type.SimTypeInt256(signed=False).with_arch(self.arch)
153
153
 
154
+ def _translate_Int512(self, tc): # pylint:disable=unused-argument
155
+ return sim_type.SimTypeInt512(signed=False).with_arch(self.arch)
156
+
154
157
  def _translate_TypeVariableReference(self, tc):
155
158
  if tc.typevar in self.translated:
156
159
  return self.translated[tc.typevar]
@@ -190,6 +193,9 @@ class TypeTranslator:
190
193
  def _translate_SimTypeInt256(self, st: sim_type.SimTypeChar) -> typeconsts.Int256:
191
194
  return typeconsts.Int256()
192
195
 
196
+ def _translate_SimTypeInt512(self, st: sim_type.SimTypeChar) -> typeconsts.Int512:
197
+ return typeconsts.Int512()
198
+
193
199
  def _translate_SimTypeInt(self, st: sim_type.SimTypeInt) -> typeconsts.Int32:
194
200
  return typeconsts.Int32()
195
201
 
@@ -235,6 +241,7 @@ TypeConstHandlers = {
235
241
  typeconsts.Int64: TypeTranslator._translate_Int64,
236
242
  typeconsts.Int128: TypeTranslator._translate_Int128,
237
243
  typeconsts.Int256: TypeTranslator._translate_Int256,
244
+ typeconsts.Int512: TypeTranslator._translate_Int512,
238
245
  typeconsts.TypeVariableReference: TypeTranslator._translate_TypeVariableReference,
239
246
  }
240
247
 
@@ -247,6 +254,7 @@ SimTypeHandlers = {
247
254
  sim_type.SimTypeChar: TypeTranslator._translate_SimTypeChar,
248
255
  sim_type.SimTypeInt128: TypeTranslator._translate_SimTypeInt128,
249
256
  sim_type.SimTypeInt256: TypeTranslator._translate_SimTypeInt256,
257
+ sim_type.SimTypeInt512: TypeTranslator._translate_SimTypeInt512,
250
258
  sim_type.SimStruct: TypeTranslator._translate_SimStruct,
251
259
  sim_type.SimTypeArray: TypeTranslator._translate_SimTypeArray,
252
260
  }
@@ -107,6 +107,13 @@ class Int256(Int):
107
107
  return "int256"
108
108
 
109
109
 
110
+ class Int512(Int):
111
+ SIZE = 32
112
+
113
+ def __repr__(self, memo=None):
114
+ return "int512"
115
+
116
+
110
117
  class FloatBase(TypeConstant):
111
118
  def __repr__(self, memo=None):
112
119
  return "floatbase"
@@ -281,7 +288,7 @@ class TypeVariableReference(TypeConstant):
281
288
  #
282
289
 
283
290
 
284
- def int_type(bits: int) -> Int | None:
291
+ def int_type(bits: int) -> Int:
285
292
  mapping = {
286
293
  1: Int1,
287
294
  8: Int8,
@@ -290,10 +297,11 @@ def int_type(bits: int) -> Int | None:
290
297
  64: Int64,
291
298
  128: Int128,
292
299
  256: Int256,
300
+ 512: Int512,
293
301
  }
294
302
  if bits in mapping:
295
303
  return mapping[bits]()
296
- return None
304
+ raise TypeError(f"Not a known size of int: {bits}")
297
305
 
298
306
 
299
307
  def float_type(bits: int) -> FloatBase | None:
@@ -316,12 +316,12 @@ class TypeVariable:
316
316
  class DerivedTypeVariable(TypeVariable):
317
317
  __slots__ = ("type_var", "labels")
318
318
 
319
- type_var: TypeVariable | TypeConstant
319
+ labels: tuple[BaseLabel, ...]
320
320
 
321
321
  def __init__(
322
322
  self,
323
- type_var: TypeVariable | DerivedTypeVariable | None,
324
- label,
323
+ type_var: TypeType,
324
+ label: BaseLabel | None,
325
325
  labels: Iterable[BaseLabel] | None = None,
326
326
  idx=None,
327
327
  ):
@@ -339,8 +339,10 @@ class DerivedTypeVariable(TypeVariable):
339
339
 
340
340
  if label is not None:
341
341
  self.labels = (*existing_labels, label)
342
+ elif labels is not None:
343
+ self.labels = existing_labels + tuple(labels)
342
344
  else:
343
- self.labels: tuple[BaseLabel] = existing_labels + tuple(labels)
345
+ self.labels = existing_labels
344
346
 
345
347
  if not self.labels:
346
348
  raise ValueError("A DerivedTypeVariable must have at least one label")
@@ -350,10 +352,10 @@ class DerivedTypeVariable(TypeVariable):
350
352
  def one_label(self) -> BaseLabel | None:
351
353
  return self.labels[0] if len(self.labels) == 1 else None
352
354
 
353
- def path(self) -> tuple[BaseLabel]:
355
+ def path(self) -> tuple[BaseLabel, ...]:
354
356
  return self.labels
355
357
 
356
- def longest_prefix(self) -> TypeVariable | DerivedTypeVariable | None:
358
+ def longest_prefix(self) -> TypeType | None:
357
359
  if not self.labels:
358
360
  return None
359
361
  if len(self.labels) == 1:
@@ -418,7 +420,7 @@ class TypeVariables:
418
420
  # )
419
421
  return "{TypeVars: %d items}" % len(self._typevars)
420
422
 
421
- def add_type_variable(self, var: SimVariable, codeloc, typevar: TypeVariable): # pylint:disable=unused-argument
423
+ def add_type_variable(self, var: SimVariable, codeloc, typevar: TypeType): # pylint:disable=unused-argument
422
424
  if var not in self._typevars:
423
425
  self._typevars[var] = set()
424
426
  elif typevar in self._typevars[var]: