angr 9.2.135__py3-none-macosx_11_0_arm64.whl → 9.2.136__py3-none-macosx_11_0_arm64.whl

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

Potentially problematic release.


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

Files changed (166) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/__init__.py +3 -7
  3. angr/analyses/analysis.py +4 -0
  4. angr/analyses/backward_slice.py +1 -2
  5. angr/analyses/binary_optimizer.py +3 -4
  6. angr/analyses/bindiff.py +4 -6
  7. angr/analyses/boyscout.py +1 -3
  8. angr/analyses/callee_cleanup_finder.py +4 -4
  9. angr/analyses/calling_convention/calling_convention.py +4 -3
  10. angr/analyses/calling_convention/fact_collector.py +0 -1
  11. angr/analyses/cdg.py +1 -2
  12. angr/analyses/cfg/cfb.py +1 -3
  13. angr/analyses/cfg/cfg.py +2 -2
  14. angr/analyses/cfg/cfg_base.py +37 -35
  15. angr/analyses/cfg/cfg_emulated.py +1 -1
  16. angr/analyses/cfg/cfg_fast.py +62 -15
  17. angr/analyses/cfg/cfg_fast_soot.py +1 -1
  18. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +2 -0
  19. angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +46 -10
  20. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +5 -1
  21. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +50 -14
  22. angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
  23. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +24 -5
  24. angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +2 -5
  25. angr/analyses/congruency_check.py +2 -3
  26. angr/analyses/data_dep/data_dependency_analysis.py +2 -2
  27. angr/analyses/ddg.py +1 -4
  28. angr/analyses/decompiler/ail_simplifier.py +3 -4
  29. angr/analyses/decompiler/clinic.py +42 -7
  30. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +2 -2
  31. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +2 -2
  32. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +1 -1
  33. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
  34. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
  35. angr/analyses/decompiler/structuring/phoenix.py +1 -1
  36. angr/analyses/disassembly.py +5 -5
  37. angr/analyses/fcp/__init__.py +4 -0
  38. angr/analyses/fcp/fcp.py +429 -0
  39. angr/analyses/identifier/identify.py +1 -3
  40. angr/analyses/loopfinder.py +4 -3
  41. angr/analyses/patchfinder.py +1 -1
  42. angr/analyses/propagator/engine_base.py +4 -3
  43. angr/analyses/propagator/propagator.py +14 -53
  44. angr/analyses/reassembler.py +1 -2
  45. angr/analyses/s_propagator.py +1 -3
  46. angr/analyses/soot_class_hierarchy.py +1 -2
  47. angr/analyses/stack_pointer_tracker.py +18 -2
  48. angr/analyses/static_hooker.py +1 -2
  49. angr/analyses/typehoon/simple_solver.py +2 -2
  50. angr/analyses/variable_recovery/variable_recovery_fast.py +1 -2
  51. angr/analyses/veritesting.py +4 -7
  52. angr/analyses/vfg.py +1 -1
  53. angr/analyses/vsa_ddg.py +1 -2
  54. angr/block.py +3 -2
  55. angr/callable.py +1 -3
  56. angr/calling_conventions.py +3 -3
  57. angr/codenode.py +5 -1
  58. angr/concretization_strategies/__init__.py +1 -83
  59. angr/concretization_strategies/any.py +2 -1
  60. angr/concretization_strategies/any_named.py +1 -1
  61. angr/concretization_strategies/base.py +81 -0
  62. angr/concretization_strategies/controlled_data.py +2 -1
  63. angr/concretization_strategies/eval.py +2 -1
  64. angr/concretization_strategies/logging.py +3 -1
  65. angr/concretization_strategies/max.py +2 -1
  66. angr/concretization_strategies/nonzero.py +2 -1
  67. angr/concretization_strategies/nonzero_range.py +2 -1
  68. angr/concretization_strategies/norepeats.py +2 -1
  69. angr/concretization_strategies/norepeats_range.py +2 -1
  70. angr/concretization_strategies/range.py +2 -1
  71. angr/concretization_strategies/signed_add.py +2 -1
  72. angr/concretization_strategies/single.py +2 -1
  73. angr/concretization_strategies/solutions.py +2 -1
  74. angr/concretization_strategies/unlimited_range.py +2 -1
  75. angr/engines/__init__.py +8 -5
  76. angr/engines/engine.py +3 -5
  77. angr/engines/failure.py +4 -5
  78. angr/engines/procedure.py +5 -7
  79. angr/engines/soot/expressions/__init__.py +22 -23
  80. angr/engines/soot/expressions/base.py +4 -4
  81. angr/engines/soot/expressions/invoke.py +1 -2
  82. angr/engines/soot/statements/__init__.py +9 -10
  83. angr/engines/soot/values/__init__.py +9 -10
  84. angr/engines/soot/values/arrayref.py +3 -3
  85. angr/engines/soot/values/instancefieldref.py +3 -2
  86. angr/engines/successors.py +7 -6
  87. angr/engines/syscall.py +4 -6
  88. angr/engines/unicorn.py +3 -2
  89. angr/engines/vex/claripy/ccall.py +8 -10
  90. angr/engines/vex/claripy/datalayer.py +4 -5
  91. angr/exploration_techniques/__init__.py +0 -2
  92. angr/exploration_techniques/spiller.py +1 -3
  93. angr/exploration_techniques/stochastic.py +2 -3
  94. angr/factory.py +3 -9
  95. angr/knowledge_plugins/cfg/cfg_model.py +20 -17
  96. angr/knowledge_plugins/functions/function.py +70 -73
  97. angr/knowledge_plugins/functions/function_manager.py +8 -7
  98. angr/knowledge_plugins/functions/function_parser.py +1 -1
  99. angr/knowledge_plugins/functions/soot_function.py +16 -16
  100. angr/knowledge_plugins/propagations/propagation_model.py +4 -5
  101. angr/knowledge_plugins/propagations/states.py +0 -511
  102. angr/lib/angr_native.dylib +0 -0
  103. angr/procedures/libc/memcpy.py +4 -4
  104. angr/procedures/procedure_dict.py +3 -2
  105. angr/protos/__init__.py +2 -5
  106. angr/protos/cfg_pb2.py +21 -18
  107. angr/protos/function_pb2.py +17 -14
  108. angr/protos/primitives_pb2.py +44 -39
  109. angr/protos/variables_pb2.py +36 -31
  110. angr/protos/xrefs_pb2.py +15 -12
  111. angr/sim_procedure.py +15 -16
  112. angr/sim_variable.py +13 -1
  113. angr/simos/__init__.py +2 -0
  114. angr/simos/javavm.py +4 -6
  115. angr/simos/xbox.py +32 -0
  116. angr/state_plugins/__init__.py +0 -2
  117. angr/state_plugins/callstack.py +4 -4
  118. angr/state_plugins/cgc.py +3 -2
  119. angr/state_plugins/gdb.py +6 -5
  120. angr/state_plugins/globals.py +1 -2
  121. angr/state_plugins/heap/heap_brk.py +1 -2
  122. angr/state_plugins/history.py +10 -12
  123. angr/state_plugins/inspect.py +3 -5
  124. angr/state_plugins/libc.py +2 -2
  125. angr/state_plugins/log.py +8 -10
  126. angr/state_plugins/loop_data.py +1 -2
  127. angr/state_plugins/posix.py +7 -7
  128. angr/state_plugins/preconstrainer.py +2 -3
  129. angr/state_plugins/scratch.py +5 -8
  130. angr/state_plugins/sim_action.py +3 -3
  131. angr/state_plugins/solver.py +8 -3
  132. angr/state_plugins/symbolizer.py +5 -4
  133. angr/state_plugins/uc_manager.py +3 -3
  134. angr/state_plugins/unicorn_engine.py +5 -1
  135. angr/state_plugins/view.py +3 -5
  136. angr/storage/file.py +3 -5
  137. angr/storage/memory_mixins/address_concretization_mixin.py +2 -2
  138. angr/storage/memory_mixins/bvv_conversion_mixin.py +3 -3
  139. angr/storage/memory_mixins/clouseau_mixin.py +1 -3
  140. angr/storage/memory_mixins/name_resolution_mixin.py +1 -3
  141. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +13 -15
  142. angr/storage/memory_mixins/paged_memory/pages/__init__.py +1 -22
  143. angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
  144. angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
  145. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
  146. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
  147. angr/storage/memory_mixins/paged_memory/privileged_mixin.py +3 -4
  148. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +4 -2
  149. angr/storage/memory_mixins/smart_find_mixin.py +1 -1
  150. angr/storage/memory_mixins/underconstrained_mixin.py +1 -1
  151. angr/storage/memory_mixins/unwrapper_mixin.py +1 -3
  152. angr/utils/enums_conv.py +28 -12
  153. angr/utils/segment_list.py +25 -22
  154. angr/utils/timing.py +18 -1
  155. angr/vaults.py +5 -6
  156. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/METADATA +6 -6
  157. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/RECORD +161 -160
  158. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/WHEEL +1 -1
  159. angr/analyses/propagator/outdated_definition_walker.py +0 -159
  160. angr/analyses/propagator/tmpvar_finder.py +0 -18
  161. angr/engines/concrete.py +0 -180
  162. angr/exploration_techniques/symbion.py +0 -80
  163. angr/state_plugins/concrete.py +0 -295
  164. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/LICENSE +0 -0
  165. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/entry_points.txt +0 -0
  166. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,14 @@
1
+ # pylint:disable=too-many-boolean-expressions
1
2
  from __future__ import annotations
2
3
  import os
3
4
  import logging
4
- import networkx
5
5
  import itertools
6
6
  from collections import defaultdict
7
7
  from collections.abc import Iterable
8
+ import contextlib
9
+ from typing import overload
8
10
 
11
+ import networkx
9
12
  from itanium_demangler import parse
10
13
 
11
14
  from cle.backends.symbol import Symbol
@@ -13,7 +16,6 @@ from archinfo.arch_arm import get_real_address_if_arm
13
16
  import claripy
14
17
 
15
18
  from angr.knowledge_plugins.cfg.memory_data import MemoryDataSort
16
-
17
19
  from angr.codenode import CodeNode, BlockNode, HookNode, SyscallNode
18
20
  from angr.serializable import Serializable
19
21
  from angr.errors import AngrValueError, SimEngineError, SimMemoryError
@@ -22,14 +24,12 @@ from angr.procedures.definitions import SimSyscallLibrary
22
24
  from angr.protos import function_pb2
23
25
  from angr.calling_conventions import DEFAULT_CC, default_cc
24
26
  from angr.misc.ux import deprecated
25
- from .function_parser import FunctionParser
26
-
27
- l = logging.getLogger(name=__name__)
28
-
29
27
  from angr.sim_type import SimTypeFunction, parse_defns
30
28
  from angr.calling_conventions import SimCC
31
29
  from angr.project import Project
32
- import contextlib
30
+ from .function_parser import FunctionParser
31
+
32
+ l = logging.getLogger(name=__name__)
33
33
 
34
34
 
35
35
  class Function(Serializable):
@@ -41,7 +41,6 @@ class Function(Serializable):
41
41
  "_addr_to_block_node",
42
42
  "_argument_registers",
43
43
  "_argument_stack_variables",
44
- "_block_cache",
45
44
  "_block_sizes",
46
45
  "_call_sites",
47
46
  "_callout_sites",
@@ -158,7 +157,6 @@ class Function(Serializable):
158
157
  # function, it may not be removed from _addr_to_block_node. if you want to list
159
158
  # all blocks of a function, access .blocks.
160
159
  self._block_sizes = {} # map addresses to block sizes
161
- self._block_cache = {} # a cache of real, hard data Block objects
162
160
  self._local_blocks = {} # a dict of all blocks inside the function
163
161
  self._local_block_addrs = set() # a set of addresses of all blocks inside the function
164
162
 
@@ -374,13 +372,6 @@ class Function(Serializable):
374
372
  :param byte_string:
375
373
  :return:
376
374
  """
377
- if addr in self._block_cache:
378
- b = self._block_cache[addr]
379
- if size is None or b.size == size:
380
- return b
381
- # size seems to be updated. remove this cached entry from the block cache
382
- del self._block_cache[addr]
383
-
384
375
  if size is None and addr in self.block_addrs:
385
376
  # we know the size
386
377
  size = self._block_sizes[addr]
@@ -389,7 +380,6 @@ class Function(Serializable):
389
380
  if size is None:
390
381
  # update block_size dict
391
382
  self._block_sizes[addr] = block.size
392
- self._block_cache[addr] = block
393
383
  return block
394
384
 
395
385
  # compatibility
@@ -440,7 +430,7 @@ class Function(Serializable):
440
430
 
441
431
  @classmethod
442
432
  def _get_cmsg(cls):
443
- return function_pb2.Function()
433
+ return function_pb2.Function() # pylint:disable=no-member
444
434
 
445
435
  def serialize_to_cmessage(self):
446
436
  return FunctionParser.serialize(self)
@@ -613,7 +603,6 @@ class Function(Serializable):
613
603
  d["_local_transition_graph"] = None
614
604
  d["_project"] = None
615
605
  d["_function_manager"] = None
616
- d["_block_cache"] = {}
617
606
  return d
618
607
 
619
608
  @property
@@ -642,7 +631,7 @@ class Function(Serializable):
642
631
 
643
632
  @property
644
633
  def size(self):
645
- return sum([b.size for b in self.blocks])
634
+ return sum(b.size for b in self.blocks)
646
635
 
647
636
  @property
648
637
  def binary(self):
@@ -675,7 +664,7 @@ class Function(Serializable):
675
664
  dec = self.project.analyses.Decompiler(self, cfg=self._function_manager._kb.cfgs.get_most_accurate())
676
665
  return dec.codegen.text
677
666
 
678
- def add_jumpout_site(self, node):
667
+ def add_jumpout_site(self, node: CodeNode):
679
668
  """
680
669
  Add a custom jumpout site.
681
670
 
@@ -683,11 +672,11 @@ class Function(Serializable):
683
672
  :return: None
684
673
  """
685
674
 
686
- self._register_nodes(True, node)
675
+ node = self._register_node(True, node)
687
676
  self._jumpout_sites.add(node)
688
677
  self._add_endpoint(node, "transition")
689
678
 
690
- def add_retout_site(self, node):
679
+ def add_retout_site(self, node: CodeNode):
691
680
  """
692
681
  Add a custom retout site.
693
682
 
@@ -703,7 +692,7 @@ class Function(Serializable):
703
692
  :return: None
704
693
  """
705
694
 
706
- self._register_nodes(True, node)
695
+ node = self._register_node(True, node)
707
696
  self._retout_sites.add(node)
708
697
  self._add_endpoint(node, "return")
709
698
 
@@ -785,7 +774,6 @@ class Function(Serializable):
785
774
  return None
786
775
 
787
776
  def _clear_transition_graph(self):
788
- self._block_cache = {}
789
777
  self._block_sizes = {}
790
778
  self._addr_to_block_node = {}
791
779
  self._local_blocks = {}
@@ -812,11 +800,13 @@ class Function(Serializable):
812
800
 
813
801
  # it's confirmed. register the node if needed
814
802
  if "outside" not in data or data["outside"] is False:
815
- self._register_nodes(True, dst)
803
+ dst = self._register_node(True, dst)
816
804
 
817
805
  self.transition_graph[src][dst]["confirmed"] = True
818
806
 
819
- def _transit_to(self, from_node, to_node, outside=False, ins_addr=None, stmt_idx=None, is_exception=False):
807
+ def _transit_to(
808
+ self, from_node: CodeNode, to_node, outside=False, ins_addr=None, stmt_idx=None, is_exception=False
809
+ ):
820
810
  """
821
811
  Registers an edge between basic blocks in this function's transition graph.
822
812
  Arguments are CodeNode objects.
@@ -830,16 +820,15 @@ class Function(Serializable):
830
820
  """
831
821
 
832
822
  if outside:
833
- self._register_nodes(True, from_node)
823
+ from_node = self._register_node(True, from_node)
834
824
  if to_node is not None:
835
- self._register_nodes(False, to_node)
825
+ to_node = self._register_node(False, to_node)
836
826
 
837
827
  self._jumpout_sites.add(from_node)
838
828
  else:
829
+ from_node = self._register_node(True, from_node)
839
830
  if to_node is not None:
840
- self._register_nodes(True, from_node, to_node)
841
- else:
842
- self._register_nodes(True, from_node)
831
+ to_node = self._register_node(True, to_node)
843
832
 
844
833
  type_ = "transition" if not is_exception else "exception"
845
834
  if to_node is not None:
@@ -871,19 +860,22 @@ class Function(Serializable):
871
860
  :type ins_addr: int or None
872
861
  """
873
862
 
874
- self._register_nodes(True, from_node)
863
+ from_node = self._register_node(True, from_node)
875
864
 
876
865
  if to_func.is_syscall:
877
866
  self.transition_graph.add_edge(from_node, to_func, type="syscall", stmt_idx=stmt_idx, ins_addr=ins_addr)
878
867
  else:
879
868
  self.transition_graph.add_edge(from_node, to_func, type="call", stmt_idx=stmt_idx, ins_addr=ins_addr)
880
869
  if ret_node is not None:
870
+ ret_node = self._register_node(return_to_outside is False, ret_node)
881
871
  self._fakeret_to(from_node, ret_node, to_outside=return_to_outside)
882
872
 
883
873
  self._local_transition_graph = None
884
874
 
885
875
  def _fakeret_to(self, from_node, to_node, confirmed=None, to_outside=False):
886
- self._register_nodes(True, from_node)
876
+ from_node = self._register_node(True, from_node)
877
+ if confirmed:
878
+ to_node = self._register_node(not to_outside, to_node)
887
879
 
888
880
  if confirmed is None:
889
881
  self.transition_graph.add_edge(from_node, to_node, type="fake_return", outside=to_outside)
@@ -891,8 +883,6 @@ class Function(Serializable):
891
883
  self.transition_graph.add_edge(
892
884
  from_node, to_node, type="fake_return", confirmed=confirmed, outside=to_outside
893
885
  )
894
- if confirmed:
895
- self._register_nodes(not to_outside, to_node)
896
886
 
897
887
  self._local_transition_graph = None
898
888
 
@@ -910,45 +900,56 @@ class Function(Serializable):
910
900
  self._local_transition_graph = None
911
901
 
912
902
  def _update_local_blocks(self, node: CodeNode):
913
- self._local_blocks[node.addr] = node
914
- self._local_block_addrs.add(node.addr)
903
+ if node.addr not in self._local_blocks or self._local_blocks[node.addr] != node:
904
+ self._local_blocks[node.addr] = node
905
+ self._local_block_addrs.add(node.addr)
915
906
 
916
907
  def _update_addr_to_block_cache(self, node: BlockNode):
917
908
  if node.addr not in self._addr_to_block_node:
918
909
  self._addr_to_block_node[node.addr] = node
919
910
 
920
- def _register_nodes(self, is_local, *nodes):
921
- if not isinstance(is_local, bool):
922
- raise AngrValueError('_register_nodes(): the "is_local" parameter must be a bool')
923
-
924
- for node in nodes:
925
- if node.addr not in self:
926
- # only add each node once
927
- self.transition_graph.add_node(node)
928
-
929
- if not isinstance(node, CodeNode):
930
- continue
931
- node._graph = self.transition_graph
932
- if self._block_sizes.get(node.addr, 0) == 0:
933
- self._block_sizes[node.addr] = node.size
934
- if node.addr == self.addr and (self.startpoint is None or not self.startpoint.is_hook):
935
- self.startpoint = node
936
- if is_local and node.addr not in self._local_blocks:
937
- self._update_local_blocks(node)
938
- # add BlockNodes to the addr_to_block_node cache if not already there
939
- if isinstance(node, BlockNode):
940
- self._update_addr_to_block_cache(node)
941
- # else:
942
- # # checks that we don't have multiple block nodes at a single address
943
- # assert node == self._addr_to_block_node[node.addr]
944
-
945
- def _add_return_site(self, return_site):
911
+ @overload
912
+ def _register_node(self, is_local: bool, node: CodeNode) -> CodeNode: ...
913
+
914
+ @overload
915
+ def _register_node(self, is_local: bool, node: Function) -> Function: ...
916
+
917
+ def _register_node(self, is_local: bool, node: CodeNode | Function) -> CodeNode | Function:
918
+ # if the node already exists and is the same, we reuse the existing node
919
+ if is_local and self._local_blocks.get(node.addr, None) == node:
920
+ return self._local_blocks[node.addr]
921
+
922
+ if node.addr not in self and node not in self.transition_graph:
923
+ # only add each node to the graph once
924
+ self.transition_graph.add_node(node)
925
+
926
+ if not isinstance(node, CodeNode):
927
+ # function and other things bail here
928
+ return node
929
+
930
+ # this is either a new node or a different node at the same address
931
+ node._graph = self.transition_graph
932
+ if self._block_sizes.get(node.addr, 0) == 0:
933
+ self._block_sizes[node.addr] = node.size
934
+ if node.addr == self.addr and (self.startpoint is None or not self.startpoint.is_hook):
935
+ self.startpoint = node
936
+ if is_local and node.addr not in self._local_blocks:
937
+ self._update_local_blocks(node)
938
+ # add BlockNodes to the addr_to_block_node cache if not already there
939
+ if isinstance(node, BlockNode):
940
+ self._update_addr_to_block_cache(node)
941
+ # else:
942
+ # # checks that we don't have multiple block nodes at a single address
943
+ # assert node == self._addr_to_block_node[node.addr]
944
+ return node
945
+
946
+ def _add_return_site(self, return_site: CodeNode):
946
947
  """
947
948
  Registers a basic block as a site for control flow to return from this function.
948
949
 
949
- :param CodeNode return_site: The block node that ends with a return.
950
+ :param return_site: The block node that ends with a return.
950
951
  """
951
- self._register_nodes(True, return_site)
952
+ return_site = self._register_node(True, return_site)
952
953
 
953
954
  self._ret_sites.add(return_site)
954
955
  # A return site must be an endpoint of the function - you cannot continue execution of the current function
@@ -1285,8 +1286,8 @@ class Function(Serializable):
1285
1286
  """
1286
1287
  Draw the graph and save it to a PNG file.
1287
1288
  """
1288
- import matplotlib.pyplot as pyplot # pylint: disable=import-error
1289
- from networkx.drawing.nx_agraph import graphviz_layout # pylint: disable=import-error
1289
+ import matplotlib.pyplot as pyplot # pylint: disable=import-error,import-outside-toplevel
1290
+ from networkx.drawing.nx_agraph import graphviz_layout # pylint: disable=import-error,import-outside-toplevel
1290
1291
 
1291
1292
  tmp_graph = networkx.classes.digraph.DiGraph()
1292
1293
  for from_block, to_block in self.transition_graph.edges():
@@ -1416,11 +1417,8 @@ class Function(Serializable):
1416
1417
  self._local_blocks[n.addr] = new_node
1417
1418
 
1418
1419
  # update block_cache and block_sizes
1419
- if (n.addr in self._block_cache and self._block_cache[n.addr].size != new_node.size) or (
1420
- n.addr in self._block_sizes and self._block_sizes[n.addr] != new_node.size
1421
- ):
1420
+ if n.addr in self._block_sizes and self._block_sizes[n.addr] != new_node.size:
1422
1421
  # the cache needs updating
1423
- self._block_cache.pop(n.addr, None)
1424
1422
  self._block_sizes[n.addr] = new_node.size
1425
1423
 
1426
1424
  for p, _, data in original_predecessors:
@@ -1680,7 +1678,6 @@ class Function(Serializable):
1680
1678
  func.startpoint = self.startpoint
1681
1679
  func._addr_to_block_node = self._addr_to_block_node.copy()
1682
1680
  func._block_sizes = self._block_sizes.copy()
1683
- func._block_cache = self._block_cache.copy()
1684
1681
  func._local_blocks = self._local_blocks.copy()
1685
1682
  func._local_block_addrs = self._local_block_addrs.copy()
1686
1683
  func.info = self.info.copy()
@@ -6,6 +6,7 @@ from collections.abc import Generator
6
6
  import logging
7
7
  import collections.abc
8
8
  import re
9
+ import weakref
9
10
  from sortedcontainers import SortedDict
10
11
 
11
12
  import networkx
@@ -31,7 +32,7 @@ class FunctionDict(SortedDict):
31
32
  """
32
33
 
33
34
  def __init__(self, backref, *args, **kwargs):
34
- self._backref = backref
35
+ self._backref = weakref.proxy(backref) if backref is not None else None
35
36
  self._key_types = kwargs.pop("key_types", int)
36
37
  super().__init__(*args, **kwargs)
37
38
 
@@ -39,7 +40,7 @@ class FunctionDict(SortedDict):
39
40
  try:
40
41
  return super().__getitem__(addr)
41
42
  except KeyError as ex:
42
- if not isinstance(addr, self._key_types):
43
+ if isinstance(addr, bool) or not isinstance(addr, self._key_types):
43
44
  raise TypeError(f"FunctionDict only supports {self._key_types} as key type") from ex
44
45
 
45
46
  if isinstance(addr, SootMethodDescriptor):
@@ -148,7 +149,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
148
149
  dst_func = self._function_map[function_addr]
149
150
  if syscall in (True, False):
150
151
  dst_func.is_syscall = syscall
151
- dst_func._register_nodes(True, node)
152
+ dst_func._register_node(True, node)
152
153
  self.block_map[node.addr] = node
153
154
 
154
155
  def _add_call_to(
@@ -160,7 +161,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
160
161
  syscall=None,
161
162
  stmt_idx=None,
162
163
  ins_addr=None,
163
- return_to_outside=False,
164
+ return_to_outside: bool = False,
164
165
  ):
165
166
  """
166
167
  Add a call to a function.
@@ -172,7 +173,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
172
173
  :param bool syscall: If this is a call to a syscall or not.
173
174
  :param int stmt_idx: ID of the statement where this call happens.
174
175
  :param int ins_addr: Address of the instruction where this call happens.
175
- :param bool return_to_outside: True if the return of the call is considered going to outside of the current
176
+ :param return_to_outside: True if the return of the call is considered going to outside of the current
176
177
  function.
177
178
  :return: None
178
179
  """
@@ -306,7 +307,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
306
307
  try:
307
308
  _ = self[item]
308
309
  return True
309
- except KeyError:
310
+ except (KeyError, TypeError):
310
311
  return False
311
312
 
312
313
  def __getitem__(self, k) -> Function:
@@ -406,7 +407,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
406
407
 
407
408
  try:
408
409
  prev_addr = self._function_map.floor_addr(addr)
409
- return self._function_map[prev_addr]
410
+ return self._function_map.get(prev_addr)
410
411
 
411
412
  except KeyError:
412
413
  return None
@@ -246,7 +246,7 @@ class FunctionParser:
246
246
  # add leftover blocks
247
247
  for block in blocks.values():
248
248
  if block not in added_nodes:
249
- obj._register_nodes(True, block)
249
+ obj._register_node(True, block)
250
250
 
251
251
  return obj
252
252
 
@@ -108,24 +108,24 @@ class SootFunction(Function):
108
108
  # The Shimple CFG is already normalized.
109
109
  pass
110
110
 
111
- def _register_nodes(self, is_local, *nodes):
112
- if not isinstance(is_local, bool):
113
- raise AngrValueError('_register_nodes(): the "is_local" parameter must be a bool')
111
+ def _register_node(self, is_local: bool, node):
112
+ if is_local and self._local_blocks.get(node.addr) == node:
113
+ return self._local_blocks[node.addr]
114
114
 
115
- for node in nodes:
115
+ if node not in self.transition_graph:
116
116
  self.transition_graph.add_node(node)
117
- node._graph = self.transition_graph
118
- if node.addr not in self or self._block_sizes[node.addr] == 0:
119
- self._block_sizes[node.addr] = node.size
120
- if node.addr == self.addr.addr and (self.startpoint is None or not self.startpoint.is_hook):
121
- self.startpoint = node
122
- if is_local:
123
- self._local_blocks[node.addr] = node
124
- self._local_block_addrs.add(node.addr)
125
- # add BlockNodes to the addr_to_block_node cache if not already there
126
- if isinstance(node, BlockNode) and node.addr not in self._addr_to_block_node:
127
- self._addr_to_block_node[node.addr] = node
117
+ node._graph = self.transition_graph
118
+ if node.addr not in self or self._block_sizes[node.addr] == 0:
119
+ self._block_sizes[node.addr] = node.size
120
+ if node.addr == self.addr.addr and (self.startpoint is None or not self.startpoint.is_hook):
121
+ self.startpoint = node
122
+ if is_local:
123
+ self._local_blocks[node.addr] = node
124
+ self._local_block_addrs.add(node.addr)
125
+ # add BlockNodes to the addr_to_block_node cache if not already there
126
+ if isinstance(node, BlockNode) and node.addr not in self._addr_to_block_node:
127
+ self._addr_to_block_node[node.addr] = node
128
+ return node
128
129
 
129
130
 
130
131
  from angr.codenode import BlockNode
131
- from angr.errors import AngrValueError
@@ -6,7 +6,7 @@ import claripy
6
6
  import ailment
7
7
  from angr.serializable import Serializable
8
8
  from angr.knowledge_plugins.functions.function import Function
9
- from .states import PropagatorVEXState, PropagatorAILState, PropagatorState
9
+ from .states import PropagatorVEXState, PropagatorState
10
10
 
11
11
 
12
12
  class PropagationModel(Serializable):
@@ -65,10 +65,9 @@ class PropagationModel(Serializable):
65
65
  preds = [self.states[pnode.addr] for pnode in self._function.graph.predecessors(node)]
66
66
  if not preds:
67
67
  if isinstance(node, ailment.Block):
68
- state = PropagatorAILState.initial_state(self._function.project, func_addr=self._function.addr)
69
- else:
70
- state = PropagatorVEXState.initial_state(self._function.project, func_addr=self._function.addr)
71
- state.store_register(state.arch.ip_offset, state.arch.bytes, claripy.BVV(block_addr, state.arch.bits))
68
+ raise NotImplementedError
69
+ state = PropagatorVEXState.initial_state(self._function.project, func_addr=self._function.addr)
70
+ state.store_register(state.arch.ip_offset, state.arch.bytes, claripy.BVV(block_addr, state.arch.bits))
72
71
  else:
73
72
  state, _ = preds[0].merge(*preds[1:])
74
73
  return state