angr 9.2.61__py3-none-manylinux2014_x86_64.whl → 9.2.63__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 (37) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/cfg/cfg_fast.py +18 -20
  3. angr/analyses/decompiler/ail_simplifier.py +15 -30
  4. angr/analyses/decompiler/block_simplifier.py +11 -7
  5. angr/analyses/decompiler/clinic.py +144 -0
  6. angr/analyses/decompiler/condition_processor.py +4 -2
  7. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +2 -0
  8. angr/analyses/decompiler/structured_codegen/c.py +20 -16
  9. angr/analyses/decompiler/structuring/phoenix.py +6 -10
  10. angr/analyses/disassembly.py +7 -11
  11. angr/analyses/propagator/engine_ail.py +14 -42
  12. angr/analyses/propagator/outdated_definition_walker.py +17 -53
  13. angr/analyses/propagator/propagator.py +1 -0
  14. angr/analyses/reaching_definitions/engine_ail.py +20 -9
  15. angr/analyses/reaching_definitions/engine_vex.py +20 -5
  16. angr/analyses/reaching_definitions/function_handler.py +9 -3
  17. angr/analyses/reaching_definitions/rd_state.py +34 -13
  18. angr/analyses/reaching_definitions/reaching_definitions.py +92 -16
  19. angr/analyses/variable_recovery/engine_vex.py +20 -0
  20. angr/analyses/variable_recovery/variable_recovery_fast.py +5 -0
  21. angr/calling_conventions.py +28 -0
  22. angr/knowledge_plugins/key_definitions/live_definitions.py +15 -5
  23. angr/knowledge_plugins/key_definitions/liveness.py +94 -0
  24. angr/knowledge_plugins/key_definitions/rd_model.py +90 -9
  25. angr/knowledge_plugins/propagations/states.py +3 -0
  26. angr/knowledge_plugins/variables/variable_manager.py +26 -4
  27. angr/lib/angr_native.so +0 -0
  28. angr/project.py +2 -2
  29. angr/sim_type.py +2 -2
  30. angr/state_plugins/unicorn_engine.py +9 -1
  31. angr/storage/memory_mixins/multi_value_merger_mixin.py +7 -2
  32. angr/utils/timing.py +12 -5
  33. {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/METADATA +15 -15
  34. {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/RECORD +37 -36
  35. {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/WHEEL +1 -1
  36. {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/LICENSE +0 -0
  37. {angr-9.2.61.dist-info → angr-9.2.63.dist-info}/top_level.txt +0 -0
@@ -158,6 +158,12 @@ def refine_locs_with_struct_type(
158
158
  for field, field_ty in arg_type.fields.items()
159
159
  }
160
160
  return SimStructArg(arg_type, locs)
161
+ if isinstance(arg_type, SimUnion):
162
+ # Treat a SimUnion as functionality equivalent to its longest member
163
+ for member in arg_type.members.values():
164
+ if member.size == arg_type.size:
165
+ return refine_locs_with_struct_type(arch, locs, member, offset)
166
+
161
167
  raise TypeError("I don't know how to lay out a %s" % arg_type)
162
168
 
163
169
 
@@ -1813,6 +1819,24 @@ class SimCCAArch64LinuxSyscall(SimCCSyscall):
1813
1819
  return state.regs.x8
1814
1820
 
1815
1821
 
1822
+ class SimCCRISCV64LinuxSyscall(SimCCSyscall):
1823
+ # TODO: Make sure all the information is correct
1824
+ ARG_REGS = ["a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7"]
1825
+ FP_ARG_REGS = [] # TODO: ???
1826
+ RETURN_VAL = SimRegArg("a0", 8)
1827
+ RETURN_ADDR = SimRegArg("ip_at_syscall", 4)
1828
+ ARCH = archinfo.ArchRISCV64
1829
+
1830
+ @classmethod
1831
+ def _match(cls, arch, args, sp_delta): # pylint: disable=unused-argument
1832
+ # never appears anywhere except syscalls
1833
+ return False
1834
+
1835
+ @staticmethod
1836
+ def syscall_num(state):
1837
+ return state.regs.a0
1838
+
1839
+
1816
1840
  class SimCCO32(SimCC):
1817
1841
  ARG_REGS = ["a0", "a1", "a2", "a3"]
1818
1842
  FP_ARG_REGS = [
@@ -2292,6 +2316,10 @@ SYSCALL_CC: Dict[str, Dict[str, Type[SimCCSyscall]]] = {
2292
2316
  "default": SimCCS390XLinuxSyscall,
2293
2317
  "Linux": SimCCS390XLinuxSyscall,
2294
2318
  },
2319
+ "RISCV64": {
2320
+ "default": SimCCRISCV64LinuxSyscall,
2321
+ "Linux": SimCCRISCV64LinuxSyscall,
2322
+ },
2295
2323
  }
2296
2324
 
2297
2325
 
@@ -196,7 +196,7 @@ class LiveDefinitions:
196
196
  ctnt += ", %d tmpdefs" % len(self.tmps)
197
197
  return "<%s>" % ctnt
198
198
 
199
- def copy(self) -> "LiveDefinitions":
199
+ def copy(self, discard_tmpdefs=False) -> "LiveDefinitions":
200
200
  rd = LiveDefinitions(
201
201
  self.arch,
202
202
  track_tmps=self.track_tmps,
@@ -205,12 +205,12 @@ class LiveDefinitions:
205
205
  stack_definitions=self.stack_definitions.copy(),
206
206
  heap_definitions=self.heap_definitions.copy(),
207
207
  memory_definitions=self.memory_definitions.copy(),
208
- tmps=self.tmps.copy(),
208
+ tmps=self.tmps.copy() if not discard_tmpdefs else None,
209
209
  register_uses=self.register_uses.copy(),
210
210
  stack_uses=self.stack_uses.copy(),
211
211
  heap_uses=self.heap_uses.copy(),
212
212
  memory_uses=self.memory_uses.copy(),
213
- tmp_uses=self.tmp_uses.copy(),
213
+ tmp_uses=self.tmp_uses.copy() if not discard_tmpdefs else None,
214
214
  )
215
215
 
216
216
  return rd
@@ -495,6 +495,9 @@ class LiveDefinitions:
495
495
  except SimMemoryError:
496
496
  l.warning("Failed to store register definition %s at %d.", d, atom.reg_offset, exc_info=True)
497
497
  elif isinstance(atom, MemoryLocation):
498
+ if endness is None:
499
+ endness = atom.endness
500
+
498
501
  if isinstance(atom.addr, SpOffset):
499
502
  if atom.addr.offset is not None:
500
503
  stack_addr = self.stack_offset_to_stack_addr(atom.addr.offset)
@@ -600,8 +603,15 @@ class LiveDefinitions:
600
603
  size=size,
601
604
  endness=endness,
602
605
  )
603
- except SimMemoryMissingError:
604
- return
606
+ except SimMemoryMissingError as ex:
607
+ # load values and stop at the missing location
608
+ if ex.missing_addr > reg_offset:
609
+ values: MultiValues = self.register_definitions.load(
610
+ reg_offset, size=ex.missing_addr - reg_offset, endness=endness
611
+ )
612
+ else:
613
+ # nothing we can do
614
+ return
605
615
  yield from LiveDefinitions.extract_defs_from_mv(values)
606
616
 
607
617
  def get_stack_values(self, stack_offset: int, size: int, endness: str) -> Optional[MultiValues]:
@@ -0,0 +1,94 @@
1
+ from typing import DefaultDict, Optional, List, Set, Tuple, TYPE_CHECKING
2
+
3
+ from collections import defaultdict
4
+
5
+ from .constants import ObservationPointType, OP_BEFORE, OP_AFTER
6
+
7
+ if TYPE_CHECKING:
8
+ from .definition import Definition
9
+ from angr.code_location import CodeLocation
10
+
11
+
12
+ LocationType = Tuple[int, Optional[int], Optional[int]] # block addr, block ID, stmt ID
13
+ LocationWithPosType = Tuple[
14
+ int, Optional[int], Optional[int], ObservationPointType
15
+ ] # block addr, block ID, stmt ID, before/after
16
+
17
+
18
+ class Liveness:
19
+ """
20
+ This class stores liveness information for each definition.
21
+ """
22
+
23
+ def __init__(self):
24
+ self.curr_live_defs: Set["Definition"] = set()
25
+ self.curr_loc: Optional[LocationType] = None
26
+ self.def_to_liveness: DefaultDict["Definition", Set[LocationType]] = defaultdict(set)
27
+ self.loc_to_defs: DefaultDict[LocationWithPosType, Set["Definition"]] = defaultdict(set)
28
+ self._node_max_stmt_id: DefaultDict[Tuple[int, Optional[int]], int] = defaultdict(int)
29
+
30
+ def add_def(self, d: "Definition", code_loc: "CodeLocation") -> None:
31
+ loc = (code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx)
32
+ self.curr_live_defs.add(d)
33
+ self.def_to_liveness[d].add(loc)
34
+
35
+ def kill_def(self, d: "Definition") -> None:
36
+ self.curr_live_defs.discard(d)
37
+
38
+ def complete_loc(self) -> None:
39
+ if self.curr_loc is not None:
40
+ for live_def in self.curr_live_defs:
41
+ self.def_to_liveness[live_def].add(self.curr_loc)
42
+ self.loc_to_defs[self.curr_loc + (OP_AFTER,)] |= self.curr_live_defs
43
+
44
+ def at_new_stmt(self, code_loc: "CodeLocation") -> None:
45
+ """
46
+ Only support moving from a statement to the next statement within one basic block.
47
+ """
48
+ self.complete_loc()
49
+ self.curr_loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx
50
+ if (
51
+ code_loc.stmt_idx is not None
52
+ and code_loc.stmt_idx > self._node_max_stmt_id[(code_loc.block_addr, code_loc.block_idx)]
53
+ ):
54
+ self._node_max_stmt_id[(code_loc.block_addr, code_loc.block_idx)] = code_loc.stmt_idx
55
+
56
+ def at_new_block(self, code_loc: "CodeLocation", pred_codelocs: List["CodeLocation"]) -> None:
57
+ """
58
+ Only support moving to a new block from one or more blocks.
59
+ """
60
+ loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx
61
+ key = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx, OP_BEFORE
62
+ for pred_codeloc in pred_codelocs:
63
+ if pred_codeloc.stmt_idx is None:
64
+ # external code location
65
+ pred_max_stmt_id = None
66
+ else:
67
+ pred_max_stmt_id = self._node_max_stmt_id[(pred_codeloc.block_addr, pred_codeloc.block_idx)]
68
+ pred_key = pred_codeloc.block_addr, pred_codeloc.block_idx, pred_max_stmt_id, OP_AFTER
69
+ pred_defs = self.loc_to_defs[pred_key]
70
+ for pred_def in pred_defs:
71
+ self.def_to_liveness[pred_def].add(loc)
72
+ self.loc_to_defs[key] |= pred_defs
73
+
74
+ self.curr_live_defs = set(self.loc_to_defs[key])
75
+ self.curr_loc = loc
76
+
77
+ def find_defs_at(self, code_loc: "CodeLocation", op: int = OP_BEFORE) -> Set["Definition"]:
78
+ if op == OP_BEFORE:
79
+ if code_loc.stmt_idx != 0:
80
+ loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx - 1, OP_AFTER
81
+ else:
82
+ loc = code_loc.block_addr, code_loc.block_idx, 0, OP_BEFORE
83
+ else:
84
+ loc = code_loc.block_addr, code_loc.block_idx, code_loc.stmt_idx, OP_AFTER
85
+ return set() if loc not in self.loc_to_defs else self.loc_to_defs[loc]
86
+
87
+ def copy(self) -> "Liveness":
88
+ o = Liveness()
89
+ o.curr_live_defs = self.curr_live_defs.copy()
90
+ o.curr_loc = self.curr_loc
91
+ o.def_to_liveness = self.def_to_liveness.copy()
92
+ o.loc_to_defs = self.loc_to_defs.copy()
93
+ o._node_max_stmt_id = self._node_max_stmt_id.copy()
94
+ return o
@@ -1,13 +1,14 @@
1
- from typing import Dict, Tuple, Set, Union, Optional, TYPE_CHECKING, overload
2
-
3
- from angr.knowledge_plugins.key_definitions.constants import ObservationPointType
4
- from angr.code_location import CodeLocation
1
+ from typing import Dict, List, Tuple, Set, Union, Optional, TYPE_CHECKING, overload
5
2
 
3
+ from .atoms import Atom, Register, MemoryLocation, SpOffset
6
4
  from .uses import Uses
7
5
  from .live_definitions import LiveDefinitions
6
+ from .liveness import Liveness
7
+ from .constants import OP_BEFORE, ObservationPointType
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from angr.knowledge_plugins.key_definitions.definition import Definition
11
+ from angr.code_location import CodeLocation
11
12
 
12
13
 
13
14
  # TODO: Make ReachingDefinitionsModel serializable
@@ -23,6 +24,7 @@ class ReachingDefinitionsModel:
23
24
  ] = {}
24
25
  self.all_definitions: Set["Definition"] = set()
25
26
  self.all_uses = Uses()
27
+ self.liveness = Liveness()
26
28
 
27
29
  def __repr__(self):
28
30
  return "<RDModel{} with {} observations>".format(
@@ -30,11 +32,70 @@ class ReachingDefinitionsModel:
30
32
  len(self.observed_results),
31
33
  )
32
34
 
35
+ def add_def(self, d: "Definition", codeloc: "CodeLocation") -> None:
36
+ self.liveness.add_def(d, codeloc)
37
+
38
+ def kill_def(self, d: "Definition") -> None:
39
+ self.liveness.kill_def(d)
40
+
41
+ def at_new_stmt(self, codeloc: "CodeLocation") -> None:
42
+ self.liveness.at_new_stmt(codeloc)
43
+
44
+ def at_new_block(self, code_loc: "CodeLocation", pred_codelocs: List["CodeLocation"]) -> None:
45
+ self.liveness.at_new_block(code_loc, pred_codelocs)
46
+
47
+ def complete_loc(self) -> None:
48
+ self.liveness.complete_loc()
49
+
50
+ def find_defs_at(self, code_loc: "CodeLocation", op: int = OP_BEFORE) -> Set["Definition"]:
51
+ return self.liveness.find_defs_at(code_loc, op=op)
52
+
53
+ def get_defs(self, atom: Atom, code_loc: "CodeLocation", op: int) -> Set["Definition"]:
54
+ all_defs = self.liveness.find_defs_at(code_loc, op=op)
55
+ defs = None
56
+ if isinstance(atom, Register):
57
+ defs = {
58
+ d
59
+ for d in all_defs
60
+ if isinstance(d.atom, Register)
61
+ and d.atom.reg_offset <= atom.reg_offset < d.atom.reg_offset + d.atom.size
62
+ }
63
+ elif isinstance(atom, MemoryLocation):
64
+ if isinstance(atom.addr, int):
65
+ defs = {
66
+ d
67
+ for d in all_defs
68
+ if isinstance(d.atom, MemoryLocation)
69
+ and isinstance(d.atom.addr, int)
70
+ and (
71
+ d.atom.addr <= atom.addr < d.atom.addr + d.size
72
+ or atom.addr <= d.atom.addr < atom.addr + atom.size
73
+ )
74
+ }
75
+ elif isinstance(atom.addr, SpOffset):
76
+ defs = {
77
+ d
78
+ for d in all_defs
79
+ if isinstance(d.atom, MemoryLocation)
80
+ and isinstance(d.atom.addr, SpOffset)
81
+ and (
82
+ d.atom.addr.offset <= atom.addr.offset < d.atom.addr.offset + d.size
83
+ or atom.addr.offset <= d.atom.addr.offset < atom.addr.offset + atom.size
84
+ )
85
+ }
86
+
87
+ if defs is None:
88
+ # unsupported for now
89
+ defs = set()
90
+
91
+ return defs
92
+
33
93
  def copy(self) -> "ReachingDefinitionsModel":
34
94
  new = ReachingDefinitionsModel(self.func_addr)
35
95
  new.observed_results = self.observed_results.copy()
36
96
  new.all_definitions = self.all_definitions.copy()
37
97
  new.all_uses = self.all_uses.copy()
98
+ new.liveness = self.liveness.copy()
38
99
  return new
39
100
 
40
101
  def merge(self, model: "ReachingDefinitionsModel"):
@@ -47,9 +108,10 @@ class ReachingDefinitionsModel:
47
108
  self.observed_results[k] = merged
48
109
  self.all_definitions.union(model.all_definitions)
49
110
  self.all_uses.merge(model.all_uses)
111
+ # TODO: Merge self.liveness
50
112
 
51
113
  def get_observation_by_insn(
52
- self, ins_addr: Union[int, CodeLocation], kind: ObservationPointType
114
+ self, ins_addr: Union[int, "CodeLocation"], kind: ObservationPointType
53
115
  ) -> Optional[LiveDefinitions]:
54
116
  if isinstance(ins_addr, int):
55
117
  return self.observed_results.get(("insn", ins_addr, kind), None)
@@ -58,15 +120,21 @@ class ReachingDefinitionsModel:
58
120
  return self.observed_results.get(("insn", ins_addr.ins_addr, kind))
59
121
 
60
122
  def get_observation_by_node(
61
- self, node_addr: Union[int, CodeLocation], kind: ObservationPointType
123
+ self, node_addr: Union[int, "CodeLocation"], kind: ObservationPointType, node_idx: Optional[int] = None
62
124
  ) -> Optional[LiveDefinitions]:
63
125
  if isinstance(node_addr, int):
64
- return self.observed_results.get(("node", node_addr, kind), None)
126
+ key = ("node", node_addr, kind) if node_idx is None else ("node", (node_addr, node_idx), kind)
127
+ return self.observed_results.get(key, None)
65
128
  else:
66
- return self.observed_results.get(("node", node_addr.block_addr, kind))
129
+ key = (
130
+ ("node", node_addr.block_addr, kind)
131
+ if node_idx is None
132
+ else ("node", (node_addr.block_addr, node_idx), kind)
133
+ )
134
+ return self.observed_results.get(key, None)
67
135
 
68
136
  @overload
69
- def get_observation_by_stmt(self, codeloc: CodeLocation, kind: ObservationPointType) -> Optional[LiveDefinitions]:
137
+ def get_observation_by_stmt(self, codeloc: "CodeLocation", kind: ObservationPointType) -> Optional[LiveDefinitions]:
70
138
  ...
71
139
 
72
140
  @overload
@@ -88,3 +156,16 @@ class ReachingDefinitionsModel:
88
156
  return self.observed_results.get(("stmt", (arg1.block_addr, arg1.stmt_idx), arg2), None)
89
157
  else:
90
158
  return self.observed_results.get(("stmt", (arg1.block_addr, arg1.stmt_idx, block_idx), arg2), None)
159
+
160
+ def get_observation_by_exit(
161
+ self,
162
+ node_addr: int,
163
+ stmt_idx: int,
164
+ src_node_idx: Optional[int] = None,
165
+ ) -> Optional[LiveDefinitions]:
166
+ key = (
167
+ ("exit", (node_addr, stmt_idx), ObservationPointType.OP_AFTER)
168
+ if src_node_idx is None
169
+ else ("exit", (node_addr, src_node_idx, stmt_idx), ObservationPointType.OP_AFTER)
170
+ )
171
+ return self.observed_results.get(key, None)
@@ -235,6 +235,9 @@ class PropagatorState:
235
235
 
236
236
  return state, merge_occurred
237
237
 
238
+ def init_replacements(self):
239
+ self._replacements = defaultdict(dict)
240
+
238
241
  def add_replacement(self, codeloc, old: CodeLocation, new):
239
242
  """
240
243
  Add a replacement record: Replacing expression `old` with `new` at program location `codeloc`.
@@ -1,4 +1,4 @@
1
- from typing import Set, List, Tuple, Dict, Union, Optional, TYPE_CHECKING
1
+ from typing import Set, List, Tuple, Dict, Union, Optional, Literal, TYPE_CHECKING
2
2
  import logging
3
3
  from collections import defaultdict
4
4
  from itertools import count, chain
@@ -591,14 +591,15 @@ class VariableManagerInternal(Serializable):
591
591
 
592
592
  return accesses
593
593
 
594
- def get_variables(self, sort=None, collapse_same_ident=False) -> List[Union[SimStackVariable, SimRegisterVariable]]:
594
+ def get_variables(
595
+ self, sort: Optional[Literal["stack", "reg"]] = None, collapse_same_ident=False
596
+ ) -> List[Union[SimStackVariable, SimRegisterVariable]]:
595
597
  """
596
598
  Get a list of variables.
597
599
 
598
- :param str or None sort: Sort of the variable to get.
600
+ :param sort: Sort of the variable to get.
599
601
  :param collapse_same_ident: Whether variables of the same identifier should be collapsed or not.
600
602
  :return: A list of variables.
601
- :rtype: list
602
603
  """
603
604
 
604
605
  variables = []
@@ -615,6 +616,27 @@ class VariableManagerInternal(Serializable):
615
616
 
616
617
  return variables
617
618
 
619
+ def get_unified_variables(
620
+ self, sort: Optional[Literal["stack", "reg"]] = None
621
+ ) -> List[Union[SimStackVariable, SimRegisterVariable]]:
622
+ """
623
+ Get a list of unified variables.
624
+
625
+ :param sort: Sort of the variable to get.
626
+ :return: A list of variables.
627
+ """
628
+
629
+ variables = []
630
+
631
+ for var in self._unified_variables:
632
+ if sort == "stack" and not isinstance(var, SimStackVariable):
633
+ continue
634
+ if sort == "reg" and not isinstance(var, SimRegisterVariable):
635
+ continue
636
+ variables.append(var)
637
+
638
+ return variables
639
+
618
640
  def get_global_variables(self, addr):
619
641
  """
620
642
  Get global variable by the address of the variable.
angr/lib/angr_native.so CHANGED
Binary file
angr/project.py CHANGED
@@ -268,8 +268,8 @@ class Project:
268
268
  """
269
269
  Initializes self.analyses using a given preset.
270
270
  """
271
- self.analyses = cast("AnalysesHubWithDefault", AnalysesHub(self))
272
- self.analyses.use_plugin_preset(self._analyses_preset if self._analyses_preset is not None else "default")
271
+ self._analyses = cast("AnalysesHubWithDefault", AnalysesHub(self))
272
+ self._analyses.use_plugin_preset(self._analyses_preset if self._analyses_preset is not None else "default")
273
273
 
274
274
  def _register_object(self, obj, sim_proc_arch):
275
275
  """
angr/sim_type.py CHANGED
@@ -849,7 +849,7 @@ class SimTypeFunction(SimType):
849
849
  _fields = ("args", "returnty")
850
850
  base = False
851
851
 
852
- def __init__(self, args, returnty, label=None, arg_names=None, variadic=False):
852
+ def __init__(self, args: List[SimType], returnty: Optional[SimType], label=None, arg_names=None, variadic=False):
853
853
  """
854
854
  :param label: The type label
855
855
  :param args: A tuple of types representing the arguments to the function
@@ -857,7 +857,7 @@ class SimTypeFunction(SimType):
857
857
  :param variadic: Whether the function accepts varargs
858
858
  """
859
859
  super().__init__(label=label)
860
- self.args = args
860
+ self.args: List[SimType] = args
861
861
  self.returnty: Optional[SimType] = returnty
862
862
  self.arg_names = arg_names if arg_names else ()
863
863
  self.variadic = variadic
@@ -481,6 +481,7 @@ def _load_native():
481
481
  ctypes.c_uint64,
482
482
  ctypes.c_uint32,
483
483
  ctypes.c_uint64,
484
+ ctypes.c_uint64,
484
485
  ctypes.c_uint32,
485
486
  ctypes.c_uint64,
486
487
  )
@@ -1273,7 +1274,14 @@ class Unicorn(SimStatePlugin):
1273
1274
  )
1274
1275
 
1275
1276
  _UC_NATIVE.set_cgc_syscall_details(
1276
- self._uc_state, 2, cgc_transmit_addr, 3, cgc_receive_addr, 7, cgc_random_addr
1277
+ self._uc_state,
1278
+ 2,
1279
+ cgc_transmit_addr,
1280
+ 3,
1281
+ cgc_receive_addr,
1282
+ self.state.cgc.max_receive_size,
1283
+ 7,
1284
+ cgc_random_addr,
1277
1285
  )
1278
1286
 
1279
1287
  # set memory map callback so we can call it explicitly
@@ -21,11 +21,16 @@ class MultiValueMergerMixin(MemoryMixin):
21
21
  # try to merge it in the traditional way
22
22
  if len(values_set) > self._element_limit:
23
23
  # strip annotations from each value and see how many raw values there are in total
24
- stripped_values_set = {v._apply_to_annotations(lambda alist: None) for v in values_set}
24
+ # We have to use cache_key to determine uniqueness here, because if __hash__ collides,
25
+ # python implicitly calls __eq__ to determine if the two objects are actually the same
26
+ # and that just results in a new AST for a BV. Python then tries to convert that AST to a bool
27
+ # which fails with the safeguard in claripy.ast.bool.Bool.__bool__.
28
+ stripped_values_set = {v._apply_to_annotations(lambda alist: None).cache_key for v in values_set}
25
29
  if len(stripped_values_set) > 1:
26
30
  ret_val = self._top_func(merged_size * self.state.arch.byte_width)
27
31
  else:
28
- ret_val = next(iter(stripped_values_set))
32
+ # Get the AST back from the cache_key
33
+ ret_val = next(iter(stripped_values_set)).ast
29
34
  # migrate annotations
30
35
  annotations = []
31
36
  for v in values_set:
angr/utils/timing.py CHANGED
@@ -1,14 +1,16 @@
1
- # pylint:disable=no-member
1
+ # pylint:disable=no-member,global-statement
2
+ import os
2
3
  import time
3
4
  from functools import wraps
4
5
  from collections import defaultdict
5
6
 
6
- TIMING = False
7
- PRINT = False
7
+ TIMING = os.environ.get("TIMING", "").lower() not in {"", "no", "0", "false"}
8
+ PRINT = os.environ.get("PRINT", "").lower() not in {"", "no", "0", "false"}
8
9
  TIME_DISTRIBUTION = False
9
10
 
10
11
  total_time = defaultdict(float)
11
12
  time_distribution = defaultdict(list)
13
+ depth = 0
12
14
 
13
15
 
14
16
  def timethis(func):
@@ -19,18 +21,23 @@ def timethis(func):
19
21
  def _t():
20
22
  return time.perf_counter_ns() / 1000000
21
23
 
24
+ global depth
25
+ depth += 1
26
+
22
27
  start = _t()
23
28
  r = func(*args, **kwargs)
24
29
  millisec = _t() - start
25
30
  sec = millisec / 1000
26
31
  if PRINT:
32
+ indent = " " * ((depth - 1) * 2)
27
33
  if sec > 1.0:
28
- print(f"[timing] {func.__name__} took {sec:f} seconds ({millisec:f} milliseconds).")
34
+ print(f"[timing] {indent}{func.__name__} took {sec:f} seconds ({millisec:f} milliseconds).")
29
35
  else:
30
- print(f"[timing] {func.__name__} took {millisec:f} milliseconds.")
36
+ print(f"[timing] {indent}{func.__name__} took {millisec:f} milliseconds.")
31
37
  total_time[func] += millisec
32
38
  if TIME_DISTRIBUTION:
33
39
  time_distribution[func].append(millisec)
40
+ depth -= 1
34
41
  return r
35
42
  else:
36
43
  return func(*args, **kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: angr
3
- Version: 9.2.61
3
+ Version: 9.2.63
4
4
  Summary: A multi-architecture binary analysis toolkit, with the ability to perform dynamic symbolic execution and various static analyses on binaries
5
5
  Home-page: https://github.com/angr/angr
6
6
  License: BSD-2-Clause
@@ -16,27 +16,27 @@ Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
17
  Requires-Dist: CppHeaderParser
18
18
  Requires-Dist: GitPython
19
- Requires-Dist: ailment (==9.2.61)
20
- Requires-Dist: archinfo (==9.2.61)
19
+ Requires-Dist: ailment ==9.2.63
20
+ Requires-Dist: archinfo ==9.2.63
21
21
  Requires-Dist: cachetools
22
- Requires-Dist: capstone (!=5.0.0rc2,>=3.0.5rc2)
23
- Requires-Dist: cffi (>=1.14.0)
24
- Requires-Dist: claripy (==9.2.61)
25
- Requires-Dist: cle (==9.2.61)
22
+ Requires-Dist: capstone !=5.0.0rc2,>=3.0.5rc2
23
+ Requires-Dist: cffi >=1.14.0
24
+ Requires-Dist: claripy ==9.2.63
25
+ Requires-Dist: cle ==9.2.63
26
26
  Requires-Dist: dpkt
27
27
  Requires-Dist: itanium-demangler
28
28
  Requires-Dist: mulpyplexer
29
29
  Requires-Dist: nampa
30
- Requires-Dist: networkx (!=2.8.1,>=2.0)
31
- Requires-Dist: protobuf (>=3.19.0)
30
+ Requires-Dist: networkx !=2.8.1,>=2.0
31
+ Requires-Dist: protobuf >=3.19.0
32
32
  Requires-Dist: psutil
33
- Requires-Dist: pycparser (>=2.18)
34
- Requires-Dist: pyvex (==9.2.61)
35
- Requires-Dist: rich (>=13.1.0)
33
+ Requires-Dist: pycparser >=2.18
34
+ Requires-Dist: pyvex ==9.2.63
35
+ Requires-Dist: rich >=13.1.0
36
36
  Requires-Dist: rpyc
37
37
  Requires-Dist: sortedcontainers
38
38
  Requires-Dist: sympy
39
- Requires-Dist: unicorn (==2.0.1.post1)
39
+ Requires-Dist: unicorn ==2.0.1.post1
40
40
  Requires-Dist: colorama ; platform_system == "Windows"
41
41
  Provides-Extra: angrdb
42
42
  Requires-Dist: sqlalchemy ; extra == 'angrdb'
@@ -46,10 +46,10 @@ Requires-Dist: myst-parser ; extra == 'docs'
46
46
  Requires-Dist: sphinx ; extra == 'docs'
47
47
  Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
48
48
  Provides-Extra: pcode
49
- Requires-Dist: pypcode (>=1.1) ; extra == 'pcode'
49
+ Requires-Dist: pypcode >=1.1 ; extra == 'pcode'
50
50
  Provides-Extra: testing
51
51
  Requires-Dist: keystone-engine ; extra == 'testing'
52
- Requires-Dist: pypcode (>=1.1) ; extra == 'testing'
52
+ Requires-Dist: pypcode >=1.1 ; extra == 'testing'
53
53
  Requires-Dist: pytest ; extra == 'testing'
54
54
  Requires-Dist: pytest-split ; extra == 'testing'
55
55
  Requires-Dist: pytest-xdist ; extra == 'testing'