angr 9.2.118__py3-none-manylinux2014_x86_64.whl → 9.2.119__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.
- angr/__init__.py +1 -1
- angr/analyses/analysis.py +43 -1
- angr/analyses/cfg/cfg_fast.py +135 -23
- angr/analyses/decompiler/ail_simplifier.py +1 -1
- angr/analyses/decompiler/clinic.py +23 -12
- angr/analyses/decompiler/condition_processor.py +41 -16
- angr/analyses/decompiler/decompiler.py +3 -0
- angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +1 -1
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +7 -4
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +6 -2
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +19 -19
- angr/analyses/decompiler/structured_codegen/c.py +9 -2
- angr/analyses/decompiler/structuring/dream.py +8 -7
- angr/analyses/decompiler/structuring/phoenix.py +3 -3
- angr/analyses/propagator/engine_ail.py +2 -1
- angr/analyses/reaching_definitions/function_handler.py +6 -2
- angr/analyses/stack_pointer_tracker.py +29 -11
- angr/analyses/typehoon/translator.py +19 -2
- angr/analyses/typehoon/typeconsts.py +8 -0
- angr/analyses/variable_recovery/engine_vex.py +7 -10
- angr/calling_conventions.py +69 -24
- angr/concretization_strategies/norepeats.py +3 -3
- angr/engines/concrete.py +1 -1
- angr/engines/light/engine.py +6 -11
- angr/engines/pcode/engine.py +2 -2
- angr/engines/soot/engine.py +5 -5
- angr/engines/soot/expressions/condition.py +1 -1
- angr/engines/soot/statements/goto.py +1 -1
- angr/engines/soot/statements/if_.py +1 -1
- angr/engines/soot/statements/throw.py +1 -1
- angr/engines/successors.py +1 -1
- angr/engines/unicorn.py +2 -2
- angr/engines/vex/heavy/heavy.py +2 -2
- angr/errors.py +4 -0
- angr/exploration_techniques/driller_core.py +2 -3
- angr/exploration_techniques/suggestions.py +2 -2
- angr/knowledge_plugins/cfg/cfg_model.py +2 -1
- angr/knowledge_plugins/cfg/memory_data.py +1 -0
- angr/misc/telemetry.py +54 -0
- angr/procedures/java/unconstrained.py +1 -1
- angr/procedures/java_jni/__init__.py +21 -13
- angr/procedures/java_jni/string_operations.py +1 -1
- angr/procedures/java_lang/double.py +1 -1
- angr/procedures/java_lang/string.py +1 -1
- angr/procedures/java_util/scanner_nextline.py +1 -1
- angr/procedures/linux_kernel/vsyscall.py +1 -1
- angr/procedures/stubs/Redirect.py +1 -1
- angr/procedures/stubs/UserHook.py +1 -1
- angr/procedures/stubs/format_parser.py +1 -1
- angr/sim_procedure.py +5 -5
- angr/sim_state.py +21 -34
- angr/sim_type.py +42 -0
- angr/simos/javavm.py +7 -12
- angr/simos/linux.py +1 -1
- angr/simos/simos.py +1 -1
- angr/simos/windows.py +1 -1
- angr/state_hierarchy.py +1 -1
- angr/state_plugins/preconstrainer.py +2 -2
- angr/state_plugins/scratch.py +1 -1
- angr/state_plugins/solver.py +1 -1
- angr/state_plugins/trace_additions.py +8 -8
- angr/storage/file.py +12 -12
- angr/storage/memory_mixins/actions_mixin.py +1 -1
- angr/storage/memory_mixins/convenient_mappings_mixin.py +6 -8
- angr/storage/memory_mixins/multi_value_merger_mixin.py +5 -5
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +1 -1
- angr/storage/memory_mixins/size_resolution_mixin.py +1 -1
- angr/storage/memory_mixins/smart_find_mixin.py +2 -2
- angr/storage/memory_object.py +7 -9
- angr/utils/timing.py +30 -18
- {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/METADATA +8 -6
- {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/RECORD +76 -75
- {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/LICENSE +0 -0
- {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/WHEEL +0 -0
- {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/entry_points.txt +0 -0
- {angr-9.2.118.dist-info → angr-9.2.119.dist-info}/top_level.txt +0 -0
angr/calling_conventions.py
CHANGED
|
@@ -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
|
|
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
|
|
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) ->
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
427
|
-
|
|
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
|
-
|
|
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 =
|
|
1074
|
-
all_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 =
|
|
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
|
-
|
|
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 >
|
|
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.
|
|
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.
|
|
35
|
-
seen.add(c.
|
|
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
|
|
angr/engines/light/engine.py
CHANGED
|
@@ -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+)
|
|
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
|
-
|
|
1344
|
-
|
|
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
|
-
|
|
1389
|
-
return expr_0 >> expr_1
|
|
1390
|
-
|
|
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
|
angr/engines/pcode/engine.py
CHANGED
|
@@ -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
|
angr/engines/soot/engine.py
CHANGED
|
@@ -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())
|
angr/engines/successors.py
CHANGED
|
@@ -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
|
angr/engines/vex/heavy/heavy.py
CHANGED
|
@@ -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
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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)
|
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}"
|
|
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=
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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(
|
|
188
|
+
self.state.memory.store(length, claripy.BVV(0, 8))
|
|
181
189
|
|
|
182
190
|
return addr
|
|
183
191
|
|
|
@@ -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)
|
|
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"
|
|
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")
|
|
@@ -15,4 +15,4 @@ class Redirect(angr.SimProcedure):
|
|
|
15
15
|
|
|
16
16
|
self._custom_name = f"Redirect to 0x{redirect_to:08x}"
|
|
17
17
|
# There is definitely no refs
|
|
18
|
-
self.add_successor(self.state, redirect_to, claripy.true, "Ijk_Boring")
|
|
18
|
+
self.add_successor(self.state, redirect_to, claripy.true(), "Ijk_Boring")
|