angr 9.2.139__py3-none-manylinux2014_x86_64.whl → 9.2.141__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 (87) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/calling_convention/calling_convention.py +136 -53
  3. angr/analyses/calling_convention/fact_collector.py +44 -18
  4. angr/analyses/calling_convention/utils.py +3 -1
  5. angr/analyses/cfg/cfg_base.py +13 -0
  6. angr/analyses/cfg/cfg_fast.py +11 -0
  7. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +9 -8
  8. angr/analyses/decompiler/ail_simplifier.py +115 -72
  9. angr/analyses/decompiler/callsite_maker.py +24 -11
  10. angr/analyses/decompiler/clinic.py +78 -43
  11. angr/analyses/decompiler/decompiler.py +18 -7
  12. angr/analyses/decompiler/expression_narrower.py +1 -1
  13. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
  14. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +3 -1
  15. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +21 -2
  16. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
  17. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +84 -15
  18. angr/analyses/decompiler/optimization_passes/optimization_pass.py +92 -11
  19. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +53 -9
  20. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +44 -7
  21. angr/analyses/decompiler/region_identifier.py +6 -4
  22. angr/analyses/decompiler/region_simplifiers/expr_folding.py +287 -122
  23. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +31 -13
  24. angr/analyses/decompiler/ssailification/rewriting.py +23 -15
  25. angr/analyses/decompiler/ssailification/rewriting_engine.py +105 -24
  26. angr/analyses/decompiler/ssailification/ssailification.py +22 -14
  27. angr/analyses/decompiler/structured_codegen/c.py +73 -137
  28. angr/analyses/decompiler/structuring/dream.py +22 -18
  29. angr/analyses/decompiler/structuring/phoenix.py +158 -41
  30. angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
  31. angr/analyses/decompiler/structuring/structurer_base.py +37 -10
  32. angr/analyses/decompiler/structuring/structurer_nodes.py +4 -1
  33. angr/analyses/decompiler/utils.py +106 -21
  34. angr/analyses/deobfuscator/api_obf_finder.py +8 -5
  35. angr/analyses/deobfuscator/api_obf_type2_finder.py +18 -10
  36. angr/analyses/deobfuscator/string_obf_finder.py +105 -18
  37. angr/analyses/forward_analysis/forward_analysis.py +1 -1
  38. angr/analyses/propagator/top_checker_mixin.py +6 -6
  39. angr/analyses/reaching_definitions/__init__.py +2 -1
  40. angr/analyses/reaching_definitions/dep_graph.py +1 -12
  41. angr/analyses/reaching_definitions/engine_vex.py +36 -31
  42. angr/analyses/reaching_definitions/function_handler.py +15 -2
  43. angr/analyses/reaching_definitions/rd_state.py +1 -37
  44. angr/analyses/reaching_definitions/reaching_definitions.py +13 -24
  45. angr/analyses/s_propagator.py +6 -41
  46. angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
  47. angr/analyses/s_reaching_definitions/s_rda_view.py +43 -25
  48. angr/analyses/stack_pointer_tracker.py +36 -22
  49. angr/analyses/typehoon/simple_solver.py +45 -7
  50. angr/analyses/typehoon/typeconsts.py +18 -5
  51. angr/analyses/variable_recovery/engine_ail.py +1 -1
  52. angr/analyses/variable_recovery/engine_base.py +7 -5
  53. angr/analyses/variable_recovery/engine_vex.py +20 -4
  54. angr/block.py +69 -107
  55. angr/callable.py +14 -7
  56. angr/calling_conventions.py +30 -11
  57. angr/distributed/__init__.py +1 -1
  58. angr/engines/__init__.py +7 -8
  59. angr/engines/engine.py +1 -120
  60. angr/engines/failure.py +2 -2
  61. angr/engines/hook.py +2 -2
  62. angr/engines/light/engine.py +2 -2
  63. angr/engines/pcode/engine.py +2 -14
  64. angr/engines/procedure.py +2 -2
  65. angr/engines/soot/engine.py +2 -2
  66. angr/engines/soot/statements/switch.py +1 -1
  67. angr/engines/successors.py +124 -11
  68. angr/engines/syscall.py +2 -2
  69. angr/engines/unicorn.py +3 -3
  70. angr/engines/vex/heavy/heavy.py +3 -15
  71. angr/factory.py +12 -22
  72. angr/knowledge_plugins/key_definitions/atoms.py +8 -4
  73. angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
  74. angr/knowledge_plugins/variables/variable_manager.py +7 -5
  75. angr/sim_type.py +19 -17
  76. angr/simos/simos.py +3 -1
  77. angr/state_plugins/plugin.py +19 -4
  78. angr/storage/memory_mixins/memory_mixin.py +1 -1
  79. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +10 -5
  80. angr/utils/ssa/__init__.py +119 -4
  81. angr/utils/types.py +48 -0
  82. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/METADATA +6 -6
  83. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/RECORD +87 -86
  84. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/LICENSE +0 -0
  85. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/WHEEL +0 -0
  86. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/entry_points.txt +0 -0
  87. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,7 @@ import logging
3
3
  import claripy
4
4
  import pyvex
5
5
 
6
- from angr.engines.engine import SuccessorsMixin
6
+ from angr.engines.successors import SuccessorsEngine
7
7
  from angr.engines.vex.light import VEXMixin
8
8
  from angr.engines.vex.lifter import VEXLifter
9
9
  from angr.engines.vex.claripy.datalayer import ClaripyDataMixin, symbol
@@ -57,7 +57,7 @@ class SimStateStorageMixin(VEXMixin):
57
57
 
58
58
 
59
59
  # pylint:disable=arguments-differ
60
- class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEXMixin, VEXLifter):
60
+ class HeavyVEXMixin(SuccessorsEngine, ClaripyDataMixin, SimStateStorageMixin, VEXMixin, VEXLifter):
61
61
  """
62
62
  Execution engine based on VEX, Valgrind's IR.
63
63
 
@@ -83,7 +83,6 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
83
83
  self,
84
84
  successors,
85
85
  irsb=None,
86
- insn_text=None,
87
86
  insn_bytes=None,
88
87
  thumb=False,
89
88
  size=None,
@@ -99,21 +98,10 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
99
98
  extra_stop_points=extra_stop_points,
100
99
  num_inst=num_inst,
101
100
  size=size,
102
- insn_text=insn_text,
103
101
  insn_bytes=insn_bytes,
104
102
  **kwargs,
105
103
  )
106
104
 
107
- if insn_text is not None:
108
- if insn_bytes is not None:
109
- raise errors.SimEngineError("You cannot provide both 'insn_bytes' and 'insn_text'!")
110
-
111
- insn_bytes = self.project.arch.asm(insn_text, addr=successors.addr, thumb=thumb)
112
- if insn_bytes is None:
113
- raise errors.AngrAssemblyError(
114
- "Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
115
- )
116
-
117
105
  successors.sort = "IRSB"
118
106
  successors.description = "IRSB"
119
107
  self.state.history.recent_block_count = 1
@@ -137,9 +125,9 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
137
125
 
138
126
  if irsb is None:
139
127
  irsb = self.lift_vex(
128
+ insn_bytes=insn_bytes,
140
129
  addr=addr,
141
130
  state=self.state,
142
- insn_bytes=insn_bytes,
143
131
  thumb=thumb,
144
132
  size=size,
145
133
  num_inst=num_inst,
angr/factory.py CHANGED
@@ -7,10 +7,11 @@ from typing import overload, TYPE_CHECKING
7
7
  import archinfo
8
8
  from archinfo.arch_soot import ArchSoot, SootAddressDescriptor
9
9
 
10
+ from .knowledge_plugins.functions import Function
10
11
  from .sim_state import SimState
11
12
  from .calling_conventions import default_cc, SimRegArg, SimStackArg, PointerWrapper, SimCCUnknown
12
13
  from .callable import Callable
13
- from .errors import AngrAssemblyError, AngrError
14
+ from .errors import AngrError
14
15
  from .engines import UberEngine, ProcedureEngine
15
16
  from .sim_type import SimTypeFunction, SimTypeInt
16
17
  from .codenode import HookNode, SyscallNode
@@ -236,7 +237,7 @@ class AngrObjectFactory:
236
237
 
237
238
  def callable(
238
239
  self,
239
- addr,
240
+ addr: int | Function,
240
241
  prototype=None,
241
242
  concrete_only=False,
242
243
  perform_merge=True,
@@ -245,22 +246,28 @@ class AngrObjectFactory:
245
246
  cc=None,
246
247
  add_options=None,
247
248
  remove_options=None,
249
+ step_limit: int | None = None,
248
250
  ):
249
251
  """
250
252
  A Callable is a representation of a function in the binary that can be interacted with like a native python
251
253
  function.
252
254
 
253
- :param addr: The address of the function to use
254
- :param prototype: The prototype of the call to use, as a string or a SimTypeFunction
255
+ :param addr: The address of the function to use. If you pass in the function object, we will take
256
+ its addr.
257
+ :param prototype: The prototype of the call to use, as a string or a SimTypeFunction
255
258
  :param concrete_only: Throw an exception if the execution splits into multiple states
256
259
  :param perform_merge: Merge all result states into one at the end (only relevant if concrete_only=False)
257
260
  :param base_state: The state from which to do these runs
258
261
  :param toc: The address of the table of contents for ppc64
259
262
  :param cc: The SimCC to use for a calling convention
263
+ :param step_limit: The maximum number of blocks that Callable will execute before pruning the path.
260
264
  :returns: A Callable object that can be used as a interface for executing guest code like a
261
265
  python function.
262
266
  :rtype: angr.callable.Callable
263
267
  """
268
+ if isinstance(addr, Function):
269
+ addr = addr.addr
270
+
264
271
  return Callable(
265
272
  self.project,
266
273
  addr=addr,
@@ -272,6 +279,7 @@ class AngrObjectFactory:
272
279
  cc=cc,
273
280
  add_options=add_options,
274
281
  remove_options=remove_options,
282
+ step_limit=step_limit,
275
283
  )
276
284
 
277
285
  def cc(self):
@@ -300,7 +308,6 @@ class AngrObjectFactory:
300
308
  size=None,
301
309
  max_size=None,
302
310
  byte_string=None,
303
- vex=None,
304
311
  thumb=False,
305
312
  backup_state=None,
306
313
  extra_stop_points=None,
@@ -308,7 +315,6 @@ class AngrObjectFactory:
308
315
  num_inst=None,
309
316
  traceflags=0,
310
317
  insn_bytes=None,
311
- insn_text=None, # backward compatibility
312
318
  strict_block_end=None,
313
319
  collect_data_refs=False,
314
320
  cross_insn_opt=True,
@@ -326,7 +332,6 @@ class AngrObjectFactory:
326
332
  size=None,
327
333
  max_size=None,
328
334
  byte_string=None,
329
- vex=None,
330
335
  thumb=False,
331
336
  backup_state=None,
332
337
  extra_stop_points=None,
@@ -334,7 +339,6 @@ class AngrObjectFactory:
334
339
  num_inst=None,
335
340
  traceflags=0,
336
341
  insn_bytes=None,
337
- insn_text=None, # backward compatibility
338
342
  strict_block_end=None,
339
343
  collect_data_refs=False,
340
344
  load_from_ro_regions=False,
@@ -349,7 +353,6 @@ class AngrObjectFactory:
349
353
  size=None,
350
354
  max_size=None,
351
355
  byte_string=None,
352
- vex=None,
353
356
  thumb=False,
354
357
  backup_state=None,
355
358
  extra_stop_points=None,
@@ -357,7 +360,6 @@ class AngrObjectFactory:
357
360
  num_inst=None,
358
361
  traceflags=0,
359
362
  insn_bytes=None,
360
- insn_text=None, # backward compatibility
361
363
  strict_block_end=None,
362
364
  collect_data_refs=False,
363
365
  cross_insn_opt=True,
@@ -369,27 +371,15 @@ class AngrObjectFactory:
369
371
  if isinstance(self.project.arch, ArchSoot) and isinstance(addr, SootAddressDescriptor):
370
372
  return SootBlock(addr, arch=self.project.arch, project=self.project)
371
373
 
372
- if insn_bytes is not None and insn_text is not None:
373
- raise AngrError("You cannot provide both 'insn_bytes' and 'insn_text'!")
374
-
375
374
  if insn_bytes is not None:
376
375
  byte_string = insn_bytes
377
376
 
378
- if insn_text is not None:
379
- byte_string = self.project.arch.asm(insn_text, addr=addr, as_bytes=True, thumb=thumb)
380
- if byte_string is None:
381
- # assembly failed
382
- raise AngrAssemblyError(
383
- "Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
384
- )
385
-
386
377
  return Block(
387
378
  addr,
388
379
  project=self.project,
389
380
  size=size,
390
381
  max_size=max_size,
391
382
  byte_string=byte_string,
392
- vex=vex,
393
383
  extra_stop_points=extra_stop_points,
394
384
  thumb=thumb,
395
385
  backup_state=backup_state,
@@ -3,7 +3,7 @@ from enum import Enum, auto
3
3
 
4
4
  import claripy
5
5
  import ailment
6
- from archinfo import Arch, RegisterOffset
6
+ from archinfo import Arch, Endness, RegisterOffset
7
7
 
8
8
  from angr.calling_conventions import SimFunctionArgument, SimRegArg, SimStackArg
9
9
  from angr.engines.light import SpOffset
@@ -123,7 +123,7 @@ class Atom:
123
123
  register = reg
124
124
 
125
125
  @staticmethod
126
- def mem(addr: SpOffset | HeapAddress | int, size: int, endness: str | None = None) -> MemoryLocation:
126
+ def mem(addr: SpOffset | HeapAddress | int, size: int, endness: Endness | None = None) -> MemoryLocation:
127
127
  """
128
128
  Create a MemoryLocation atom,
129
129
 
@@ -251,7 +251,11 @@ class VirtualVariable(Atom):
251
251
  )
252
252
 
253
253
  def __init__(
254
- self, varid: int, size: int, category: ailment.Expr.VirtualVariableCategory, oident: str | int | None = None
254
+ self,
255
+ varid: int,
256
+ size: int,
257
+ category: ailment.Expr.VirtualVariableCategory,
258
+ oident: str | int | tuple | None = None,
255
259
  ):
256
260
  super().__init__(size)
257
261
 
@@ -310,7 +314,7 @@ class MemoryLocation(Atom):
310
314
  "endness",
311
315
  )
312
316
 
313
- def __init__(self, addr: SpOffset | HeapAddress | int, size: int, endness: str | None = None):
317
+ def __init__(self, addr: SpOffset | HeapAddress | int, size: int, endness: Endness | None = None):
314
318
  """
315
319
  :param int addr: The address of the beginning memory location slice.
316
320
  :param int size: The size of the represented memory location, in bytes.
@@ -1,26 +1,26 @@
1
1
  from __future__ import annotations
2
2
  from typing import Any, TYPE_CHECKING, cast, overload
3
+ from collections import defaultdict
3
4
  from collections.abc import Iterable, Generator
5
+ from enum import Enum, auto
4
6
  import weakref
5
7
  import logging
6
- from enum import Enum, auto
7
-
8
- from collections import defaultdict
9
8
 
10
9
  import claripy
11
10
  from claripy.annotation import Annotation
12
11
  import archinfo
13
12
 
14
- from angr.misc.ux import deprecated
15
13
  from angr.errors import SimMemoryMissingError, SimMemoryError
16
14
  from angr.storage.memory_mixins import MultiValuedMemory
17
15
  from angr.storage.memory_mixins.paged_memory.pages.multi_values import MVType, MultiValues
18
16
  from angr.knowledge_plugins.key_definitions.definition import A
19
17
  from angr.engines.light import SpOffset
20
18
  from angr.code_location import CodeLocation, ExternalCodeLocation
19
+ from angr.utils.constants import is_alignment_mask
21
20
  from .atoms import Atom, Register, MemoryLocation, Tmp, ConstantSrc
22
21
  from .definition import Definition, Tag
23
22
  from .heap_address import HeapAddress
23
+ from .undefined import Undefined
24
24
  from .uses import Uses
25
25
 
26
26
  if TYPE_CHECKING:
@@ -207,26 +207,6 @@ class LiveDefinitions:
207
207
 
208
208
  self.uses_by_codeloc: dict[CodeLocation, set[Definition]] = defaultdict(set)
209
209
 
210
- @property
211
- @deprecated("registers")
212
- def register_definitions(self) -> MultiValuedMemory:
213
- return self.registers
214
-
215
- @property
216
- @deprecated("stack")
217
- def stack_definitions(self) -> MultiValuedMemory:
218
- return self.stack
219
-
220
- @property
221
- @deprecated("memory")
222
- def memory_definitions(self) -> MultiValuedMemory:
223
- return self.memory
224
-
225
- @property
226
- @deprecated("heap")
227
- def heap_definitions(self) -> MultiValuedMemory:
228
- return self.heap
229
-
230
210
  def __repr__(self):
231
211
  ctnt = "LiveDefs"
232
212
  if self.tmps:
@@ -359,6 +339,19 @@ class LiveDefinitions:
359
339
  return off0 - off1
360
340
  return None
361
341
 
342
+ @staticmethod
343
+ def _simplify_sp_alignment(data: MultiValues) -> MultiValues:
344
+ """
345
+ Eliminate trivial stack pointer alignment, e.g.: {sp & ~0xf} -> {sp}
346
+ """
347
+ value = data.one_value()
348
+ if value is not None and "stack_base" in value.variables and value.op == "__and__" and len(value.args) == 2:
349
+ if value.args[1].concrete and is_alignment_mask(value.args[1].concrete_value):
350
+ return MultiValues(value.args[0])
351
+ if value.args[0].concrete and is_alignment_mask(value.args[0].concrete_value):
352
+ return MultiValues(value.args[1])
353
+ return data
354
+
362
355
  @staticmethod
363
356
  def annotate_with_def(symvar: MVType, definition: Definition) -> MVType:
364
357
  """
@@ -521,7 +514,8 @@ class LiveDefinitions:
521
514
  else:
522
515
  l.warning("Skip stack storing since the stack offset is None.")
523
516
  elif isinstance(atom.addr, HeapAddress):
524
- self.heap.erase(atom.addr.value, size=atom.size)
517
+ if not isinstance(atom.addr.value, Undefined):
518
+ self.heap.erase(atom.addr.value, size=atom.size)
525
519
  elif isinstance(atom.addr, int):
526
520
  self.memory.erase(atom.addr, size=atom.size)
527
521
  elif isinstance(atom.addr, claripy.ast.Base):
@@ -571,6 +565,11 @@ class LiveDefinitions:
571
565
 
572
566
  # set_object() replaces kill (not implemented) and add (add) in one step
573
567
  if isinstance(atom, Register):
568
+
569
+ # Tolerate simple stack pointer alignments
570
+ if atom.reg_offset == self.arch.sp_offset:
571
+ d = self._simplify_sp_alignment(d)
572
+
574
573
  try:
575
574
  self.registers.store(
576
575
  atom.reg_offset,
@@ -611,7 +610,7 @@ class LiveDefinitions:
611
610
  return None
612
611
  elif isinstance(atom, Tmp):
613
612
  if self.track_tmps:
614
- self.tmps[atom.tmp_idx] = {definition}
613
+ self.tmps[atom.tmp_idx] = {Definition(atom, code_loc, dummy=dummy, tags=tags)}
615
614
  else:
616
615
  self.tmps[atom.tmp_idx] = self.uses_by_codeloc[code_loc]
617
616
  return None
@@ -686,6 +685,8 @@ class LiveDefinitions:
686
685
  if isinstance(thing.addr, SpOffset):
687
686
  return self.get_stack_definitions(thing.addr.offset, thing.size)
688
687
  if isinstance(thing.addr, HeapAddress):
688
+ if isinstance(thing.addr.value, Undefined):
689
+ return set()
689
690
  return self.get_heap_definitions(thing.addr.value, size=thing.size)
690
691
  if isinstance(thing.addr, int):
691
692
  return self.get_memory_definitions(thing.addr, thing.size)
@@ -747,72 +748,9 @@ class LiveDefinitions:
747
748
 
748
749
  return LiveDefinitions.extract_defs_from_annotations(annotations)
749
750
 
750
- @deprecated("get_definitions")
751
- def get_definitions_from_atoms(self, atoms: Iterable[A]) -> Iterable[Definition]:
752
- result = set()
753
- for atom in atoms:
754
- result |= self.get_definitions(atom)
755
- return result
756
-
757
- @deprecated("get_values")
758
- def get_value_from_definition(self, definition: Definition) -> MultiValues | None:
759
- return self.get_value_from_atom(definition.atom)
760
-
761
- @deprecated("get_one_value")
762
- def get_one_value_from_definition(self, definition: Definition) -> claripy.ast.bv.BV | None:
763
- return self.get_one_value_from_atom(definition.atom)
764
-
765
- @deprecated("get_concrete_value")
766
- def get_concrete_value_from_definition(self, definition: Definition) -> int | None:
767
- return self.get_concrete_value_from_atom(definition.atom)
768
-
769
- @deprecated("get_values")
770
- def get_value_from_atom(self, atom: Atom) -> MultiValues | None:
771
- if isinstance(atom, Register):
772
- try:
773
- return self.registers.load(atom.reg_offset, size=atom.size)
774
- except SimMemoryMissingError:
775
- return None
776
- elif isinstance(atom, MemoryLocation):
777
- if isinstance(atom.addr, SpOffset):
778
- stack_addr = self.stack_offset_to_stack_addr(atom.addr.offset)
779
- try:
780
- return self.stack.load(stack_addr, size=atom.size, endness=atom.endness)
781
- except SimMemoryMissingError:
782
- return None
783
- elif isinstance(atom.addr, HeapAddress):
784
- try:
785
- return self.heap.load(atom.addr.value, size=atom.size, endness=atom.endness)
786
- except SimMemoryMissingError:
787
- return None
788
- elif isinstance(atom.addr, int):
789
- try:
790
- return self.memory.load(atom.addr, size=atom.size, endness=atom.endness)
791
- except SimMemoryMissingError:
792
- return None
793
- else:
794
- # ignore RegisterOffset
795
- return None
796
- else:
797
- return None
798
-
799
- @deprecated("get_one_value")
800
- def get_one_value_from_atom(self, atom: Atom) -> claripy.ast.bv.BV | None:
801
- r = self.get_value_from_atom(atom)
802
- if r is None:
803
- return None
804
- return r.one_value()
805
-
806
- @deprecated("get_concrete_value")
807
- def get_concrete_value_from_atom(self, atom: Atom) -> int | None:
808
- r = self.get_one_value_from_atom(atom)
809
- if r is None:
810
- return None
811
- if r.symbolic:
812
- return None
813
- return r.concrete_value
814
-
815
- def get_values(self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]]) -> MultiValues | None:
751
+ def get_values(
752
+ self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], endness: archinfo.Endness | None = None
753
+ ) -> MultiValues | None:
816
754
  if isinstance(spec, Definition):
817
755
  atom = spec.atom
818
756
  elif isinstance(spec, Atom):
@@ -820,7 +758,7 @@ class LiveDefinitions:
820
758
  else:
821
759
  result = None
822
760
  for atom in spec:
823
- r = self.get_values(atom)
761
+ r = self.get_values(atom, endness)
824
762
  if r is None:
825
763
  continue
826
764
  result = r if result is None else result.merge(r)
@@ -831,27 +769,29 @@ class LiveDefinitions:
831
769
  return self.registers.load(atom.reg_offset, size=atom.size)
832
770
  except SimMemoryMissingError:
833
771
  return None
834
- elif isinstance(atom, MemoryLocation):
772
+
773
+ if isinstance(atom, MemoryLocation):
774
+ endness = endness or atom.endness
835
775
  if isinstance(atom.addr, SpOffset):
836
776
  stack_addr = self.stack_offset_to_stack_addr(atom.addr.offset)
837
777
  try:
838
- return self.stack.load(stack_addr, size=atom.size, endness=atom.endness)
778
+ return self.stack.load(stack_addr, size=atom.size, endness=endness)
839
779
  except SimMemoryMissingError:
840
780
  return None
841
781
  elif isinstance(atom.addr, HeapAddress):
842
782
  try:
843
- return self.heap.load(atom.addr.value, size=atom.size, endness=atom.endness)
783
+ return self.heap.load(atom.addr.value, size=atom.size, endness=endness)
844
784
  except SimMemoryMissingError:
845
785
  return None
846
786
  elif isinstance(atom.addr, int):
847
787
  try:
848
- return self.memory.load(atom.addr, size=atom.size, endness=atom.endness)
788
+ return self.memory.load(atom.addr, size=atom.size, endness=endness)
849
789
  except SimMemoryMissingError:
850
790
  pass
851
791
  if self.project is not None:
852
792
  try:
853
793
  bytestring = self.project.loader.memory.load(atom.addr, atom.size)
854
- if atom.endness == archinfo.Endness.LE:
794
+ if endness == archinfo.Endness.LE:
855
795
  bytestring = bytes(reversed(bytestring))
856
796
  return MultiValues(
857
797
  self.annotate_with_def(claripy.BVV(bytestring), Definition(atom, ExternalCodeLocation()))
@@ -877,14 +817,12 @@ class LiveDefinitions:
877
817
 
878
818
  @overload
879
819
  def get_concrete_value(
880
- self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], cast_to: type[int] = ...
820
+ self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], cast_to: type[int]
881
821
  ) -> int | None: ...
882
822
 
883
823
  @overload
884
824
  def get_concrete_value(
885
- self,
886
- spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]],
887
- cast_to: type[bytes] = ...,
825
+ self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], cast_to: type[bytes]
888
826
  ) -> bytes | None: ...
889
827
 
890
828
  def get_concrete_value(
@@ -991,7 +929,7 @@ class LiveDefinitions:
991
929
 
992
930
  def deref(self, pointer, size, endness=archinfo.Endness.BE):
993
931
  if isinstance(pointer, (Atom, Definition)):
994
- pointer = self.get_values(pointer)
932
+ pointer = self.get_values(pointer, self.arch.memory_endness)
995
933
  if pointer is None:
996
934
  return set()
997
935
 
@@ -12,6 +12,7 @@ from cle.backends.elf.variable import Variable
12
12
 
13
13
  from angr.utils.orderedset import OrderedSet
14
14
  from angr.utils.ail import is_phi_assignment
15
+ from angr.utils.types import unpack_pointer, replace_pointer_pts_to
15
16
  from angr.protos import variables_pb2
16
17
  from angr.serializable import Serializable
17
18
  from angr.sim_variable import SimVariable, SimStackVariable, SimMemoryVariable, SimRegisterVariable
@@ -19,7 +20,6 @@ from angr.sim_type import (
19
20
  TypeRef,
20
21
  SimType,
21
22
  SimStruct,
22
- SimTypePointer,
23
23
  SimTypeBottom,
24
24
  SimTypeChar,
25
25
  SimTypeShort,
@@ -985,10 +985,12 @@ class VariableManagerInternal(Serializable):
985
985
  if name not in self.types:
986
986
  self.types[name] = TypeRef(name, ty).with_arch(self.manager._kb._project.arch)
987
987
  ty = self.types[name]
988
- elif isinstance(ty, SimTypePointer) and isinstance(ty.pts_to, SimStruct):
989
- typeref = self._register_struct_type(ty.pts_to)
990
- ty = ty.copy().with_arch(self.manager._kb._project.arch)
991
- ty.pts_to = typeref
988
+ elif (inner_ty := unpack_pointer(ty, iterative=True)) and isinstance(inner_ty, SimStruct):
989
+ typeref = self._register_struct_type(inner_ty)
990
+ # rebuild the multi-layer pointer type
991
+ replaced_ty = replace_pointer_pts_to(ty, inner_ty, typeref)
992
+ assert replaced_ty is not None
993
+ ty = replaced_ty.with_arch(self.manager._kb._project.arch)
992
994
  elif isinstance(ty, SimStruct):
993
995
  ty = self._register_struct_type(ty, name=name)
994
996
 
angr/sim_type.py CHANGED
@@ -20,10 +20,8 @@ from .misc.ux import deprecated
20
20
 
21
21
  if TYPE_CHECKING:
22
22
  from angr.procedures.definitions import SimTypeCollection
23
- from angr.storage.memory_mixins import _Coerce
24
-
25
- StoreType = _Coerce
26
23
 
24
+ StoreType = int | claripy.ast.BV
27
25
 
28
26
  l = logging.getLogger(name=__name__)
29
27
 
@@ -318,6 +316,8 @@ class SimTypeReg(SimType):
318
316
  return f"reg{self.size}_t"
319
317
 
320
318
  def store(self, state, addr, value: StoreType):
319
+ if self.size is None:
320
+ raise TypeError("Need a size to store")
321
321
  store_endness = state.arch.memory_endness
322
322
  with contextlib.suppress(AttributeError):
323
323
  value = value.ast # type: ignore
@@ -366,7 +366,7 @@ class SimTypeNum(SimType):
366
366
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
367
367
 
368
368
  @overload
369
- def extract(self, state, addr, concrete: Literal[True] = ...) -> int: ...
369
+ def extract(self, state, addr, concrete: Literal[True]) -> int: ...
370
370
 
371
371
  def extract(self, state, addr, concrete=False):
372
372
  out = state.memory.load(addr, self.size // state.arch.byte_width, endness=state.arch.memory_endness)
@@ -445,7 +445,7 @@ class SimTypeInt(SimTypeReg):
445
445
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
446
446
 
447
447
  @overload
448
- def extract(self, state, addr, concrete: Literal[True] = ...) -> int: ...
448
+ def extract(self, state, addr, concrete: Literal[True]) -> int: ...
449
449
 
450
450
  def extract(self, state, addr, concrete=False):
451
451
  out = state.memory.load(addr, self.size // state.arch.byte_width, endness=state.arch.memory_endness)
@@ -575,7 +575,7 @@ class SimTypeChar(SimTypeReg):
575
575
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
576
576
 
577
577
  @overload
578
- def extract(self, state, addr, concrete: Literal[True] = ...) -> bytes: ...
578
+ def extract(self, state, addr, concrete: Literal[True]) -> bytes: ...
579
579
 
580
580
  def extract(self, state, addr, concrete: bool = False) -> claripy.ast.BV | bytes:
581
581
  # FIXME: This is a hack.
@@ -665,7 +665,7 @@ class SimTypeBool(SimTypeReg):
665
665
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.Bool: ...
666
666
 
667
667
  @overload
668
- def extract(self, state, addr, concrete: Literal[True] = ...) -> bool: ...
668
+ def extract(self, state, addr, concrete: Literal[True]) -> bool: ...
669
669
 
670
670
  def extract(self, state, addr, concrete=False):
671
671
  ver = super().extract(state, addr, concrete)
@@ -715,7 +715,7 @@ class SimTypeFd(SimTypeReg):
715
715
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
716
716
 
717
717
  @overload
718
- def extract(self, state, addr, concrete: Literal[True] = ...) -> int: ...
718
+ def extract(self, state, addr, concrete: Literal[True]) -> int: ...
719
719
 
720
720
  def extract(self, state, addr, concrete=False):
721
721
  # TODO: EDG says this looks dangerously closed-minded. Just in case...
@@ -788,7 +788,7 @@ class SimTypePointer(SimTypeReg):
788
788
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
789
789
 
790
790
  @overload
791
- def extract(self, state, addr, concrete: Literal[True] = ...) -> int: ...
791
+ def extract(self, state, addr, concrete: Literal[True]) -> int: ...
792
792
 
793
793
  def extract(self, state, addr, concrete=False):
794
794
  # TODO: EDG says this looks dangerously closed-minded. Just in case...
@@ -848,7 +848,7 @@ class SimTypeReference(SimTypeReg):
848
848
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
849
849
 
850
850
  @overload
851
- def extract(self, state, addr, concrete: Literal[True] = ...) -> int: ...
851
+ def extract(self, state, addr, concrete: Literal[True]) -> int: ...
852
852
 
853
853
  def extract(self, state, addr, concrete=False):
854
854
  # TODO: EDG says this looks dangerously closed-minded. Just in case...
@@ -984,7 +984,7 @@ class SimTypeString(NamedTypeMixin, SimType):
984
984
  def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
985
985
 
986
986
  @overload
987
- def extract(self, state, addr, concrete: Literal[True] = ...) -> bytes: ...
987
+ def extract(self, state, addr, concrete: Literal[True]) -> bytes: ...
988
988
 
989
989
  def extract(self, state: SimState, addr, concrete=False):
990
990
  if self.length is None:
@@ -1585,7 +1585,7 @@ class SimStructValue:
1585
1585
  for name in self._struct.fields:
1586
1586
  value = self._values[name]
1587
1587
  try:
1588
- f = value.__indented_repr__
1588
+ f = value.__indented_repr__ # type: ignore[reportAttributeAccessIssue]
1589
1589
  s = f(indent=indent + 2)
1590
1590
  except AttributeError:
1591
1591
  s = repr(value)
@@ -1620,7 +1620,7 @@ class SimStructValue:
1620
1620
  class SimUnion(NamedTypeMixin, SimType):
1621
1621
  fields = ("members", "name")
1622
1622
 
1623
- def __init__(self, members, name=None, label=None):
1623
+ def __init__(self, members: dict[str, SimType], name=None, label=None):
1624
1624
  """
1625
1625
  :param members: The members of the union, as a mapping name -> type
1626
1626
  :param name: The name of the union
@@ -1630,6 +1630,8 @@ class SimUnion(NamedTypeMixin, SimType):
1630
1630
 
1631
1631
  @property
1632
1632
  def size(self):
1633
+ if self._arch is None:
1634
+ raise ValueError("Can't tell my size without an arch!")
1633
1635
  member_sizes = [ty.size for ty in self.members.values() if not isinstance(ty, SimTypeBottom)]
1634
1636
  # fall back to word size in case all members are SimTypeBottom
1635
1637
  return max(member_sizes) if member_sizes else self._arch.bytes
@@ -1722,7 +1724,7 @@ class SimUnionValue:
1722
1724
  fields = []
1723
1725
  for name, value in self._values.items():
1724
1726
  try:
1725
- f = value.__indented_repr__
1727
+ f = value.__indented_repr__ # type: ignore[reportAttributeAccessIssue]
1726
1728
  s = f(indent=indent + 2)
1727
1729
  except AttributeError:
1728
1730
  s = repr(value)
@@ -1820,7 +1822,7 @@ class SimCppClassValue(SimStructValue):
1820
1822
  for name in self._class.fields:
1821
1823
  value = self._values[name]
1822
1824
  try:
1823
- f = value.__indented_repr__
1825
+ f = value.__indented_repr__ # type: ignore[reportAttributeAccessIssue]
1824
1826
  s = f(indent=indent + 2)
1825
1827
  except AttributeError:
1826
1828
  s = repr(value)
@@ -1864,10 +1866,10 @@ class SimTypeNumOffset(SimTypeNum):
1864
1866
  self.offset = offset
1865
1867
 
1866
1868
  @overload
1867
- def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
1869
+ def extract(self, state: SimState, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
1868
1870
 
1869
1871
  @overload
1870
- def extract(self, state, addr, concrete: Literal[True] = ...) -> int: ...
1872
+ def extract(self, state: SimState, addr, concrete: Literal[True]) -> int: ...
1871
1873
 
1872
1874
  def extract(self, state: SimState, addr, concrete=False):
1873
1875
  if state.arch.memory_endness != Endness.LE:
angr/simos/simos.py CHANGED
@@ -23,7 +23,9 @@ class SimOS:
23
23
  A class describing OS/arch-level configuration.
24
24
  """
25
25
 
26
- def __init__(self, project: angr.Project, name=None):
26
+ name: str | None
27
+
28
+ def __init__(self, project: angr.Project, name: str | None = None):
27
29
  self.arch = project.arch
28
30
  self.project = project
29
31
  self.name = name