angr 9.2.143__py3-none-manylinux2014_aarch64.whl → 9.2.145__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 (49) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/calling_convention/calling_convention.py +13 -1
  3. angr/analyses/calling_convention/fact_collector.py +41 -5
  4. angr/analyses/cfg/cfg_base.py +7 -2
  5. angr/analyses/cfg/cfg_emulated.py +13 -4
  6. angr/analyses/cfg/cfg_fast.py +35 -61
  7. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +2 -0
  8. angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
  9. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +2 -1
  10. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2 -101
  11. angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
  12. angr/analyses/decompiler/ail_simplifier.py +5 -0
  13. angr/analyses/decompiler/clinic.py +163 -69
  14. angr/analyses/decompiler/decompiler.py +4 -4
  15. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +1 -1
  16. angr/analyses/decompiler/optimization_passes/optimization_pass.py +5 -5
  17. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +5 -0
  18. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +58 -2
  19. angr/analyses/decompiler/peephole_optimizations/__init__.py +2 -0
  20. angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
  21. angr/analyses/decompiler/ssailification/rewriting_engine.py +2 -0
  22. angr/analyses/decompiler/ssailification/ssailification.py +10 -2
  23. angr/analyses/decompiler/ssailification/traversal_engine.py +17 -2
  24. angr/analyses/decompiler/structured_codegen/c.py +25 -4
  25. angr/analyses/disassembly.py +3 -3
  26. angr/analyses/fcp/fcp.py +1 -4
  27. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +21 -22
  28. angr/analyses/stack_pointer_tracker.py +61 -25
  29. angr/analyses/typehoon/dfa.py +13 -3
  30. angr/analyses/typehoon/typehoon.py +60 -18
  31. angr/analyses/typehoon/typevars.py +11 -7
  32. angr/analyses/variable_recovery/engine_ail.py +13 -17
  33. angr/analyses/variable_recovery/engine_base.py +26 -30
  34. angr/analyses/variable_recovery/variable_recovery_fast.py +17 -21
  35. angr/knowledge_plugins/functions/function.py +29 -15
  36. angr/knowledge_plugins/key_definitions/constants.py +2 -2
  37. angr/knowledge_plugins/key_definitions/liveness.py +4 -4
  38. angr/lib/angr_native.so +0 -0
  39. angr/state_plugins/unicorn_engine.py +24 -8
  40. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +1 -2
  41. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +2 -2
  42. angr/utils/funcid.py +27 -2
  43. angr/utils/graph.py +26 -20
  44. {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/METADATA +11 -8
  45. {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/RECORD +49 -46
  46. {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/WHEEL +1 -1
  47. {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/LICENSE +0 -0
  48. {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/entry_points.txt +0 -0
  49. {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,18 @@
1
1
  # pylint:disable=bad-builtin
2
2
  from __future__ import annotations
3
3
  from typing import TYPE_CHECKING
4
+ from collections import defaultdict
4
5
 
5
6
  from angr.sim_type import SimStruct, SimTypePointer, SimTypeArray
6
7
  from angr.errors import AngrRuntimeError
7
8
  from angr.analyses.analysis import Analysis, AnalysesHub
9
+ from angr.sim_variable import SimVariable, SimStackVariable
8
10
  from .simple_solver import SimpleSolver
9
11
  from .translator import TypeTranslator
10
12
  from .typeconsts import Struct, Pointer, TypeConstant, Array, TopType
11
13
  from .typevars import Equivalence, Subtype, TypeVariable
12
14
 
13
15
  if TYPE_CHECKING:
14
- from angr.sim_variable import SimVariable
15
16
  from angr.sim_type import SimType
16
17
  from .typevars import TypeConstraint
17
18
 
@@ -38,6 +39,7 @@ class Typehoon(Analysis):
38
39
  var_mapping: dict[SimVariable, set[TypeVariable]] | None = None,
39
40
  must_struct: set[TypeVariable] | None = None,
40
41
  stackvar_max_sizes: dict[TypeVariable, int] | None = None,
42
+ stack_offset_tvs: dict[int, TypeVariable] | None = None,
41
43
  ):
42
44
  """
43
45
 
@@ -54,6 +56,7 @@ class Typehoon(Analysis):
54
56
  self._var_mapping = var_mapping
55
57
  self._must_struct = must_struct
56
58
  self._stackvar_max_sizes = stackvar_max_sizes if stackvar_max_sizes is not None else {}
59
+ self._stack_offset_tvs = stack_offset_tvs if stack_offset_tvs is not None else {}
57
60
 
58
61
  self.bits = self.project.arch.bits
59
62
  self.solution = None
@@ -70,25 +73,55 @@ class Typehoon(Analysis):
70
73
  # Public methods
71
74
  #
72
75
 
73
- def update_variable_types(self, func_addr: int | str, var_to_typevars):
76
+ def update_variable_types(
77
+ self,
78
+ func_addr: int | str,
79
+ var_to_typevars: dict[SimVariable, set[TypeVariable]],
80
+ stack_offset_tvs: dict[int, TypeVariable] | None = None,
81
+ ) -> None:
82
+
83
+ if not self.simtypes_solution:
84
+ return
85
+
74
86
  for var, typevars in var_to_typevars.items():
75
- for typevar in typevars:
87
+ # if the variable is a stack variable, does the stack offset have any corresponding type variable?
88
+ typevars_list = sorted(typevars, key=lambda tv: tv.idx)
89
+ if stack_offset_tvs and isinstance(var, SimStackVariable) and var.offset in stack_offset_tvs:
90
+ typevars_list.append(stack_offset_tvs[var.offset])
91
+
92
+ type_candidates: list[SimType] = []
93
+ for typevar in typevars_list:
76
94
  type_ = self.simtypes_solution.get(typevar, None)
77
- if type_ is not None:
78
- # print("{} -> {}: {}".format(var, typevar, type_))
79
- # Hack: if a global address is of a pointer type and it is not an array, we unpack the type
80
- if (
81
- func_addr == "global"
82
- and isinstance(type_, SimTypePointer)
83
- and not isinstance(type_.pts_to, SimTypeArray)
84
- ):
85
- type_ = type_.pts_to
86
-
87
- name = None
88
- if isinstance(type_, SimStruct):
89
- name = type_.name
90
-
91
- self.kb.variables[func_addr].set_variable_type(var, type_, name=name)
95
+ # print("{} -> {}: {}".format(var, typevar, type_))
96
+ # Hack: if a global address is of a pointer type and it is not an array, we unpack the type
97
+ if (
98
+ func_addr == "global"
99
+ and isinstance(type_, SimTypePointer)
100
+ and not isinstance(type_.pts_to, SimTypeArray)
101
+ ):
102
+ type_ = type_.pts_to
103
+ type_candidates.append(type_)
104
+
105
+ # determine the best type - this logic can be made better!
106
+ if not type_candidates:
107
+ continue
108
+ if len(type_candidates) > 1:
109
+ types_by_size: dict[int, list[SimType]] = defaultdict(list)
110
+ for t in type_candidates:
111
+ if t.size is not None:
112
+ types_by_size[t.size].append(t)
113
+ if not types_by_size:
114
+ # we only have BOT and TOP? damn
115
+ the_type = type_candidates[0]
116
+ else:
117
+ max_size = max(types_by_size.keys())
118
+ the_type = types_by_size[max_size][0] # TODO: Sort it
119
+ else:
120
+ the_type = type_candidates[0]
121
+
122
+ self.kb.variables[func_addr].set_variable_type(
123
+ var, the_type, name=the_type.name if isinstance(the_type, SimStruct) else None
124
+ )
92
125
 
93
126
  def pp_constraints(self) -> None:
94
127
  """
@@ -131,6 +164,8 @@ class Typehoon(Analysis):
131
164
  sol = self.solution[typevar]
132
165
  var_and_typevar = f"{typevar_to_var[typevar]} ({typevar})" if typevar in typevar_to_var else typevar
133
166
  print(f" {var_and_typevar} -> {sol}")
167
+ for stack_off, tv in self._stack_offset_tvs.items():
168
+ print(f" stack_{stack_off:#x} ({tv}) -> {self.solution[tv]}")
134
169
  print("### end of solutions ###")
135
170
 
136
171
  #
@@ -157,6 +192,7 @@ class Typehoon(Analysis):
157
192
  if self._var_mapping:
158
193
  for variable_typevars in self._var_mapping.values():
159
194
  typevars |= variable_typevars
195
+ typevars |= set(self._stack_offset_tvs.values())
160
196
  else:
161
197
  # collect type variables from constraints
162
198
  for constraint in self._constraints[self.func_var]:
@@ -175,6 +211,9 @@ class Typehoon(Analysis):
175
211
  - structs where every element is of the same type will be converted to an array of that element type.
176
212
  """
177
213
 
214
+ if not self.solution:
215
+ return
216
+
178
217
  for tv in list(self.solution.keys()):
179
218
  if self._must_struct and tv in self._must_struct:
180
219
  continue
@@ -223,6 +262,9 @@ class Typehoon(Analysis):
223
262
  Translate solutions in type variables to solutions in SimTypes.
224
263
  """
225
264
 
265
+ if not self.solution:
266
+ return
267
+
226
268
  simtypes_solution = {}
227
269
  translator = TypeTranslator(arch=self.project.arch)
228
270
  needs_backpatch = set()
@@ -397,11 +397,13 @@ class DerivedTypeVariable(TypeVariable):
397
397
  class TypeVariables:
398
398
  __slots__ = (
399
399
  "_last_typevars",
400
+ "_typevar2var",
400
401
  "_typevars",
401
402
  )
402
403
 
403
404
  def __init__(self):
404
405
  self._typevars: dict[SimVariable, set[TypeVariable]] = {}
406
+ self._typevar2var: dict[TypeVariable, SimVariable] = {}
405
407
  self._last_typevars: dict[SimVariable, TypeVariable] = {}
406
408
 
407
409
  def copy(self):
@@ -418,22 +420,24 @@ class TypeVariables:
418
420
  # )
419
421
  return f"{{TypeVars: {len(self._typevars)} items}}"
420
422
 
421
- def add_type_variable(self, var: SimVariable, codeloc, typevar: TypeType): # pylint:disable=unused-argument
423
+ def add_type_variable(self, var: SimVariable, typevar: TypeVariable, latest: bool = True):
422
424
  if var not in self._typevars:
423
425
  self._typevars[var] = set()
424
426
  elif typevar in self._typevars[var]:
425
427
  return
426
428
  self._typevars[var].add(typevar)
427
- self._last_typevars[var] = typevar
429
+ if latest:
430
+ self._last_typevars[var] = typevar
431
+ self._typevar2var[typevar] = var
428
432
 
429
- def get_type_variable(self, var, codeloc): # pylint:disable=unused-argument
433
+ def get_type_variable(self, var): # pylint:disable=unused-argument
430
434
  return self._last_typevars[var]
431
435
 
432
- def has_type_variable_for(self, var: SimVariable, codeloc): # pylint:disable=unused-argument
436
+ def has_type_variable_for(self, var: SimVariable): # pylint:disable=unused-argument
433
437
  return var in self._typevars
434
- # if codeloc not in self._typevars[var]:
435
- # return False
436
- # return True
438
+
439
+ def typevar_to_variable(self, typevar: TypeVariable) -> SimVariable | None:
440
+ return self._typevar2var.get(typevar, None)
437
441
 
438
442
  def __getitem__(self, var):
439
443
  return self._last_typevars[var]
@@ -9,14 +9,13 @@ from unique_log_filter import UniqueLogFilter
9
9
 
10
10
  from angr.engines.light.engine import SimEngineNostmtAIL
11
11
  from angr.procedures import SIM_LIBRARIES, SIM_TYPE_COLLECTIONS
12
- from angr.utils.constants import MAX_POINTSTO_BITS
13
12
  from angr.sim_type import SimTypeFunction, dereference_simtype
14
13
  from angr.analyses.typehoon import typeconsts, typevars
15
14
  from angr.analyses.typehoon.lifter import TypeLifter
16
15
  from .engine_base import SimEngineVRBase, RichR
17
16
 
18
17
  if TYPE_CHECKING:
19
- pass
18
+ from .variable_recovery_fast import VariableRecoveryFastState # noqa: F401
20
19
 
21
20
 
22
21
  l = logging.getLogger(name=__name__)
@@ -272,6 +271,8 @@ class SimEngineVRAIL(
272
271
  if arg.typevar is not None:
273
272
  arg_type = dereference_simtype(arg_type, type_collections).with_arch(arg_type._arch)
274
273
  arg_ty = TypeLifter(self.arch.bits).lift(arg_type)
274
+ if isinstance(arg_ty, typevars.TypeConstraint) and isinstance(arg.typevar, typevars.TypeConstraint):
275
+ continue
275
276
  type_constraint = typevars.Subtype(arg.typevar, arg_ty)
276
277
  self.state.add_type_constraint(type_constraint)
277
278
 
@@ -399,28 +400,23 @@ class SimEngineVRAIL(
399
400
  return RichR(self.state.top(expr.to_bits), typevar=typevar)
400
401
 
401
402
  def _handle_expr_StackBaseOffset(self, expr: ailment.Expr.StackBaseOffset):
402
- ref_typevar = self.state.stack_offset_typevars.get(expr.offset, None)
403
-
404
- if ref_typevar is None:
403
+ refbase_typevar = self.state.stack_offset_typevars.get(expr.offset, None)
404
+ if refbase_typevar is None:
405
405
  # allocate a new type variable
406
- ref_typevar = typevars.TypeVariable()
407
- self.state.stack_offset_typevars[expr.offset] = ref_typevar
406
+ refbase_typevar = typevars.TypeVariable()
407
+ self.state.stack_offset_typevars[expr.offset] = refbase_typevar
408
+
409
+ ref_typevar = typevars.TypeVariable()
410
+ access_derived_typevar = self._create_access_typevar(ref_typevar, False, None, 0)
411
+ load_constraint = typevars.Subtype(refbase_typevar, access_derived_typevar)
412
+ self.state.add_type_constraint(load_constraint)
408
413
 
409
414
  value_v = self.state.stack_address(expr.offset)
410
415
  richr = RichR(value_v, typevar=ref_typevar)
411
416
  codeloc = self._codeloc()
412
- var_and_offsets = self._ensure_variable_existence(richr, codeloc, src_expr=expr)
417
+ self._ensure_variable_existence(richr, codeloc, src_expr=expr)
413
418
  if self._reference_spoffset:
414
419
  self._reference(richr, codeloc, src=expr)
415
- for var, off_in_var in var_and_offsets:
416
- if self.state.typevars.has_type_variable_for(var, codeloc):
417
- var_typevar = self.state.typevars.get_type_variable(var, codeloc)
418
- load_typevar = self._create_access_typevar(
419
- ref_typevar, False, MAX_POINTSTO_BITS // 8, 0 if off_in_var is None else off_in_var
420
- )
421
- type_constraint = typevars.Subtype(var_typevar, load_typevar)
422
- self.state.add_type_constraint(type_constraint)
423
-
424
420
  return richr
425
421
 
426
422
  def _handle_expr_BasePointerOffset(self, expr):
@@ -15,7 +15,7 @@ from angr.sim_variable import SimVariable, SimStackVariable, SimRegisterVariable
15
15
  from angr.code_location import CodeLocation
16
16
  from angr.analyses.typehoon import typevars, typeconsts
17
17
  from angr.analyses.typehoon.typevars import TypeVariable, DerivedTypeVariable, AddN, SubN, Load, Store
18
-
18
+ from angr.utils.constants import MAX_POINTSTO_BITS
19
19
 
20
20
  #
21
21
  # The base engine used in VariableRecoveryFast
@@ -269,9 +269,9 @@ class SimEngineVRBase(
269
269
  return
270
270
  variable, _ = existing_vars[0]
271
271
 
272
- if not self.state.typevars.has_type_variable_for(variable, codeloc):
272
+ if not self.state.typevars.has_type_variable_for(variable):
273
273
  variable_typevar = typevars.TypeVariable()
274
- self.state.typevars.add_type_variable(variable, codeloc, variable_typevar)
274
+ self.state.typevars.add_type_variable(variable, variable_typevar)
275
275
  # we do not add any type constraint here because we are not sure if the given memory address will ever be
276
276
  # accessed or not
277
277
 
@@ -350,13 +350,13 @@ class SimEngineVRBase(
350
350
  self.state.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
351
351
 
352
352
  if richr.typevar is not None:
353
- if not self.state.typevars.has_type_variable_for(variable, codeloc):
353
+ if not self.state.typevars.has_type_variable_for(variable):
354
354
  # assign a new type variable to it
355
355
  typevar = typevars.TypeVariable()
356
- self.state.typevars.add_type_variable(variable, codeloc, typevar)
356
+ self.state.typevars.add_type_variable(variable, typevar)
357
357
  # create constraints
358
358
  else:
359
- typevar = self.state.typevars.get_type_variable(variable, codeloc)
359
+ typevar = self.state.typevars.get_type_variable(variable)
360
360
  self.state.add_type_constraint(typevars.Subtype(richr.typevar, typevar))
361
361
  self.state.add_type_constraint(typevars.Subtype(typevar, typeconsts.int_type(variable.size * 8)))
362
362
 
@@ -448,13 +448,13 @@ class SimEngineVRBase(
448
448
  self.state.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
449
449
 
450
450
  if richr.typevar is not None:
451
- if not self.state.typevars.has_type_variable_for(variable, codeloc):
451
+ if not self.state.typevars.has_type_variable_for(variable):
452
452
  # assign a new type variable to it
453
453
  typevar = typevars.TypeVariable()
454
- self.state.typevars.add_type_variable(variable, codeloc, typevar)
454
+ self.state.typevars.add_type_variable(variable, typevar)
455
455
  # create constraints
456
456
  else:
457
- typevar = self.state.typevars.get_type_variable(variable, codeloc)
457
+ typevar = self.state.typevars.get_type_variable(variable)
458
458
  self.state.add_type_constraint(typevars.Subtype(richr.typevar, typevar))
459
459
  # the constraint below is a default constraint that may conflict with more specific ones with different
460
460
  # sizes; we post-process at the very end of VRA to remove conflicting default constraints.
@@ -564,11 +564,11 @@ class SimEngineVRBase(
564
564
 
565
565
  # create type constraints
566
566
  if data.typevar is not None:
567
- if not self.state.typevars.has_type_variable_for(variable, codeloc):
567
+ if not self.state.typevars.has_type_variable_for(variable):
568
568
  typevar = typevars.TypeVariable()
569
- self.state.typevars.add_type_variable(variable, codeloc, typevar)
569
+ self.state.typevars.add_type_variable(variable, typevar)
570
570
  else:
571
- typevar = self.state.typevars.get_type_variable(variable, codeloc)
571
+ typevar = self.state.typevars.get_type_variable(variable)
572
572
  if typevar is not None:
573
573
  self.state.add_type_constraint(typevars.Subtype(data.typevar, typevar))
574
574
  # TODO: Create a tv_sp.store.<bits>@N <: typevar type constraint for the stack pointer
@@ -640,11 +640,11 @@ class SimEngineVRBase(
640
640
  variable_manager.write_to(var, var_offset, codeloc, atom=stmt)
641
641
 
642
642
  # create type constraints
643
- if not self.state.typevars.has_type_variable_for(variable, codeloc):
643
+ if not self.state.typevars.has_type_variable_for(variable):
644
644
  typevar = typevars.TypeVariable()
645
- self.state.typevars.add_type_variable(variable, codeloc, typevar)
645
+ self.state.typevars.add_type_variable(variable, typevar)
646
646
  else:
647
- typevar = self.state.typevars.get_type_variable(variable, codeloc)
647
+ typevar = self.state.typevars.get_type_variable(variable)
648
648
 
649
649
  if offset is not None and elem_size is not None:
650
650
  # it's an array!
@@ -671,9 +671,6 @@ class SimEngineVRBase(
671
671
  self.state.add_type_constraint(typevars.Subtype(data.typevar, store_typevar))
672
672
 
673
673
  def _store_to_variable(self, richr_addr: RichR[claripy.ast.BV], data: RichR, size: int):
674
- addr_variable = richr_addr.variable
675
- codeloc = self._codeloc()
676
-
677
674
  # Storing data into a pointer
678
675
  if richr_addr.type_constraints:
679
676
  for tc in richr_addr.type_constraints:
@@ -690,8 +687,6 @@ class SimEngineVRBase(
690
687
  field_offset = 0
691
688
 
692
689
  store_typevar = self._create_access_typevar(base_typevar, True, size, field_offset)
693
- if addr_variable is not None:
694
- self.state.typevars.add_type_variable(addr_variable, codeloc, typevar)
695
690
  data_typevar = data.typevar if data.typevar is not None else typeconsts.TopType()
696
691
  self.state.add_type_constraint(typevars.Subtype(store_typevar, data_typevar))
697
692
 
@@ -823,11 +818,11 @@ class SimEngineVRBase(
823
818
  self.state.delayed_type_constraints.pop(var)
824
819
 
825
820
  # create type constraints
826
- if not self.state.typevars.has_type_variable_for(var, codeloc):
821
+ if not self.state.typevars.has_type_variable_for(var):
827
822
  typevar = typevars.TypeVariable()
828
- self.state.typevars.add_type_variable(var, codeloc, typevar)
823
+ self.state.typevars.add_type_variable(var, typevar)
829
824
  else:
830
- typevar = self.state.typevars.get_type_variable(var, codeloc)
825
+ typevar = self.state.typevars.get_type_variable(var)
831
826
 
832
827
  else:
833
828
  typevar = typevars.TypeVariable()
@@ -933,11 +928,11 @@ class SimEngineVRBase(
933
928
 
934
929
  variable, _ = next(iter(existing_vars))
935
930
  # create type constraints
936
- if not self.state.typevars.has_type_variable_for(variable, codeloc):
931
+ if not self.state.typevars.has_type_variable_for(variable):
937
932
  typevar = typevars.TypeVariable()
938
- self.state.typevars.add_type_variable(variable, codeloc, typevar)
933
+ self.state.typevars.add_type_variable(variable, typevar)
939
934
  else:
940
- typevar = self.state.typevars.get_type_variable(variable, codeloc)
935
+ typevar = self.state.typevars.get_type_variable(variable)
941
936
 
942
937
  if offset is not None and elem_size is not None:
943
938
  # it's an array!
@@ -1024,7 +1019,7 @@ class SimEngineVRBase(
1024
1019
 
1025
1020
  if var not in self.state.typevars:
1026
1021
  typevar = typevars.TypeVariable()
1027
- self.state.typevars.add_type_variable(var, codeloc, typevar)
1022
+ self.state.typevars.add_type_variable(var, typevar)
1028
1023
  else:
1029
1024
  # FIXME: This is an extremely stupid hack. Fix it later.
1030
1025
  # | typevar = next(reversed(list(self.state.typevars[var].values())))
@@ -1125,7 +1120,7 @@ class SimEngineVRBase(
1125
1120
 
1126
1121
  if var not in self.state.typevars:
1127
1122
  typevar = typevars.TypeVariable()
1128
- self.state.typevars.add_type_variable(var, codeloc, typevar)
1123
+ self.state.typevars.add_type_variable(var, typevar)
1129
1124
  else:
1130
1125
  # FIXME: This is an extremely stupid hack. Fix it later.
1131
1126
  # | typevar = next(reversed(list(self.state.typevars[var].values())))
@@ -1140,7 +1135,7 @@ class SimEngineVRBase(
1140
1135
  self,
1141
1136
  typevar: typeconsts.TypeConstant | TypeVariable | DerivedTypeVariable,
1142
1137
  is_store: bool,
1143
- size: int,
1138
+ size: int | None,
1144
1139
  offset: int,
1145
1140
  ) -> DerivedTypeVariable:
1146
1141
  if isinstance(typevar, DerivedTypeVariable):
@@ -1157,8 +1152,9 @@ class SimEngineVRBase(
1157
1152
  else:
1158
1153
  typevar = DerivedTypeVariable(typevar.type_var, None, labels=typevar.labels[:-1])
1159
1154
  lbl = Store() if is_store else Load()
1155
+ bits = size * self.project.arch.byte_width if size is not None else MAX_POINTSTO_BITS
1160
1156
  return DerivedTypeVariable(
1161
1157
  typevar,
1162
1158
  None,
1163
- labels=(lbl, typevars.HasField(size * self.project.arch.byte_width, offset)),
1159
+ labels=(lbl, typevars.HasField(bits, offset)),
1164
1160
  )
@@ -47,6 +47,7 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
47
47
  analysis,
48
48
  arch,
49
49
  func,
50
+ project,
50
51
  stack_region=None,
51
52
  register_region=None,
52
53
  global_region=None,
@@ -55,7 +56,6 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
55
56
  func_typevar=None,
56
57
  delayed_type_constraints=None,
57
58
  stack_offset_typevars=None,
58
- project=None,
59
59
  ret_val_size=None,
60
60
  ):
61
61
  super().__init__(
@@ -63,6 +63,7 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
63
63
  analysis,
64
64
  arch,
65
65
  func,
66
+ project,
66
67
  stack_region=stack_region,
67
68
  register_region=register_region,
68
69
  global_region=global_region,
@@ -71,12 +72,11 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
71
72
  func_typevar=func_typevar,
72
73
  delayed_type_constraints=delayed_type_constraints,
73
74
  stack_offset_typevars=stack_offset_typevars,
74
- project=project,
75
75
  )
76
76
  self.ret_val_size = ret_val_size
77
77
 
78
78
  def __repr__(self):
79
- return f"<VRAbstractState@{self.block_addr:#x}: {len(self.register_region)} register variables, {len(self.stack_region)} stack variables>"
79
+ return f"<VRAbstractState@{self.block_addr:#x}"
80
80
 
81
81
  def __eq__(self, other):
82
82
  if type(other) is not VariableRecoveryFastState:
@@ -96,12 +96,14 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
96
96
  type_constraints=self.type_constraints,
97
97
  func_typevar=self.func_typevar,
98
98
  delayed_type_constraints=self.delayed_type_constraints,
99
- stack_offset_typevars=dict(self.stack_offset_typevars),
99
+ stack_offset_typevars=self.stack_offset_typevars,
100
100
  project=self.project,
101
101
  ret_val_size=self.ret_val_size,
102
102
  )
103
103
 
104
- def merge(self, others: tuple[VariableRecoveryFastState], successor=None) -> tuple[VariableRecoveryFastState, bool]:
104
+ def merge(
105
+ self, others: tuple[VariableRecoveryFastState, ...], successor=None
106
+ ) -> tuple[VariableRecoveryFastState, bool]:
105
107
  """
106
108
  Merge two abstract states.
107
109
 
@@ -135,10 +137,10 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
135
137
  # add subtype constraints for all replacements
136
138
  for v0, v1 in self.phi_variables.items():
137
139
  # v0 will be replaced by v1
138
- if not typevars.has_type_variable_for(v1, None):
139
- typevars.add_type_variable(v1, None, TypeVariable())
140
- if not typevars.has_type_variable_for(v0, None):
141
- typevars.add_type_variable(v0, None, TypeVariable())
140
+ if not typevars.has_type_variable_for(v1):
141
+ typevars.add_type_variable(v1, TypeVariable())
142
+ if not typevars.has_type_variable_for(v0):
143
+ typevars.add_type_variable(v0, TypeVariable())
142
144
  # Assuming v2 = phi(v0, v1), then we know that v0_typevar == v1_typevar == v2_typevar
143
145
  # However, it's possible that neither v0 nor v1 will ever be used in future blocks, which not only makes
144
146
  # this phi function useless, but also leads to the incorrect assumption that v1_typevar == v2_typevar.
@@ -146,7 +148,7 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
146
148
  # when v1 (the new variable that will end up in the state) is ever used in the future.
147
149
 
148
150
  # create an equivalence relationship
149
- equivalence = Equivalence(typevars.get_type_variable(v1, None), typevars.get_type_variable(v0, None))
151
+ equivalence = Equivalence(typevars.get_type_variable(v1), typevars.get_type_variable(v0))
150
152
  delayed_typeconstraints[v1].add(equivalence)
151
153
 
152
154
  stack_offset_typevars = {}
@@ -281,6 +283,7 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
281
283
  self.func_typevar = TypeVariable(name=func.name)
282
284
  self.delayed_type_constraints = None
283
285
  self.ret_val_size = None
286
+ self.stack_offset_typevars: dict[int, TypeVariable] = {}
284
287
 
285
288
  self._analyze()
286
289
 
@@ -328,6 +331,7 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
328
331
  type_constraints=self.type_constraints,
329
332
  func_typevar=self.func_typevar,
330
333
  delayed_type_constraints=self.delayed_type_constraints,
334
+ stack_offset_typevars=self.stack_offset_typevars,
331
335
  )
332
336
  initial_sp = state.stack_address(self.project.arch.bytes if self.project.arch.call_pushes_ret else 0)
333
337
  if self.project.arch.sp_offset is not None:
@@ -439,20 +443,10 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
439
443
  block = self.project.factory.block(node.addr, node.size, opt_level=1, cross_insn_opt=False)
440
444
  block_key = node.addr
441
445
 
442
- # if node.addr in self._instates:
443
- # prev_state: VariableRecoveryFastState = self._instates[node.addr]
444
- # if input_state == prev_state:
445
- # l.debug('Skip node %#x as we have reached a fixed-point', node.addr)
446
- # return False, input_state
447
- # else:
448
- # l.debug('Merging input state of node %#x with the previous state.', node.addr)
449
- # input_state, _ = prev_state.merge((input_state,), successor=node.addr)
450
-
451
446
  state = state.copy()
452
447
  state.block_addr = node.addr
453
448
  if isinstance(node, ailment.Block):
454
449
  state.block_idx = node.idx
455
- # self._instates[node.addr] = state
456
450
 
457
451
  if self._node_iterations[block_key] >= self._max_iterations:
458
452
  l.debug("Skip node %#x as we have iterated %d times on it.", node.addr, self._node_iterations[node.addr])
@@ -491,10 +485,12 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
491
485
  self.variable_manager[self.function.addr].unify_variables()
492
486
 
493
487
  # fill in var_to_typevars
488
+ assert self.typevars is not None
494
489
  for var, typevar_set in self.typevars._typevars.items():
495
490
  self.var_to_typevars[var] = typevar_set
496
491
 
497
492
  # unify type variables for global variables
493
+ assert self.type_constraints is not None
498
494
  for var, typevars in self.var_to_typevars.items():
499
495
  if len(typevars) > 1 and isinstance(var, SimMemoryVariable) and not isinstance(var, SimStackVariable):
500
496
  sorted_typevars = sorted(typevars, key=lambda x: str(x)) # pylint:disable=unnecessary-lambda
@@ -600,7 +596,7 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
600
596
  block = self._peephole_optimize(block)
601
597
 
602
598
  processor = self._ail_engine if isinstance(block, ailment.Block) else self._vex_engine
603
- processor.process(state, block=block, fail_fast=self._fail_fast)
599
+ processor.process(state, block=block, fail_fast=self._fail_fast) # type: ignore
604
600
 
605
601
  if self._track_sp and block.addr in self._node_to_cc:
606
602
  # readjusting sp at the end for blocks that end in a call
@@ -237,21 +237,7 @@ class Function(Serializable):
237
237
 
238
238
  self._returning = self._get_initial_returning()
239
239
 
240
- # Determine a calling convention
241
- # If it is a SimProcedure it might have a CC already defined which can be used
242
- if self.is_simprocedure and self.project is not None and self.addr in self.project._sim_procedures:
243
- simproc = self.project._sim_procedures[self.addr]
244
- cc = simproc.cc
245
- if cc is None:
246
- arch = self.project.arch
247
- if self.project.arch.name in DEFAULT_CC:
248
- cc = default_cc(
249
- arch.name, platform=self.project.simos.name if self.project.simos is not None else None
250
- )(arch)
251
-
252
- self.calling_convention: SimCC | None = cc
253
- else:
254
- self.calling_convention: SimCC | None = None
240
+ self._init_prototype_and_calling_convention()
255
241
 
256
242
  @property
257
243
  @deprecated(".is_alignment")
@@ -768,6 +754,34 @@ class Function(Serializable):
768
754
  # Cannot determine
769
755
  return None
770
756
 
757
+ def _init_prototype_and_calling_convention(self) -> None:
758
+ """
759
+ Initialize prototype and calling convention from a SimProcedure, if available.
760
+ """
761
+ hooker = None
762
+ if self.is_syscall and self.project is not None and self.project.simos.is_syscall_addr(self.addr):
763
+ hooker = self.project.simos.syscall_from_addr(self.addr)
764
+ elif self.is_simprocedure and self.project is not None:
765
+ hooker = self.project.hooked_by(self.addr)
766
+ if hooker is None or hooker.guessed_prototype:
767
+ return
768
+
769
+ if hooker.prototype:
770
+ self.prototype_libname = hooker.library_name
771
+ self.prototype = hooker.prototype
772
+ self.is_prototype_guessed = False
773
+
774
+ cc = hooker.cc
775
+ if cc is None and self.project is not None:
776
+ arch = self.project.arch
777
+ if arch.name in DEFAULT_CC:
778
+ cc_cls = default_cc(
779
+ arch.name, platform=self.project.simos.name if self.project.simos is not None else None
780
+ )
781
+ if cc_cls is not None:
782
+ cc = cc_cls(arch)
783
+ self.calling_convention = cc
784
+
771
785
  def _clear_transition_graph(self):
772
786
  self._block_sizes = {}
773
787
  self._addr_to_block_node = {}
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import Literal, Union
2
+ from typing import Literal
3
3
  import enum
4
4
 
5
5
  DEBUG = False
@@ -25,5 +25,5 @@ OP_BEFORE = ObservationPointType.OP_BEFORE
25
25
  OP_AFTER = ObservationPointType.OP_AFTER
26
26
 
27
27
  ObservationPoint = tuple[
28
- Literal["insn", "node", "stmt", "exit"], Union[int, tuple[int, int], tuple[int, int, int]], ObservationPointType
28
+ Literal["insn", "node", "stmt", "exit"], int | tuple[int, int] | tuple[int, int, int], ObservationPointType
29
29
  ]
@@ -1,5 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import Optional, TYPE_CHECKING
2
+ from typing import TYPE_CHECKING
3
3
 
4
4
  from collections import defaultdict
5
5
  from itertools import chain
@@ -14,11 +14,11 @@ if TYPE_CHECKING:
14
14
  from angr.code_location import CodeLocation
15
15
 
16
16
 
17
- LocationType = tuple[int, Optional[int], Optional[int]] # block addr, block ID, stmt ID
17
+ LocationType = tuple[int, int | None, int | None] # block addr, block ID, stmt ID
18
18
  LocationWithPosType = tuple[
19
- int, Optional[int], Optional[int], ObservationPointType
19
+ int, int | None, int | None, ObservationPointType
20
20
  ] # block addr, block ID, stmt ID, before/after
21
- BlockAddrType = tuple[int, Optional[int]] # block addr, block ID
21
+ BlockAddrType = tuple[int, int | None] # block addr, block ID
22
22
 
23
23
 
24
24
  class Liveness:
angr/lib/angr_native.so CHANGED
Binary file