angr 9.2.118__py3-none-macosx_11_0_arm64.whl → 9.2.119__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 (77) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/analysis.py +43 -1
  3. angr/analyses/cfg/cfg_fast.py +135 -23
  4. angr/analyses/decompiler/ail_simplifier.py +1 -1
  5. angr/analyses/decompiler/clinic.py +23 -12
  6. angr/analyses/decompiler/condition_processor.py +41 -16
  7. angr/analyses/decompiler/decompiler.py +3 -0
  8. angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +1 -1
  9. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +7 -4
  10. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +6 -2
  11. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +19 -19
  12. angr/analyses/decompiler/structured_codegen/c.py +9 -2
  13. angr/analyses/decompiler/structuring/dream.py +8 -7
  14. angr/analyses/decompiler/structuring/phoenix.py +3 -3
  15. angr/analyses/propagator/engine_ail.py +2 -1
  16. angr/analyses/reaching_definitions/function_handler.py +6 -2
  17. angr/analyses/stack_pointer_tracker.py +29 -11
  18. angr/analyses/typehoon/translator.py +19 -2
  19. angr/analyses/typehoon/typeconsts.py +8 -0
  20. angr/analyses/variable_recovery/engine_vex.py +7 -10
  21. angr/calling_conventions.py +69 -24
  22. angr/concretization_strategies/norepeats.py +3 -3
  23. angr/engines/concrete.py +1 -1
  24. angr/engines/light/engine.py +6 -11
  25. angr/engines/pcode/engine.py +2 -2
  26. angr/engines/soot/engine.py +5 -5
  27. angr/engines/soot/expressions/condition.py +1 -1
  28. angr/engines/soot/statements/goto.py +1 -1
  29. angr/engines/soot/statements/if_.py +1 -1
  30. angr/engines/soot/statements/throw.py +1 -1
  31. angr/engines/successors.py +1 -1
  32. angr/engines/unicorn.py +2 -2
  33. angr/engines/vex/heavy/heavy.py +2 -2
  34. angr/errors.py +4 -0
  35. angr/exploration_techniques/driller_core.py +2 -3
  36. angr/exploration_techniques/suggestions.py +2 -2
  37. angr/knowledge_plugins/cfg/cfg_model.py +2 -1
  38. angr/knowledge_plugins/cfg/memory_data.py +1 -0
  39. angr/lib/angr_native.dylib +0 -0
  40. angr/misc/telemetry.py +54 -0
  41. angr/procedures/java/unconstrained.py +1 -1
  42. angr/procedures/java_jni/__init__.py +21 -13
  43. angr/procedures/java_jni/string_operations.py +1 -1
  44. angr/procedures/java_lang/double.py +1 -1
  45. angr/procedures/java_lang/string.py +1 -1
  46. angr/procedures/java_util/scanner_nextline.py +1 -1
  47. angr/procedures/linux_kernel/vsyscall.py +1 -1
  48. angr/procedures/stubs/Redirect.py +1 -1
  49. angr/procedures/stubs/UserHook.py +1 -1
  50. angr/procedures/stubs/format_parser.py +1 -1
  51. angr/sim_procedure.py +5 -5
  52. angr/sim_state.py +21 -34
  53. angr/sim_type.py +42 -0
  54. angr/simos/javavm.py +7 -12
  55. angr/simos/linux.py +1 -1
  56. angr/simos/simos.py +1 -1
  57. angr/simos/windows.py +1 -1
  58. angr/state_hierarchy.py +1 -1
  59. angr/state_plugins/preconstrainer.py +2 -2
  60. angr/state_plugins/scratch.py +1 -1
  61. angr/state_plugins/solver.py +1 -1
  62. angr/state_plugins/trace_additions.py +8 -8
  63. angr/storage/file.py +12 -12
  64. angr/storage/memory_mixins/actions_mixin.py +1 -1
  65. angr/storage/memory_mixins/convenient_mappings_mixin.py +6 -8
  66. angr/storage/memory_mixins/multi_value_merger_mixin.py +5 -5
  67. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +1 -1
  68. angr/storage/memory_mixins/size_resolution_mixin.py +1 -1
  69. angr/storage/memory_mixins/smart_find_mixin.py +2 -2
  70. angr/storage/memory_object.py +7 -9
  71. angr/utils/timing.py +30 -18
  72. {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/METADATA +8 -6
  73. {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/RECORD +77 -76
  74. {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/LICENSE +0 -0
  75. {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/WHEEL +0 -0
  76. {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/entry_points.txt +0 -0
  77. {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
2
2
  from __future__ import annotations
3
3
  import logging
4
4
  from typing import cast
5
+ from collections.abc import Iterable
5
6
  from collections import defaultdict
6
7
 
7
8
  import claripy
@@ -49,6 +50,7 @@ class AllocHelper:
49
50
  self.base = claripy.BVS("alloc_base", ptrsize)
50
51
  self.ptr = self.base
51
52
  self.stores = {}
53
+ self.store_asts = {}
52
54
 
53
55
  def alloc(self, size):
54
56
  out = self.ptr
@@ -58,7 +60,7 @@ class AllocHelper:
58
60
  def dump(self, val, state, loc=None):
59
61
  if loc is None:
60
62
  loc = self.stack_loc(val, state.arch)
61
- self.stores[self.ptr.cache_key] = (val, loc)
63
+ self.stores[self.ptr] = (val, loc)
62
64
  return self.alloc(self.calc_size(val, state.arch))
63
65
 
64
66
  def translate(self, val, base):
@@ -66,7 +68,7 @@ class AllocHelper:
66
68
  return SimStructValue(
67
69
  val.struct, {field: self.translate(subval, base) for field, subval in val._values.items()}
68
70
  )
69
- if isinstance(val, claripy.Bits):
71
+ if isinstance(val, claripy.ast.Bits):
70
72
  return val.replace(self.base, base)
71
73
  if type(val) is list:
72
74
  return [self.translate(subval, base) for subval in val]
@@ -75,7 +77,7 @@ class AllocHelper:
75
77
  def apply(self, state, base):
76
78
  for ptr, (val, loc) in self.stores.items():
77
79
  translated_val = self.translate(val, base)
78
- translated_ptr = self.translate(ptr.ast, base)
80
+ translated_ptr = self.translate(ptr, base)
79
81
  loc.set_value(state, translated_val, stack_base=translated_ptr)
80
82
 
81
83
  def size(self):
@@ -87,7 +89,7 @@ class AllocHelper:
87
89
  def calc_size(cls, val, arch):
88
90
  if type(val) is SimStructValue:
89
91
  return val.struct.size // arch.byte_width
90
- if isinstance(val, claripy.Bits):
92
+ if isinstance(val, claripy.ast.Bits):
91
93
  return len(val) // arch.byte_width
92
94
  if type(val) is list:
93
95
  # TODO real strides
@@ -98,7 +100,7 @@ class AllocHelper:
98
100
 
99
101
  @classmethod
100
102
  def stack_loc(cls, val, arch, offset=0):
101
- if isinstance(val, claripy.Bits):
103
+ if isinstance(val, claripy.ast.Bits):
102
104
  return SimStackArg(offset, len(val) // arch.byte_width)
103
105
  if type(val) is list:
104
106
  # TODO real strides
@@ -264,7 +266,7 @@ class SimFunctionArgument:
264
266
  def refine(self, size, arch=None, offset=None, is_fp=None):
265
267
  raise NotImplementedError
266
268
 
267
- def get_footprint(self) -> list[SimRegArg | SimStackArg]:
269
+ def get_footprint(self) -> Iterable[SimRegArg | SimStackArg]:
268
270
  """
269
271
  Return a list of SimRegArg and SimStackArgs that are the base components used for this location
270
272
  """
@@ -289,13 +291,18 @@ class SimRegArg(SimFunctionArgument):
289
291
  self.clear_entire_reg = clear_entire_reg
290
292
 
291
293
  def get_footprint(self):
292
- yield self
294
+ return {self}
293
295
 
294
296
  def __repr__(self):
295
297
  return f"<{self.reg_name}>"
296
298
 
297
299
  def __eq__(self, other):
298
- return type(other) is SimRegArg and self.reg_name == other.reg_name and self.reg_offset == other.reg_offset
300
+ return (
301
+ type(other) is SimRegArg
302
+ and self.reg_name == other.reg_name
303
+ and self.reg_offset == other.reg_offset
304
+ and self.size == other.size
305
+ )
299
306
 
300
307
  def __hash__(self):
301
308
  return hash((self.size, self.reg_name, self.reg_offset))
@@ -337,12 +344,12 @@ class SimStackArg(SimFunctionArgument):
337
344
  :ivar bool is_fp: Whether loads from this location should return a floating point bitvector
338
345
  """
339
346
 
340
- def __init__(self, stack_offset, size, is_fp=False):
347
+ def __init__(self, stack_offset: int, size: int, is_fp: bool = False):
341
348
  SimFunctionArgument.__init__(self, size, is_fp)
342
- self.stack_offset = stack_offset
349
+ self.stack_offset: int = stack_offset
343
350
 
344
351
  def get_footprint(self):
345
- yield self
352
+ return {self}
346
353
 
347
354
  def __repr__(self):
348
355
  return f"[{self.stack_offset:#x}]"
@@ -385,8 +392,7 @@ class SimComboArg(SimFunctionArgument):
385
392
  self.locations = locations
386
393
 
387
394
  def get_footprint(self):
388
- for x in self.locations:
389
- yield from x.get_footprint()
395
+ return {y for x in self.locations for y in x.get_footprint()}
390
396
 
391
397
  def __repr__(self):
392
398
  return f"SimComboArg({self.locations!r})"
@@ -423,8 +429,21 @@ class SimStructArg(SimFunctionArgument):
423
429
  self.locs = locs
424
430
 
425
431
  def get_footprint(self):
426
- for x in self.locs.values():
427
- yield from x.get_footprint()
432
+ regs: defaultdict[str, set[SimRegArg]] = defaultdict(set)
433
+ others: set[SimRegArg | SimStackArg] = set()
434
+ for loc in self.locs.values():
435
+ for footloc in loc.get_footprint():
436
+ if isinstance(footloc, SimRegArg):
437
+ regs[footloc.reg_name].add(footloc)
438
+ else:
439
+ others.add(footloc)
440
+
441
+ for reg, locset in regs.items():
442
+ min_offset = min(loc.reg_offset for loc in locset)
443
+ max_offset = max(loc.reg_offset + loc.size for loc in locset)
444
+ others.add(SimRegArg(reg, max_offset - min_offset, min_offset))
445
+
446
+ return others
428
447
 
429
448
  def get_value(self, state, **kwargs):
430
449
  return SimStructValue(
@@ -442,8 +461,7 @@ class SimArrayArg(SimFunctionArgument):
442
461
  self.locs = locs
443
462
 
444
463
  def get_footprint(self):
445
- for x in self.locs:
446
- yield from x.get_footprint()
464
+ return {y for x in self.locs for y in x.get_footprint()}
447
465
 
448
466
  def get_value(self, state, **kwargs):
449
467
  return [getter.get_value(state, **kwargs) for getter in self.locs]
@@ -470,7 +488,7 @@ class SimReferenceArgument(SimFunctionArgument):
470
488
  self.main_loc = main_loc
471
489
 
472
490
  def get_footprint(self):
473
- yield from self.ptr_loc.get_footprint()
491
+ return self.main_loc.get_footprint()
474
492
 
475
493
  def get_value(self, state, **kwargs):
476
494
  ptr_val = self.ptr_loc.get_value(state, **kwargs)
@@ -946,7 +964,7 @@ class SimCC:
946
964
  raise TypeError(f"Type mismatch: expected {ty}, got pointer-wrapper")
947
965
 
948
966
  if arg.buffer:
949
- if isinstance(arg.value, claripy.Bits):
967
+ if isinstance(arg.value, claripy.ast.Bits):
950
968
  real_value = arg.value.chop(state.arch.byte_width)
951
969
  elif type(arg.value) in (bytes, str):
952
970
  real_value = claripy.BVV(arg.value).chop(8)
@@ -1069,15 +1087,21 @@ class SimCC:
1069
1087
  if sp_delta != cls.STACKARG_SP_DIFF:
1070
1088
  return False
1071
1089
 
1090
+ def _arg_ident(a: SimRegArg | SimStackArg) -> int | str:
1091
+ if isinstance(a, SimRegArg):
1092
+ return a.reg_name
1093
+ return a.stack_offset
1094
+
1072
1095
  sample_inst = cls(arch)
1073
- all_fp_args = list(sample_inst.fp_args)
1074
- all_int_args = list(sample_inst.int_args)
1096
+ all_fp_args: set[int | str] = {_arg_ident(a) for a in sample_inst.fp_args}
1097
+ all_int_args: set[int | str] = {_arg_ident(a) for a in sample_inst.int_args}
1075
1098
  both_iter = sample_inst.memory_args
1076
- some_both_args = [next(both_iter) for _ in range(len(args))]
1099
+ some_both_args: set[int | str] = {_arg_ident(next(both_iter)) for _ in range(len(args))}
1077
1100
 
1078
1101
  new_args = []
1079
1102
  for arg in args:
1080
- if arg not in all_fp_args and arg not in all_int_args and arg not in some_both_args:
1103
+ arg_ident = _arg_ident(arg)
1104
+ if arg_ident not in all_fp_args and arg_ident not in all_int_args and arg_ident not in some_both_args:
1081
1105
  if isinstance(arg, SimRegArg) and arg.reg_name in sample_inst.CALLER_SAVED_REGS:
1082
1106
  continue
1083
1107
  return False
@@ -1258,6 +1282,8 @@ class SimCCMicrosoftAMD64(SimCC):
1258
1282
 
1259
1283
  ArgSession = MicrosoftAMD64ArgSession
1260
1284
 
1285
+ STRUCT_RETURN_THRESHOLD = 64
1286
+
1261
1287
  def next_arg(self, session, arg_type):
1262
1288
  if isinstance(arg_type, (SimTypeArray, SimTypeFixedSizeArray)): # hack
1263
1289
  arg_type = SimTypePointer(arg_type.elem_type).with_arch(self.arch)
@@ -1282,7 +1308,26 @@ class SimCCMicrosoftAMD64(SimCC):
1282
1308
  def return_in_implicit_outparam(self, ty):
1283
1309
  if isinstance(ty, SimTypeBottom):
1284
1310
  return False
1285
- return not isinstance(ty, SimTypeFloat) and ty.size > 64
1311
+ return not isinstance(ty, SimTypeFloat) and ty.size > self.STRUCT_RETURN_THRESHOLD
1312
+
1313
+ def return_val(self, ty, perspective_returned=False):
1314
+ if ty._arch is None:
1315
+ ty = ty.with_arch(self.arch)
1316
+ if not isinstance(ty, SimStruct):
1317
+ return super().return_val(ty, perspective_returned)
1318
+
1319
+ if ty.size > self.STRUCT_RETURN_THRESHOLD:
1320
+ # TODO this code is duplicated a ton of places. how should it be a function?
1321
+ byte_size = ty.size // self.arch.byte_width
1322
+ referenced_locs = [SimStackArg(offset, self.arch.bytes) for offset in range(0, byte_size, self.arch.bytes)]
1323
+ referenced_loc = refine_locs_with_struct_type(self.arch, referenced_locs, ty)
1324
+ if perspective_returned:
1325
+ ptr_loc = self.RETURN_VAL
1326
+ else:
1327
+ ptr_loc = self.next_arg(self.ArgSession(self), SimTypePointer(SimTypeBottom()).with_arch(self.arch))
1328
+ return SimReferenceArgument(ptr_loc, referenced_loc)
1329
+
1330
+ return refine_locs_with_struct_type(self.arch, [self.RETURN_VAL], ty)
1286
1331
 
1287
1332
 
1288
1333
  class SimCCSyscall(SimCC):
@@ -29,8 +29,8 @@ class SimConcretizationStrategyNorepeats(SimConcretizationStrategy):
29
29
  )
30
30
 
31
31
  def merge(self, others):
32
- seen = {s.cache_key for s in self._repeat_constraints}
32
+ seen = {s.hash() for s in self._repeat_constraints}
33
33
  for c in itertools.chain.from_iterable(o._repeat_constraints for o in others):
34
- if c.cache_key not in seen:
35
- seen.add(c.cache_key)
34
+ if c.hash() not in seen:
35
+ seen.add(c.hash())
36
36
  self._repeat_constraints.append(c)
angr/engines/concrete.py CHANGED
@@ -61,7 +61,7 @@ class SimEngineConcrete(SuccessorsMixin):
61
61
 
62
62
  successors.engine = "SimEngineConcrete"
63
63
  successors.sort = "SimEngineConcrete"
64
- successors.add_successor(new_state, new_state.ip, claripy.true, new_state.unicorn.jumpkind)
64
+ successors.add_successor(new_state, new_state.ip, claripy.true(), new_state.unicorn.jumpkind)
65
65
  successors.description = "Concrete Successors"
66
66
  successors.processed = True
67
67
 
@@ -419,7 +419,7 @@ class SimEngineLightVEXMixin(SimEngineLightMixin):
419
419
  vector_size, vector_count = None, None
420
420
  if handler is not None:
421
421
  # vector information
422
- m = re.match(r"Iop_[^\d]+(\d+)U{0,1}x(\d+)", expr.op)
422
+ m = re.match(r"Iop_[^\d]+(\d+)[SU]{0,1}x(\d+)", expr.op)
423
423
  if m is not None:
424
424
  vector_size = int(m.group(1))
425
425
  vector_count = int(m.group(2))
@@ -1340,12 +1340,8 @@ class SimEngineLightAILMixin(SimEngineLightMixin):
1340
1340
  if expr_1 is None:
1341
1341
  expr_1 = arg1
1342
1342
 
1343
- try:
1344
- if isinstance(expr_1, claripy.ast.BV) and expr_1.concrete:
1345
- return expr_0 << expr_1.concrete_value
1346
- except TypeError:
1347
- pass
1348
-
1343
+ if isinstance(expr_0, claripy.ast.BV) and isinstance(expr_1, claripy.ast.BV) and expr_1.concrete:
1344
+ return expr_0 << expr_1.concrete_value
1349
1345
  return ailment.Expr.BinaryOp(expr.idx, "Shl", [expr_0, expr_1], expr.signed, **expr.tags)
1350
1346
 
1351
1347
  def _ail_handle_Sal(self, expr):
@@ -1385,10 +1381,9 @@ class SimEngineLightAILMixin(SimEngineLightMixin):
1385
1381
  if expr_1 is None:
1386
1382
  expr_1 = arg1
1387
1383
 
1388
- try:
1389
- return expr_0 >> expr_1
1390
- except TypeError:
1391
- return ailment.Expr.BinaryOp(expr.idx, "Sar", [expr_0, expr_1], expr.signed, **expr.tags)
1384
+ if isinstance(expr_0, claripy.ast.Bits) and isinstance(expr_1, claripy.ast.Bits) and expr_1.concrete:
1385
+ return expr_0 >> expr_1.concrete_value
1386
+ return ailment.Expr.BinaryOp(expr.idx, "Sar", [expr_0, expr_1], expr.signed, **expr.tags)
1392
1387
 
1393
1388
  def _ail_handle_Concat(self, expr):
1394
1389
  arg0, arg1 = expr.operands
@@ -85,7 +85,7 @@ class HeavyPcodeMixin(
85
85
  successors.sort = "IRSB"
86
86
  successors.description = "IRSB"
87
87
  self.state.history.recent_block_count = 1
88
- self.state.scratch.guard = claripy.true
88
+ self.state.scratch.guard = claripy.true()
89
89
  self.state.scratch.sim_procedure = None
90
90
  addr = successors.addr
91
91
  self.state.scratch.bbl_addr = addr
@@ -240,7 +240,7 @@ class HeavyPcodeMixin(
240
240
  l.debug("%s adding postcall exit.", self)
241
241
 
242
242
  ret_state = exit_state.copy()
243
- guard = claripy.true if o.TRUE_RET_EMULATION_GUARD in self.state.options else claripy.false
243
+ guard = claripy.true() if o.TRUE_RET_EMULATION_GUARD in self.state.options else claripy.false()
244
244
  ret_target = claripy.BVV(successors.addr + self.state.scratch.irsb.size, ret_state.arch.bits)
245
245
  if ret_state.arch.call_pushes_ret and not exit_jumpkind.startswith("Ijk_Sys"):
246
246
  ret_state.regs.sp = ret_state.regs.sp + ret_state.arch.bytes
@@ -136,7 +136,7 @@ class SootMixin(SuccessorsMixin, ProcedureMixin):
136
136
  next_addr = self._get_next_linear_instruction(state, stmt_idx)
137
137
  l.debug("Advancing execution linearly to %s", next_addr)
138
138
  if next_addr is not None:
139
- successors.add_successor(state.copy(), next_addr, claripy.true, "Ijk_Boring")
139
+ successors.add_successor(state.copy(), next_addr, claripy.true(), "Ijk_Boring")
140
140
 
141
141
  def _handle_soot_stmt(self, state, successors, stmt_idx, stmt):
142
142
  # execute statement
@@ -174,7 +174,7 @@ class SootMixin(SuccessorsMixin, ProcedureMixin):
174
174
  # add invoke state as the successor and terminate execution
175
175
  # prematurely, since Soot does not guarantee that an invoke stmt
176
176
  # terminates a block
177
- successors.add_successor(invoke_state, addr, claripy.true, "Ijk_Call")
177
+ successors.add_successor(invoke_state, addr, claripy.true(), "Ijk_Call")
178
178
  return True
179
179
 
180
180
  # add jmp exit
@@ -199,7 +199,7 @@ class SootMixin(SuccessorsMixin, ProcedureMixin):
199
199
  def _add_return_exit(cls, state, successors, return_val=None):
200
200
  ret_state = state.copy()
201
201
  cls.prepare_return_state(ret_state, return_val)
202
- successors.add_successor(ret_state, state.callstack.ret_addr, claripy.true, "Ijk_Ret")
202
+ successors.add_successor(ret_state, state.callstack.ret_addr, claripy.true(), "Ijk_Ret")
203
203
  successors.processed = True
204
204
 
205
205
  def _get_sim_procedure(self, addr):
@@ -320,7 +320,7 @@ class SootMixin(SuccessorsMixin, ProcedureMixin):
320
320
  # TODO symbolic exit code?
321
321
  exit_code = claripy.BVV(exit_code, state.arch.bits)
322
322
  state.history.add_event("terminate", exit_code=exit_code)
323
- successors.add_successor(state, state.regs.ip, claripy.true, "Ijk_Exit")
323
+ successors.add_successor(state, state.regs.ip, claripy.true(), "Ijk_Exit")
324
324
  successors.processed = True
325
325
  raise BlockTerminationNotice
326
326
 
@@ -342,7 +342,7 @@ class SootMixin(SuccessorsMixin, ProcedureMixin):
342
342
 
343
343
  # set successor flags
344
344
  ret_state.regs._ip = ret_state.callstack.ret_addr
345
- ret_state.scratch.guard = claripy.true
345
+ ret_state.scratch.guard = claripy.true()
346
346
  ret_state.history.jumpkind = "Ijk_Ret"
347
347
 
348
348
  # if available, lookup the return value in native memory
@@ -19,7 +19,7 @@ class SimSootExpr_Condition(SimSootExpr):
19
19
  elif isinstance(v1.expr, (SootNullConstant, SimSootValue_StringRef)) or isinstance(
20
20
  v2.expr, (SootNullConstant, SimSootValue_StringRef)
21
21
  ):
22
- self.expr = claripy.true if operator_func(v1.expr, v2.expr) else claripy.false
22
+ self.expr = claripy.true() if operator_func(v1.expr, v2.expr) else claripy.false()
23
23
  else:
24
24
  self.expr = operator_func(v1.expr, v2.expr)
25
25
 
@@ -11,4 +11,4 @@ l = logging.getLogger("angr.engines.soot.statements.goto")
11
11
  class SimSootStmt_Goto(SimSootStmt):
12
12
  def _execute(self):
13
13
  jmp_target = self._get_bb_addr_from_instr(instr=self.stmt.target)
14
- self._add_jmp_target(target=jmp_target, condition=claripy.true)
14
+ self._add_jmp_target(target=jmp_target, condition=claripy.true())
@@ -15,5 +15,5 @@ class SimSootStmt_If(SimSootStmt):
15
15
  self._add_jmp_target(target=jmp_target, condition=jmp_condition)
16
16
  self._add_jmp_target(
17
17
  target=None, # if target is None, engine goes on linearly
18
- condition=(jmp_condition == claripy.false),
18
+ condition=(jmp_condition == claripy.false()),
19
19
  )
@@ -12,4 +12,4 @@ l = logging.getLogger(name=__name__)
12
12
  class SimSootStmt_Throw(SimSootStmt):
13
13
  def _execute(self):
14
14
  # TODO: implement simprocedure to throw exception
15
- self._add_jmp_target(target=SootAddressTerminator(), condition=claripy.true)
15
+ self._add_jmp_target(target=SootAddressTerminator(), condition=claripy.true())
@@ -320,7 +320,7 @@ class SimSuccessors:
320
320
  skip_max_targets_warning = False
321
321
  if o.NO_IP_CONCRETIZATION in state.options:
322
322
  # Don't try to concretize the IP
323
- cond_and_targets = [(claripy.true, target)]
323
+ cond_and_targets = [(claripy.true(), target)]
324
324
  max_targets = 0
325
325
  skip_max_targets_warning = True # don't warn
326
326
  elif o.KEEP_IP_SYMBOLIC in state.options:
angr/engines/unicorn.py CHANGED
@@ -184,7 +184,7 @@ class SimEngineUnicorn(SuccessorsMixin):
184
184
 
185
185
  self._instr_mem_write_addrs = set() # pylint:disable=attribute-defined-outside-init
186
186
  for block_details in self.state.unicorn._get_details_of_blocks_with_symbolic_vex_stmts():
187
- self.state.scratch.guard = claripy.true
187
+ self.state.scratch.guard = claripy.true()
188
188
  try:
189
189
  if self.state.os_name == "CGC" and block_details["block_addr"] in {
190
190
  self.state.unicorn.cgc_random_addr,
@@ -481,7 +481,7 @@ class SimEngineUnicorn(SuccessorsMixin):
481
481
 
482
482
  if state.unicorn.jumpkind.startswith("Ijk_Sys"):
483
483
  state.ip = state.unicorn._syscall_pc
484
- successors.add_successor(state, state.ip, claripy.true, state.unicorn.jumpkind)
484
+ successors.add_successor(state, state.ip, claripy.true(), state.unicorn.jumpkind)
485
485
 
486
486
  successors.description = description
487
487
  successors.processed = True
@@ -116,7 +116,7 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
116
116
  successors.sort = "IRSB"
117
117
  successors.description = "IRSB"
118
118
  self.state.history.recent_block_count = 1
119
- self.state.scratch.guard = claripy.true
119
+ self.state.scratch.guard = claripy.true()
120
120
  self.state.scratch.sim_procedure = None
121
121
  addr = successors.addr
122
122
  self.state.scratch.bbl_addr = addr
@@ -216,7 +216,7 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
216
216
  l.debug("%s adding postcall exit.", self)
217
217
 
218
218
  ret_state = exit_state.copy()
219
- guard = claripy.true if o.TRUE_RET_EMULATION_GUARD in self.state.options else claripy.false
219
+ guard = claripy.true() if o.TRUE_RET_EMULATION_GUARD in self.state.options else claripy.false()
220
220
  ret_target = claripy.BVV(successors.addr + irsb.size, ret_state.arch.bits)
221
221
  ret_state.registers.store(
222
222
  ret_state.arch.ret_offset, ret_state.solver.Unconstrained("fake_ret_value", ret_state.arch.bits)
angr/errors.py CHANGED
@@ -605,5 +605,9 @@ class SimConcreteBreakpointError(AngrError):
605
605
  #
606
606
 
607
607
 
608
+ class AngrDecompilationError(AngrError):
609
+ pass
610
+
611
+
608
612
  class UnsupportedNodeTypeError(AngrError, NotImplementedError):
609
613
  pass
@@ -94,8 +94,7 @@ class DrillerCore(ExplorationTechnique):
94
94
  @staticmethod
95
95
  def _has_false(state):
96
96
  # Check if the state is unsat even if we remove preconstraints.
97
- claripy_false = claripy.false
98
- if state.scratch.guard.cache_key == claripy_false.cache_key:
97
+ if state.scratch.guard.identical(claripy.false()):
99
98
  return True
100
99
 
101
- return any(c.cache_key == claripy_false.cache_key for c in state.solver.constraints)
100
+ return any(c.identical(claripy.false()) for c in state.solver.constraints)
@@ -20,12 +20,12 @@ def ast_weight(ast, memo=None):
20
20
  if memo is None:
21
21
  memo = {}
22
22
 
23
- result = memo.get(ast.cache_key, None)
23
+ result = memo.get(ast.hash(), None)
24
24
  if result is not None:
25
25
  return result
26
26
 
27
27
  result = 1 + sum(ast_weight(arg, memo) for arg in ast.args)
28
- memo[ast.cache_key] = result
28
+ memo[ast.hash()] = result
29
29
  return result
30
30
 
31
31
 
@@ -721,7 +721,8 @@ class CFGModel(Serializable):
721
721
  new_data_found = True
722
722
 
723
723
  else:
724
- memory_data.size = memory_data.max_size
724
+ if memory_data.max_size is not None:
725
+ memory_data.size = memory_data.max_size
725
726
 
726
727
  if seg_list is not None:
727
728
  seg_list.occupy(data_addr, memory_data.size, memory_data.sort)
@@ -16,6 +16,7 @@ class MemoryDataSort:
16
16
  GOTPLTEntry = "GOT PLT Entry"
17
17
  ELFHeader = "elf-header"
18
18
  FloatingPoint = "fp" # the size is determined by the MemoryData itself
19
+ Alignment = "alignment"
19
20
 
20
21
 
21
22
  _SORT_TO_IDX = {
Binary file
angr/misc/telemetry.py ADDED
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING
3
+ import enum
4
+
5
+ try:
6
+ from opentelemetry.trace import get_current_span, Status, StatusCode, Tracer, get_tracer as _get_tracer
7
+ except ImportError:
8
+ if TYPE_CHECKING:
9
+ raise
10
+
11
+ # pylint: disable=missing-class-docstring,unused-argument
12
+ class Status:
13
+ def __init__(self, *args, **kwargs):
14
+ pass
15
+
16
+ class StatusCode(enum.Enum):
17
+ OK = 0
18
+ UNSET = 1
19
+ ERROR = 2
20
+
21
+ class Tracer:
22
+ @staticmethod
23
+ def start_as_current_span(*args, **kwargs):
24
+ def inner(f):
25
+ return f
26
+
27
+ return inner
28
+
29
+ @staticmethod
30
+ def get_current_span(*args, **kwargs):
31
+ return Span()
32
+
33
+ def _get_tracer(*args, **kwargs):
34
+ return Tracer()
35
+
36
+ class Span:
37
+ @staticmethod
38
+ def set_attribute(*args, **kwargs):
39
+ pass
40
+
41
+ @staticmethod
42
+ def add_event(*args, **kwargs):
43
+ pass
44
+
45
+ get_current_span = Tracer.get_current_span
46
+
47
+
48
+ from angr import __version__
49
+
50
+ __all__ = ["get_tracer", "get_current_span", "Status", "StatusCode"]
51
+
52
+
53
+ def get_tracer(name: str) -> Tracer:
54
+ return _get_tracer(name, __version__)
@@ -33,7 +33,7 @@ class UnconstrainedMethod(JavaSimProcedure):
33
33
  ret_value = claripy.FPS(f"unc_double_{method_descriptor.name}", claripy.FSORT_DOUBLE)
34
34
  elif method_descriptor.ret == "java.lang.String":
35
35
  str_ref = SimSootValue_StringRef.new_string(
36
- self.state, claripy.StringS(f"unc_string_{method_descriptor.name}", 1000)
36
+ self.state, claripy.StringS(f"unc_string_{method_descriptor.name}")
37
37
  )
38
38
  ret_value = str_ref
39
39
  elif method_descriptor.ret.endswith("[][]"):
@@ -152,8 +152,18 @@ class JNISimProcedure(SimProcedure):
152
152
  If not set, native memory is allocated.
153
153
  :return: Native address of the string.
154
154
  """
155
+ # warn if string is symbolic
156
+ if self.state.solver.symbolic(string):
157
+ l.warning(
158
+ "Support for symbolic strings, passed to native code, is limited. "
159
+ "Length will be concretized immediately. String value will get "
160
+ "concretized after `ReleaseStringUTFChars` is called."
161
+ )
162
+
163
+ length = self.state.solver.eval(claripy.StrLen(string)) * 8
164
+
155
165
  if addr is None:
156
- addr = self._allocate_native_memory(size=len(string) + 1)
166
+ addr = self._allocate_native_memory(size=length + 1)
157
167
  else:
158
168
  # check if addr is symbolic
159
169
  if self.state.solver.symbolic(addr):
@@ -163,21 +173,19 @@ class JNISimProcedure(SimProcedure):
163
173
  )
164
174
  addr = self.state.solver.eval(addr)
165
175
 
166
- # warn if string is symbolic
167
- if self.state.solver.symbolic(string):
168
- l.warning(
169
- "Support for symbolic strings, passed to native code, is limited. "
170
- "String will get concretized after `ReleaseStringUTFChars` is called."
171
- )
172
-
173
176
  # store chars one by one
174
- str_len = len(string) // 8
175
- for idx in range(str_len):
176
- str_byte = claripy.StrSubstr(idx, 1, string)
177
- self.state.memory.store(addr + idx, str_byte)
177
+ if string.symbolic:
178
+ bvs = claripy.BVS(next(iter(string.variables)), length)
179
+ self.state.memory.store(addr, bvs)
180
+ else:
181
+ str_len = length // 8
182
+ for idx in range(str_len):
183
+ str_byte = claripy.StrSubstr(idx, 1, string)
184
+ as_bv = claripy.BVV(ord(self.state.solver.eval(str_byte)), 8)
185
+ self.state.memory.store(addr + idx, as_bv)
178
186
 
179
187
  # store terminating zero
180
- self.state.memory.store(len(string), claripy.BVV(0, 8))
188
+ self.state.memory.store(length, claripy.BVV(0, 8))
181
189
 
182
190
  return addr
183
191
 
@@ -84,4 +84,4 @@ class GetStringUTFLength(JNISimProcedure):
84
84
  def run(self, ptr_env, str_ref_):
85
85
  str_ref = self.state.jni_references.lookup(str_ref_)
86
86
  str_val = self.state.javavm_memory.load(str_ref)
87
- return StrLen(str_val, 32)
87
+ return StrLen(str_val)
@@ -21,4 +21,4 @@ class ParseDouble(JavaSimProcedure):
21
21
  double_val = float(str_value)
22
22
  return claripy.FPV(double_val, claripy.FSORT_DOUBLE)
23
23
 
24
- return claripy.StrToInt(str_, self.arch.bits)
24
+ return claripy.StrToInt(str_)
@@ -65,7 +65,7 @@ class StringLength(JavaSimProcedure):
65
65
  def run(self, this_str):
66
66
  log.debug(f"Called SimProcedure java.lang.String.length with args: {this_str}")
67
67
 
68
- return claripy.StrLen(self.state.memory.load(this_str), 32)
68
+ return claripy.StrLen(self.state.memory.load(this_str))
69
69
 
70
70
 
71
71
  class StringCharAt(JavaSimProcedure):
@@ -14,7 +14,7 @@ class ScannerNextLine(JavaSimProcedure):
14
14
 
15
15
  def run(self, this): # pylint: disable=arguments-differ,unused-argument
16
16
  str_ref = SimSootValue_StringRef(self.state.memory.get_new_uuid())
17
- self.state.memory.store(str_ref, StringS("scanner_return", 100))
17
+ self.state.memory.store(str_ref, StringS("scanner_return"))
18
18
  # save reference in global dict, so we can easily access it later
19
19
  try:
20
20
  self.state.globals["java.util.Scanner"].append(str_ref)
@@ -13,4 +13,4 @@ class _vsyscall(angr.SimProcedure):
13
13
  else:
14
14
  ret_addr = self.state.registers.load(self.state.arch.lr_offset, self.state.arch.bytes)
15
15
 
16
- self.successors.add_successor(self.state, ret_addr, claripy.true, "Ijk_Sys")
16
+ self.successors.add_successor(self.state, ret_addr, claripy.true(), "Ijk_Sys")