angr 9.2.87__py3-none-manylinux2014_x86_64.whl → 9.2.89__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 +4 -1
- angr/analyses/decompiler/clinic.py +16 -0
- angr/analyses/decompiler/decompiler.py +3 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +5 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +108 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +17 -4
- angr/analyses/decompiler/optimization_passes/return_duplicator.py +4 -32
- angr/analyses/decompiler/structured_codegen/c.py +12 -2
- angr/analyses/decompiler/utils.py +13 -0
- angr/analyses/typehoon/dfa.py +108 -0
- angr/analyses/typehoon/lifter.py +34 -2
- angr/analyses/typehoon/simple_solver.py +1043 -503
- angr/analyses/typehoon/translator.py +13 -4
- angr/analyses/typehoon/typeconsts.py +117 -36
- angr/analyses/typehoon/typehoon.py +31 -11
- angr/analyses/typehoon/typevars.py +88 -21
- angr/analyses/typehoon/variance.py +10 -0
- angr/analyses/variable_recovery/engine_ail.py +28 -9
- angr/analyses/variable_recovery/engine_base.py +50 -43
- angr/analyses/variable_recovery/variable_recovery_base.py +16 -3
- angr/analyses/variable_recovery/variable_recovery_fast.py +14 -5
- angr/exploration_techniques/tracer.py +2 -0
- angr/misc/autoimport.py +26 -0
- angr/procedures/definitions/__init__.py +32 -3
- angr/utils/constants.py +1 -0
- angr/utils/graph.py +20 -1
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/METADATA +7 -6
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/RECORD +32 -244
- angr-9.2.89.dist-info/top_level.txt +1 -0
- angr/procedures/definitions/ntdll.py +0 -12
- angr-9.2.87.dist-info/top_level.txt +0 -2
- tests/__init__.py +0 -0
- tests/analyses/__init__.py +0 -0
- tests/analyses/cfg/__init__.py +0 -0
- tests/analyses/cfg/test_cfg_clflush.py +0 -43
- tests/analyses/cfg/test_cfg_get_any_node.py +0 -34
- tests/analyses/cfg/test_cfg_manager.py +0 -32
- tests/analyses/cfg/test_cfg_model.py +0 -55
- tests/analyses/cfg/test_cfg_patching.py +0 -378
- tests/analyses/cfg/test_cfg_rust_got_resolution.py +0 -36
- tests/analyses/cfg/test_cfg_thumb_firmware.py +0 -50
- tests/analyses/cfg/test_cfg_vex_postprocessor.py +0 -27
- tests/analyses/cfg/test_cfgemulated.py +0 -634
- tests/analyses/cfg/test_cfgfast.py +0 -1123
- tests/analyses/cfg/test_cfgfast_soot.py +0 -38
- tests/analyses/cfg/test_const_resolver.py +0 -38
- tests/analyses/cfg/test_iat_resolver.py +0 -37
- tests/analyses/cfg/test_jumptables.py +0 -3008
- tests/analyses/cfg/test_noop_blocks.py +0 -54
- tests/analyses/cfg_slice_to_sink/__init__.py +0 -0
- tests/analyses/cfg_slice_to_sink/test_cfg_slice_to_sink.py +0 -93
- tests/analyses/cfg_slice_to_sink/test_graph.py +0 -114
- tests/analyses/cfg_slice_to_sink/test_transitions.py +0 -28
- tests/analyses/decompiler/__init__.py +0 -0
- tests/analyses/decompiler/test_baseptr_save_simplifier.py +0 -80
- tests/analyses/decompiler/test_decompiler.py +0 -3336
- tests/analyses/decompiler/test_peephole_optimizations.py +0 -48
- tests/analyses/decompiler/test_propagator_loops.py +0 -101
- tests/analyses/decompiler/test_structurer.py +0 -275
- tests/analyses/reaching_definitions/__init__.py +0 -0
- tests/analyses/reaching_definitions/test_dep_graph.py +0 -432
- tests/analyses/reaching_definitions/test_function_handler.py +0 -131
- tests/analyses/reaching_definitions/test_heap_allocator.py +0 -46
- tests/analyses/reaching_definitions/test_rd_state.py +0 -78
- tests/analyses/reaching_definitions/test_reachingdefinitions.py +0 -463
- tests/analyses/reaching_definitions/test_subject.py +0 -76
- tests/analyses/test_bindiff.py +0 -52
- tests/analyses/test_block_simplifier.py +0 -112
- tests/analyses/test_boyscout.py +0 -104
- tests/analyses/test_calling_convention_analysis.py +0 -352
- tests/analyses/test_callsite_maker.py +0 -60
- tests/analyses/test_cdg.py +0 -165
- tests/analyses/test_cfb.py +0 -37
- tests/analyses/test_class_identifier.py +0 -46
- tests/analyses/test_clinic.py +0 -30
- tests/analyses/test_codetagging.py +0 -32
- tests/analyses/test_constantpropagation.py +0 -88
- tests/analyses/test_ddg.py +0 -95
- tests/analyses/test_ddg_global_var_dependencies.py +0 -83
- tests/analyses/test_ddg_memvar_addresses.py +0 -40
- tests/analyses/test_disassembly.py +0 -121
- tests/analyses/test_find_objects_static.py +0 -35
- tests/analyses/test_flirt.py +0 -49
- tests/analyses/test_identifier.py +0 -33
- tests/analyses/test_init_finder.py +0 -38
- tests/analyses/test_proximitygraph.py +0 -31
- tests/analyses/test_reassembler.py +0 -295
- tests/analyses/test_regionidentifier.py +0 -27
- tests/analyses/test_slicing.py +0 -164
- tests/analyses/test_stack_pointer_tracker.py +0 -74
- tests/analyses/test_static_hooker.py +0 -28
- tests/analyses/test_typehoon.py +0 -55
- tests/analyses/test_variablerecovery.py +0 -464
- tests/analyses/test_vfg.py +0 -221
- tests/analyses/test_vtable.py +0 -31
- tests/analyses/test_xrefs.py +0 -77
- tests/common.py +0 -128
- tests/engines/__init__.py +0 -0
- tests/engines/light/__init__.py +0 -0
- tests/engines/light/test_data.py +0 -17
- tests/engines/pcode/__init__.py +0 -0
- tests/engines/pcode/test_emulate.py +0 -607
- tests/engines/pcode/test_pcode.py +0 -84
- tests/engines/test_actions.py +0 -27
- tests/engines/test_hook.py +0 -112
- tests/engines/test_java.py +0 -697
- tests/engines/test_unicorn.py +0 -518
- tests/engines/vex/__init__.py +0 -0
- tests/engines/vex/test_lifter.py +0 -124
- tests/engines/vex/test_vex.py +0 -574
- tests/exploration_techniques/__init__.py +0 -0
- tests/exploration_techniques/test_cacher.py +0 -45
- tests/exploration_techniques/test_director.py +0 -67
- tests/exploration_techniques/test_driller_core.py +0 -48
- tests/exploration_techniques/test_loop_seer.py +0 -158
- tests/exploration_techniques/test_memory_watcher.py +0 -46
- tests/exploration_techniques/test_oppologist.py +0 -65
- tests/exploration_techniques/test_spiller.py +0 -82
- tests/exploration_techniques/test_stochastic.py +0 -40
- tests/exploration_techniques/test_tech_builder.py +0 -61
- tests/exploration_techniques/test_tracer.py +0 -856
- tests/exploration_techniques/test_unique.py +0 -40
- tests/exploration_techniques/test_veritesting.py +0 -120
- tests/factory/__init__.py +0 -0
- tests/factory/block/__init__.py +0 -0
- tests/factory/block/test_block_cache.py +0 -33
- tests/factory/block/test_keystone.py +0 -106
- tests/factory/test_argc.py +0 -101
- tests/factory/test_argc_sym.py +0 -110
- tests/factory/test_argv.py +0 -158
- tests/factory/test_callable.py +0 -266
- tests/factory/test_windows_args.py +0 -36
- tests/knowledge_plugins/__init__.py +0 -0
- tests/knowledge_plugins/cfg/__init__.py +0 -0
- tests/knowledge_plugins/cfg/test_cfg_manager.py +0 -36
- tests/knowledge_plugins/functions/__init__.py +0 -0
- tests/knowledge_plugins/functions/test_function.py +0 -91
- tests/knowledge_plugins/functions/test_function2.py +0 -79
- tests/knowledge_plugins/functions/test_function_manager.py +0 -139
- tests/knowledge_plugins/functions/test_prototypes.py +0 -53
- tests/knowledge_plugins/key_definitions/__init__.py +0 -0
- tests/knowledge_plugins/key_definitions/test_atoms.py +0 -24
- tests/knowledge_plugins/key_definitions/test_environment.py +0 -126
- tests/knowledge_plugins/key_definitions/test_heap_address.py +0 -27
- tests/knowledge_plugins/key_definitions/test_live_definitions.py +0 -72
- tests/knowledge_plugins/test_dwarf_variables.py +0 -240
- tests/knowledge_plugins/test_kb_plugins.py +0 -91
- tests/knowledge_plugins/test_kb_plugins_dwarf.py +0 -36
- tests/knowledge_plugins/test_patches.py +0 -48
- tests/misc/__init__.py +0 -0
- tests/misc/test_hookset.py +0 -57
- tests/perf/__init__.py +0 -0
- tests/perf/perf_cfgemulated.py +0 -19
- tests/perf/perf_cfgfast.py +0 -18
- tests/perf/perf_concrete_execution.py +0 -41
- tests/perf/perf_siminspect_nop.py +0 -36
- tests/perf/perf_state_copy.py +0 -33
- tests/perf/perf_unicorn_0.py +0 -27
- tests/perf/perf_unicorn_1.py +0 -23
- tests/procedures/__init__.py +0 -0
- tests/procedures/glibc/__init__.py +0 -0
- tests/procedures/glibc/test_ctype_locale.py +0 -164
- tests/procedures/libc/__init__.py +0 -0
- tests/procedures/libc/test_fgets.py +0 -53
- tests/procedures/libc/test_scanf.py +0 -205
- tests/procedures/libc/test_sprintf.py +0 -44
- tests/procedures/libc/test_sscanf.py +0 -63
- tests/procedures/libc/test_strcasecmp.py +0 -37
- tests/procedures/libc/test_string.py +0 -1102
- tests/procedures/libc/test_strtol.py +0 -78
- tests/procedures/linux_kernel/__init__.py +0 -0
- tests/procedures/linux_kernel/test_lseek.py +0 -174
- tests/procedures/posix/__init__.py +0 -0
- tests/procedures/posix/test_chroot.py +0 -33
- tests/procedures/posix/test_getenv.py +0 -78
- tests/procedures/posix/test_pwrite_pread.py +0 -57
- tests/procedures/posix/test_sim_time.py +0 -46
- tests/procedures/posix/test_unlink.py +0 -46
- tests/procedures/test_project_resolve_simproc.py +0 -43
- tests/procedures/test_sim_procedure.py +0 -117
- tests/procedures/test_stub_procedure_args.py +0 -53
- tests/serialization/__init__.py +0 -0
- tests/serialization/test_db.py +0 -197
- tests/serialization/test_pickle.py +0 -95
- tests/serialization/test_serialization.py +0 -132
- tests/serialization/test_vault.py +0 -169
- tests/sim/__init__.py +0 -3
- tests/sim/exec_func/__init__.py +0 -0
- tests/sim/exec_func/test_mem_funcs.py +0 -55
- tests/sim/exec_func/test_str_funcs.py +0 -93
- tests/sim/exec_func/test_syscall_result.py +0 -39
- tests/sim/exec_insn/__init__.py +0 -0
- tests/sim/exec_insn/test_adc.py +0 -44
- tests/sim/exec_insn/test_ops.py +0 -83
- tests/sim/exec_insn/test_rcr.py +0 -26
- tests/sim/exec_insn/test_rol.py +0 -51
- tests/sim/exec_insn/test_signed_div.py +0 -34
- tests/sim/exec_insn/test_sqrt.py +0 -56
- tests/sim/options/__init__.py +0 -0
- tests/sim/options/test_0div.py +0 -54
- tests/sim/options/test_symbolic_fd.py +0 -59
- tests/sim/options/test_unsupported.py +0 -34
- tests/sim/test_accuracy.py +0 -137
- tests/sim/test_checkbyte.py +0 -53
- tests/sim/test_echo.py +0 -36
- tests/sim/test_fauxware.py +0 -202
- tests/sim/test_self_modifying_code.py +0 -65
- tests/sim/test_simple_api.py +0 -36
- tests/sim/test_simulation_manager.py +0 -147
- tests/sim/test_stack_alignment.py +0 -65
- tests/sim/test_state.py +0 -303
- tests/sim/test_state_customization.py +0 -54
- tests/sim/test_symbol_hooked_by.py +0 -49
- tests/simos/__init__.py +0 -0
- tests/simos/windows/__init__.py +0 -0
- tests/simos/windows/test_windows_stack_cookie.py +0 -58
- tests/state_plugins/__init__.py +0 -0
- tests/state_plugins/inspect/__init__.py +0 -0
- tests/state_plugins/inspect/test_inspect.py +0 -310
- tests/state_plugins/inspect/test_syscall_override.py +0 -90
- tests/state_plugins/posix/__init__.py +0 -0
- tests/state_plugins/posix/test_file_struct_funcs.py +0 -56
- tests/state_plugins/posix/test_files.py +0 -69
- tests/state_plugins/posix/test_posix.py +0 -72
- tests/state_plugins/solver/__init__.py +0 -0
- tests/state_plugins/solver/test_simsolver.py +0 -58
- tests/state_plugins/solver/test_symbolic.py +0 -153
- tests/state_plugins/solver/test_variable_registration.py +0 -46
- tests/state_plugins/test_callstack.py +0 -54
- tests/state_plugins/test_gdb_plugin.py +0 -35
- tests/state_plugins/test_multi_open_file.py +0 -47
- tests/state_plugins/test_symbolization.py +0 -38
- tests/storage/__init__.py +0 -0
- tests/storage/test_memory.py +0 -960
- tests/storage/test_memory_merge.py +0 -114
- tests/storage/test_memview.py +0 -205
- tests/storage/test_mmap.py +0 -26
- tests/storage/test_multivalues.py +0 -44
- tests/storage/test_permissions.py +0 -32
- tests/storage/test_ptmalloc.py +0 -291
- tests/storage/test_relro_perm.py +0 -49
- tests/test_calling_conventions.py +0 -86
- tests/test_types.py +0 -329
- tests/utils/__init__.py +0 -0
- tests/utils/test_graph.py +0 -41
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/LICENSE +0 -0
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/WHEEL +0 -0
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/entry_points.txt +0 -0
|
@@ -91,15 +91,20 @@ class TypeTranslator:
|
|
|
91
91
|
internal = self._tc2simtype(tc.basetype)
|
|
92
92
|
return sim_type.SimTypePointer(internal).with_arch(self.arch)
|
|
93
93
|
|
|
94
|
-
def _translate_Array(self, tc: typeconsts.Array):
|
|
94
|
+
def _translate_Array(self, tc: typeconsts.Array) -> sim_type.SimTypeArray:
|
|
95
95
|
elem_type = self._tc2simtype(tc.element)
|
|
96
96
|
return sim_type.SimTypeArray(elem_type, length=tc.count).with_arch(self.arch)
|
|
97
97
|
|
|
98
|
-
def _translate_Struct(self, tc):
|
|
98
|
+
def _translate_Struct(self, tc: typeconsts.Struct):
|
|
99
99
|
if tc in self.structs:
|
|
100
100
|
return self.structs[tc]
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
if tc.name:
|
|
103
|
+
name = tc.name
|
|
104
|
+
else:
|
|
105
|
+
name = self.struct_name()
|
|
106
|
+
|
|
107
|
+
s = sim_type.SimStruct({}, name=name).with_arch(self.arch)
|
|
103
108
|
self.structs[tc] = s
|
|
104
109
|
|
|
105
110
|
next_offset = 0
|
|
@@ -117,7 +122,11 @@ class TypeTranslator:
|
|
|
117
122
|
# for now, we replace it with an unsigned char
|
|
118
123
|
translated_type = sim_type.SimTypeChar(signed=False).with_arch(self.arch)
|
|
119
124
|
|
|
120
|
-
|
|
125
|
+
if tc.field_names and offset in tc.field_names:
|
|
126
|
+
field_name = tc.field_names[offset]
|
|
127
|
+
else:
|
|
128
|
+
field_name = f"field_{offset:x}"
|
|
129
|
+
s.fields[field_name] = translated_type
|
|
121
130
|
|
|
122
131
|
if isinstance(translated_type, SimTypeTempRef):
|
|
123
132
|
next_offset = self.arch.bytes + offset
|
|
@@ -3,7 +3,25 @@
|
|
|
3
3
|
All type constants used in type inference. They can be mapped, translated, or rewritten to C-style types.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import Optional
|
|
6
|
+
from typing import List, Optional, Set
|
|
7
|
+
import functools
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def memoize(f):
|
|
11
|
+
@functools.wraps(f)
|
|
12
|
+
def wrapped_repr(self, *args, **kwargs):
|
|
13
|
+
if not kwargs or "memo" not in kwargs:
|
|
14
|
+
memo = set()
|
|
15
|
+
else:
|
|
16
|
+
memo = kwargs.pop("memo")
|
|
17
|
+
if self in memo:
|
|
18
|
+
return "..."
|
|
19
|
+
memo.add(self)
|
|
20
|
+
r = f(self, *args, memo=memo, **kwargs)
|
|
21
|
+
memo.remove(self)
|
|
22
|
+
return r
|
|
23
|
+
|
|
24
|
+
return wrapped_repr
|
|
7
25
|
|
|
8
26
|
|
|
9
27
|
class TypeConstant:
|
|
@@ -12,11 +30,14 @@ class TypeConstant:
|
|
|
12
30
|
def pp_str(self, mapping) -> str: # pylint:disable=unused-argument
|
|
13
31
|
return repr(self)
|
|
14
32
|
|
|
33
|
+
def _hash(self, visited: Set[int]): # pylint:disable=unused-argument
|
|
34
|
+
return hash(type(self))
|
|
35
|
+
|
|
15
36
|
def __eq__(self, other):
|
|
16
|
-
return type(self)
|
|
37
|
+
return type(self) is type(other)
|
|
17
38
|
|
|
18
39
|
def __hash__(self):
|
|
19
|
-
return
|
|
40
|
+
return self._hash(set())
|
|
20
41
|
|
|
21
42
|
@property
|
|
22
43
|
def size(self) -> int:
|
|
@@ -24,19 +45,22 @@ class TypeConstant:
|
|
|
24
45
|
raise NotImplementedError()
|
|
25
46
|
return self.SIZE
|
|
26
47
|
|
|
48
|
+
def __repr__(self, memo=None):
|
|
49
|
+
raise NotImplementedError()
|
|
50
|
+
|
|
27
51
|
|
|
28
52
|
class TopType(TypeConstant):
|
|
29
|
-
def __repr__(self):
|
|
53
|
+
def __repr__(self, memo=None):
|
|
30
54
|
return "TOP"
|
|
31
55
|
|
|
32
56
|
|
|
33
57
|
class BottomType(TypeConstant):
|
|
34
|
-
def __repr__(self):
|
|
58
|
+
def __repr__(self, memo=None):
|
|
35
59
|
return "BOT"
|
|
36
60
|
|
|
37
61
|
|
|
38
62
|
class Int(TypeConstant):
|
|
39
|
-
def __repr__(self):
|
|
63
|
+
def __repr__(self, memo=None):
|
|
40
64
|
return "intbase"
|
|
41
65
|
|
|
42
66
|
|
|
@@ -47,81 +71,88 @@ class Int1(Int):
|
|
|
47
71
|
class Int8(Int):
|
|
48
72
|
SIZE = 1
|
|
49
73
|
|
|
50
|
-
def __repr__(self):
|
|
74
|
+
def __repr__(self, memo=None):
|
|
51
75
|
return "int8"
|
|
52
76
|
|
|
53
77
|
|
|
54
78
|
class Int16(Int):
|
|
55
79
|
SIZE = 2
|
|
56
80
|
|
|
57
|
-
def __repr__(self):
|
|
81
|
+
def __repr__(self, memo=None):
|
|
58
82
|
return "int16"
|
|
59
83
|
|
|
60
84
|
|
|
61
85
|
class Int32(Int):
|
|
62
86
|
SIZE = 4
|
|
63
87
|
|
|
64
|
-
def __repr__(self):
|
|
88
|
+
def __repr__(self, memo=None):
|
|
65
89
|
return "int32"
|
|
66
90
|
|
|
67
91
|
|
|
68
92
|
class Int64(Int):
|
|
69
93
|
SIZE = 8
|
|
70
94
|
|
|
71
|
-
def __repr__(self):
|
|
95
|
+
def __repr__(self, memo=None):
|
|
72
96
|
return "int64"
|
|
73
97
|
|
|
74
98
|
|
|
75
99
|
class Int128(Int):
|
|
76
100
|
SIZE = 16
|
|
77
101
|
|
|
78
|
-
def __repr__(self):
|
|
102
|
+
def __repr__(self, memo=None):
|
|
79
103
|
return "int128"
|
|
80
104
|
|
|
81
105
|
|
|
82
106
|
class FloatBase(TypeConstant):
|
|
83
|
-
def __repr__(self):
|
|
107
|
+
def __repr__(self, memo=None):
|
|
84
108
|
return "floatbase"
|
|
85
109
|
|
|
86
110
|
|
|
87
111
|
class Float(FloatBase):
|
|
88
112
|
SIZE = 4
|
|
89
113
|
|
|
90
|
-
def __repr__(self):
|
|
114
|
+
def __repr__(self, memo=None):
|
|
91
115
|
return "float"
|
|
92
116
|
|
|
93
117
|
|
|
94
118
|
class Double(FloatBase):
|
|
95
119
|
SIZE = 8
|
|
96
120
|
|
|
97
|
-
def __repr__(self):
|
|
121
|
+
def __repr__(self, memo=None):
|
|
98
122
|
return "double"
|
|
99
123
|
|
|
100
124
|
|
|
101
125
|
class Pointer(TypeConstant):
|
|
102
|
-
def __init__(self, basetype):
|
|
103
|
-
self.basetype = basetype
|
|
126
|
+
def __init__(self, basetype: Optional[TypeConstant]):
|
|
127
|
+
self.basetype: Optional[TypeConstant] = basetype
|
|
104
128
|
|
|
105
129
|
def __eq__(self, other):
|
|
106
130
|
return type(self) is type(other) and self.basetype == other.basetype
|
|
107
131
|
|
|
108
|
-
def
|
|
109
|
-
|
|
132
|
+
def _hash(self, visited: Set[int]):
|
|
133
|
+
if self.basetype is None:
|
|
134
|
+
return hash(type(self))
|
|
135
|
+
return hash((type(self), self.basetype._hash(visited)))
|
|
110
136
|
|
|
111
137
|
def new(self, basetype):
|
|
112
138
|
return self.__class__(basetype)
|
|
113
139
|
|
|
140
|
+
def __hash__(self):
|
|
141
|
+
return self._hash(set())
|
|
142
|
+
|
|
114
143
|
|
|
115
144
|
class Pointer32(Pointer, Int32):
|
|
116
145
|
"""
|
|
117
146
|
32-bit pointers.
|
|
118
147
|
"""
|
|
119
148
|
|
|
120
|
-
def __init__(self, basetype):
|
|
149
|
+
def __init__(self, basetype=None):
|
|
121
150
|
Pointer.__init__(self, basetype)
|
|
122
151
|
|
|
123
|
-
|
|
124
|
-
|
|
152
|
+
@memoize
|
|
153
|
+
def __repr__(self, memo=None):
|
|
154
|
+
bt = self.basetype.__repr__(memo=memo) if isinstance(self.basetype, TypeConstant) else repr(self.basetype)
|
|
155
|
+
return f"ptr32({bt})"
|
|
125
156
|
|
|
126
157
|
|
|
127
158
|
class Pointer64(Pointer, Int64):
|
|
@@ -129,19 +160,22 @@ class Pointer64(Pointer, Int64):
|
|
|
129
160
|
64-bit pointers.
|
|
130
161
|
"""
|
|
131
162
|
|
|
132
|
-
def __init__(self, basetype):
|
|
163
|
+
def __init__(self, basetype=None):
|
|
133
164
|
Pointer.__init__(self, basetype)
|
|
134
165
|
|
|
135
|
-
|
|
136
|
-
|
|
166
|
+
@memoize
|
|
167
|
+
def __repr__(self, memo=None):
|
|
168
|
+
bt = self.basetype.__repr__(memo=memo) if isinstance(self.basetype, TypeConstant) else repr(self.basetype)
|
|
169
|
+
return f"ptr64({bt})"
|
|
137
170
|
|
|
138
171
|
|
|
139
172
|
class Array(TypeConstant):
|
|
140
|
-
def __init__(self, element, count=None):
|
|
141
|
-
self.element: TypeConstant = element
|
|
173
|
+
def __init__(self, element=None, count=None):
|
|
174
|
+
self.element: Optional[TypeConstant] = element
|
|
142
175
|
self.count: Optional[int] = count
|
|
143
176
|
|
|
144
|
-
|
|
177
|
+
@memoize
|
|
178
|
+
def __repr__(self, memo=None):
|
|
145
179
|
if self.count is None:
|
|
146
180
|
return "%r[?]" % self.element
|
|
147
181
|
else:
|
|
@@ -150,34 +184,81 @@ class Array(TypeConstant):
|
|
|
150
184
|
def __eq__(self, other):
|
|
151
185
|
return type(other) is type(self) and self.element == other.element and self.count == other.count
|
|
152
186
|
|
|
153
|
-
def
|
|
187
|
+
def _hash(self, visited: Set[int]):
|
|
188
|
+
if id(self) in visited:
|
|
189
|
+
return 0
|
|
190
|
+
visited.add(id(self))
|
|
154
191
|
return hash((type(self), self.element, self.count))
|
|
155
192
|
|
|
193
|
+
def __hash__(self):
|
|
194
|
+
return self._hash(set())
|
|
195
|
+
|
|
156
196
|
|
|
157
197
|
class Struct(TypeConstant):
|
|
158
|
-
def __init__(self, fields=None):
|
|
198
|
+
def __init__(self, fields=None, name=None, field_names=None):
|
|
159
199
|
self.fields = {} if fields is None else fields # offset to type
|
|
200
|
+
self.name = name
|
|
201
|
+
self.field_names = field_names
|
|
202
|
+
|
|
203
|
+
def _hash(self, visited: Set[int]):
|
|
204
|
+
if id(self) in visited:
|
|
205
|
+
return 0
|
|
206
|
+
visited.add(id(self))
|
|
207
|
+
return hash((type(self), self._hash_fields(visited)))
|
|
160
208
|
|
|
161
|
-
def _hash_fields(self):
|
|
209
|
+
def _hash_fields(self, visited: Set[int]):
|
|
162
210
|
keys = sorted(self.fields.keys())
|
|
163
|
-
tpl = tuple((k, self.fields[k]) for k in keys)
|
|
211
|
+
tpl = tuple((k, self.fields[k]._hash(visited)) for k in keys)
|
|
164
212
|
return hash(tpl)
|
|
165
213
|
|
|
166
|
-
|
|
167
|
-
|
|
214
|
+
@memoize
|
|
215
|
+
def __repr__(self, memo=None):
|
|
216
|
+
prefix = "struct"
|
|
217
|
+
if self.name:
|
|
218
|
+
prefix = f"struct {self.name}"
|
|
219
|
+
return prefix + "{" + ", ".join(f"{k}:{v.__repr__(memo=memo)}" for k, v in self.fields.items()) + "}"
|
|
220
|
+
|
|
221
|
+
def __eq__(self, other):
|
|
222
|
+
return type(other) is type(self) and hash(self) == hash(other)
|
|
223
|
+
|
|
224
|
+
def __hash__(self):
|
|
225
|
+
return self._hash(set())
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class Function(TypeConstant):
|
|
229
|
+
def __init__(self, params: List, outputs: List):
|
|
230
|
+
self.params = params
|
|
231
|
+
self.outputs = outputs
|
|
232
|
+
|
|
233
|
+
@memoize
|
|
234
|
+
def __repr__(self, memo=None):
|
|
235
|
+
param_str = ", ".join(repr(param) for param in self.params)
|
|
236
|
+
outputs_str = ", ".join(repr(output) for output in self.outputs)
|
|
237
|
+
return f"func({param_str}) -> {outputs_str}"
|
|
168
238
|
|
|
169
239
|
def __eq__(self, other):
|
|
170
|
-
|
|
240
|
+
if not isinstance(other, Function):
|
|
241
|
+
return False
|
|
242
|
+
return self.params == other.params and self.outputs == other.outputs
|
|
243
|
+
|
|
244
|
+
def _hash(self, visited: Set[int]):
|
|
245
|
+
if id(self) in visited:
|
|
246
|
+
return 0
|
|
247
|
+
visited.add(id(self))
|
|
248
|
+
|
|
249
|
+
params_hash = tuple(param._hash(visited) for param in self.params)
|
|
250
|
+
outputs_hash = tuple(out._hash(visited) for out in self.outputs)
|
|
251
|
+
return hash((Function, params_hash, outputs_hash))
|
|
171
252
|
|
|
172
253
|
def __hash__(self):
|
|
173
|
-
return
|
|
254
|
+
return self._hash(set())
|
|
174
255
|
|
|
175
256
|
|
|
176
257
|
class TypeVariableReference(TypeConstant):
|
|
177
258
|
def __init__(self, typevar):
|
|
178
259
|
self.typevar = typevar
|
|
179
260
|
|
|
180
|
-
def __repr__(self):
|
|
261
|
+
def __repr__(self, memo=None):
|
|
181
262
|
return "ref(%s)" % self.typevar
|
|
182
263
|
|
|
183
264
|
def __eq__(self, other):
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
# pylint:disable=bad-builtin
|
|
1
2
|
from typing import List, Set, Optional, Dict, Union, TYPE_CHECKING
|
|
2
3
|
|
|
3
4
|
from ...sim_type import SimStruct, SimTypePointer, SimTypeArray
|
|
4
5
|
from ..analysis import Analysis, AnalysesHub
|
|
5
6
|
from .simple_solver import SimpleSolver
|
|
6
7
|
from .translator import TypeTranslator
|
|
7
|
-
from .typeconsts import Struct, Pointer, TypeConstant, Array
|
|
8
|
-
from .typevars import Equivalence
|
|
8
|
+
from .typeconsts import Struct, Pointer, TypeConstant, Array, TopType
|
|
9
|
+
from .typevars import Equivalence, Subtype, TypeVariable
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
12
|
from angr.sim_variable import SimVariable
|
|
12
13
|
from angr.sim_type import SimType
|
|
13
|
-
from .typevars import
|
|
14
|
+
from .typevars import TypeConstraint
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class Typehoon(Analysis):
|
|
@@ -30,6 +31,7 @@ class Typehoon(Analysis):
|
|
|
30
31
|
def __init__(
|
|
31
32
|
self,
|
|
32
33
|
constraints,
|
|
34
|
+
func_var,
|
|
33
35
|
ground_truth=None,
|
|
34
36
|
var_mapping: Optional[Dict["SimVariable", Set["TypeVariable"]]] = None,
|
|
35
37
|
must_struct: Optional[Set["TypeVariable"]] = None,
|
|
@@ -43,9 +45,10 @@ class Typehoon(Analysis):
|
|
|
43
45
|
:param must_struct:
|
|
44
46
|
"""
|
|
45
47
|
|
|
46
|
-
self.
|
|
48
|
+
self.func_var: "TypeVariable" = func_var
|
|
49
|
+
self._constraints: Dict["TypeVariable", Set["TypeConstraint"]] = constraints
|
|
47
50
|
self._ground_truth: Optional[Dict["TypeVariable", "SimType"]] = ground_truth
|
|
48
|
-
self._var_mapping = var_mapping
|
|
51
|
+
self._var_mapping = var_mapping
|
|
49
52
|
self._must_struct = must_struct
|
|
50
53
|
|
|
51
54
|
self.bits = self.project.arch.bits
|
|
@@ -95,9 +98,11 @@ class Typehoon(Analysis):
|
|
|
95
98
|
for tv in typevars:
|
|
96
99
|
typevar_to_var[tv] = k
|
|
97
100
|
|
|
98
|
-
print(f"### {len
|
|
99
|
-
for
|
|
100
|
-
print("
|
|
101
|
+
print(f"### {sum(map(len, self._constraints.values()))} constraints")
|
|
102
|
+
for func_var in self._constraints:
|
|
103
|
+
print(f"{func_var}:")
|
|
104
|
+
for constraint in self._constraints[func_var]:
|
|
105
|
+
print(" " + constraint.pp_str(typevar_to_var))
|
|
101
106
|
print("### end of constraints ###")
|
|
102
107
|
|
|
103
108
|
def pp_solution(self) -> None:
|
|
@@ -133,7 +138,7 @@ class Typehoon(Analysis):
|
|
|
133
138
|
if self._ground_truth:
|
|
134
139
|
translator = TypeTranslator(arch=self.project.arch)
|
|
135
140
|
for tv, sim_type in self._ground_truth.items():
|
|
136
|
-
self._constraints.add(Equivalence(tv, translator.simtype2tc(sim_type)))
|
|
141
|
+
self._constraints[self.func_var].add(Equivalence(tv, translator.simtype2tc(sim_type)))
|
|
137
142
|
|
|
138
143
|
self._solve()
|
|
139
144
|
self._specialize()
|
|
@@ -144,7 +149,19 @@ class Typehoon(Analysis):
|
|
|
144
149
|
self.simtypes_solution.update(self._ground_truth)
|
|
145
150
|
|
|
146
151
|
def _solve(self):
|
|
147
|
-
|
|
152
|
+
typevars = set()
|
|
153
|
+
if self._var_mapping:
|
|
154
|
+
for variable_typevars in self._var_mapping.values():
|
|
155
|
+
typevars |= variable_typevars
|
|
156
|
+
else:
|
|
157
|
+
# collect type variables from constraints
|
|
158
|
+
for constraint in self._constraints[self.func_var]:
|
|
159
|
+
if isinstance(constraint, Subtype):
|
|
160
|
+
if isinstance(constraint.sub_type, TypeVariable):
|
|
161
|
+
typevars.add(constraint.sub_type)
|
|
162
|
+
if isinstance(constraint.super_type, TypeVariable):
|
|
163
|
+
typevars.add(constraint.super_type)
|
|
164
|
+
solver = SimpleSolver(self.bits, self._constraints, typevars)
|
|
148
165
|
self.solution = solver.solution
|
|
149
166
|
|
|
150
167
|
def _specialize(self):
|
|
@@ -189,7 +206,10 @@ class Typehoon(Analysis):
|
|
|
189
206
|
if all(off % alignment == 0 for off in offsets):
|
|
190
207
|
# yeah!
|
|
191
208
|
max_offset = offsets[-1]
|
|
192
|
-
|
|
209
|
+
field0_size = 1
|
|
210
|
+
if not isinstance(field0, TopType):
|
|
211
|
+
field0_size = field0.size
|
|
212
|
+
count = (max_offset + field0_size) // alignment
|
|
193
213
|
return Array(field0, count=count)
|
|
194
214
|
|
|
195
215
|
return None
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
# pylint:disable=missing-class-docstring
|
|
2
|
-
from typing import Dict, Any, Optional, Set, TYPE_CHECKING
|
|
2
|
+
from typing import Dict, Any, Optional, Set, Iterable, Tuple, Union, TYPE_CHECKING
|
|
3
3
|
from itertools import count
|
|
4
4
|
|
|
5
|
+
from angr.utils.constants import MAX_POINTSTO_BITS
|
|
6
|
+
from .variance import Variance
|
|
7
|
+
|
|
5
8
|
if TYPE_CHECKING:
|
|
6
9
|
from angr.sim_variable import SimVariable
|
|
10
|
+
from .typeconsts import TypeConstant
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
# Type variables and constraints
|
|
10
14
|
|
|
15
|
+
TypeType = Union["TypeConstant", "TypeVariable", "DerivedTypeVariable"]
|
|
16
|
+
|
|
11
17
|
|
|
12
18
|
class TypeConstraint:
|
|
13
19
|
__slots__ = ()
|
|
@@ -79,7 +85,7 @@ class Subtype(TypeConstraint):
|
|
|
79
85
|
"sub_type",
|
|
80
86
|
)
|
|
81
87
|
|
|
82
|
-
def __init__(self, sub_type, super_type):
|
|
88
|
+
def __init__(self, sub_type: TypeType, super_type: TypeType):
|
|
83
89
|
self.super_type = super_type
|
|
84
90
|
self.sub_type = sub_type
|
|
85
91
|
|
|
@@ -272,52 +278,103 @@ _typevariable_counter = count()
|
|
|
272
278
|
|
|
273
279
|
|
|
274
280
|
class TypeVariable:
|
|
275
|
-
__slots__ = ("idx",)
|
|
281
|
+
__slots__ = ("idx", "name")
|
|
276
282
|
|
|
277
|
-
def __init__(self, idx: Optional[int] = None):
|
|
283
|
+
def __init__(self, idx: Optional[int] = None, name: Optional[str] = None):
|
|
278
284
|
if idx is None:
|
|
279
285
|
self.idx: int = next(_typevariable_counter)
|
|
280
286
|
else:
|
|
281
287
|
self.idx: int = idx
|
|
288
|
+
self.name = name
|
|
282
289
|
|
|
283
290
|
def pp_str(self, mapping: Dict["TypeVariable", Any]) -> str:
|
|
284
|
-
varname = mapping.get(self,
|
|
291
|
+
varname = mapping.get(self, self.name)
|
|
285
292
|
if varname is None:
|
|
286
293
|
return repr(self)
|
|
287
294
|
return f"{varname} ({repr(self)})"
|
|
288
295
|
|
|
289
296
|
def __eq__(self, other):
|
|
290
|
-
|
|
297
|
+
if type(other) is not TypeVariable:
|
|
298
|
+
return False
|
|
299
|
+
if self.name or other.name:
|
|
300
|
+
return self.name == other.name
|
|
301
|
+
return self.idx == other.idx
|
|
302
|
+
|
|
303
|
+
def _hash(self, visited=None): # pylint:disable=unused-argument
|
|
304
|
+
if self.name:
|
|
305
|
+
return hash((TypeVariable, self.name))
|
|
306
|
+
return hash((TypeVariable, self.idx))
|
|
291
307
|
|
|
292
308
|
def __hash__(self):
|
|
293
|
-
return
|
|
309
|
+
return self._hash()
|
|
294
310
|
|
|
295
311
|
def __repr__(self):
|
|
312
|
+
if self.name:
|
|
313
|
+
return f"{self.name}|tv_{self.idx:02d}"
|
|
296
314
|
return "tv_%02d" % self.idx
|
|
297
315
|
|
|
298
316
|
|
|
299
317
|
class DerivedTypeVariable(TypeVariable):
|
|
300
|
-
__slots__ = (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
)
|
|
318
|
+
__slots__ = ("type_var", "labels")
|
|
319
|
+
|
|
320
|
+
type_var: Union[TypeVariable, "TypeConstant"]
|
|
304
321
|
|
|
305
|
-
def __init__(
|
|
322
|
+
def __init__(
|
|
323
|
+
self,
|
|
324
|
+
type_var: Optional[Union[TypeVariable, "DerivedTypeVariable"]],
|
|
325
|
+
label,
|
|
326
|
+
labels: Optional[Iterable["BaseLabel"]] = None,
|
|
327
|
+
idx=None,
|
|
328
|
+
):
|
|
306
329
|
super().__init__(idx=idx)
|
|
307
|
-
|
|
308
|
-
|
|
330
|
+
if isinstance(type_var, DerivedTypeVariable):
|
|
331
|
+
existing_labels = type_var.labels
|
|
332
|
+
self.type_var = type_var.type_var
|
|
333
|
+
assert not isinstance(self.type_var, DerivedTypeVariable)
|
|
334
|
+
else:
|
|
335
|
+
existing_labels = ()
|
|
336
|
+
self.type_var = type_var
|
|
337
|
+
|
|
338
|
+
if label is not None and labels:
|
|
339
|
+
raise TypeError("You cannot specify both label and labels at the same time")
|
|
340
|
+
|
|
341
|
+
if label is not None:
|
|
342
|
+
self.labels = existing_labels + (label,)
|
|
343
|
+
else:
|
|
344
|
+
self.labels: Tuple["BaseLabel"] = existing_labels + tuple(labels)
|
|
345
|
+
|
|
346
|
+
if not self.labels:
|
|
347
|
+
raise ValueError("A DerivedTypeVariable must have at least one label")
|
|
348
|
+
|
|
349
|
+
def one_label(self) -> Optional["BaseLabel"]:
|
|
350
|
+
return self.labels[0] if len(self.labels) == 1 else None
|
|
351
|
+
|
|
352
|
+
def path(self) -> Tuple["BaseLabel"]:
|
|
353
|
+
return self.labels
|
|
354
|
+
|
|
355
|
+
def longest_prefix(self) -> Optional[Union[TypeVariable, "DerivedTypeVariable"]]:
|
|
356
|
+
if not self.labels:
|
|
357
|
+
return None
|
|
358
|
+
if len(self.labels) == 1:
|
|
359
|
+
return self.type_var
|
|
360
|
+
return DerivedTypeVariable(self.type_var, None, labels=self.labels[:-1])
|
|
309
361
|
|
|
310
362
|
def pp_str(self, mapping: Dict["TypeVariable", Any]) -> str:
|
|
311
|
-
return
|
|
363
|
+
return ".".join([self.type_var.pp_str(mapping)] + [repr(lbl) for lbl in self.labels])
|
|
312
364
|
|
|
313
365
|
def __eq__(self, other):
|
|
314
|
-
return
|
|
366
|
+
return (
|
|
367
|
+
isinstance(other, DerivedTypeVariable) and self.type_var == other.type_var and self.labels == other.labels
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
def _hash(self, visited=None):
|
|
371
|
+
return hash((DerivedTypeVariable, self.type_var, self.labels))
|
|
315
372
|
|
|
316
373
|
def __hash__(self):
|
|
317
|
-
return
|
|
374
|
+
return self._hash()
|
|
318
375
|
|
|
319
376
|
def __repr__(self):
|
|
320
|
-
return
|
|
377
|
+
return ".".join([repr(self.type_var)] + [repr(lbl) for lbl in self.labels])
|
|
321
378
|
|
|
322
379
|
def replace(self, replacements):
|
|
323
380
|
typevar = None
|
|
@@ -332,7 +389,7 @@ class DerivedTypeVariable(TypeVariable):
|
|
|
332
389
|
|
|
333
390
|
if typevar is not None:
|
|
334
391
|
# replacement has happened
|
|
335
|
-
return True, DerivedTypeVariable(typevar, self.
|
|
392
|
+
return True, DerivedTypeVariable(typevar, None, labels=self.labels, idx=self.idx)
|
|
336
393
|
else:
|
|
337
394
|
return False, self
|
|
338
395
|
|
|
@@ -397,7 +454,11 @@ class BaseLabel:
|
|
|
397
454
|
return type(self) is type(other) and hash(self) == hash(other)
|
|
398
455
|
|
|
399
456
|
def __hash__(self):
|
|
400
|
-
return hash(tuple(getattr(self, k) for k in self.__slots__))
|
|
457
|
+
return hash((type(self),) + tuple(getattr(self, k) for k in self.__slots__))
|
|
458
|
+
|
|
459
|
+
@property
|
|
460
|
+
def variance(self) -> Variance:
|
|
461
|
+
return Variance.COVARIANT
|
|
401
462
|
|
|
402
463
|
|
|
403
464
|
class FuncIn(BaseLabel):
|
|
@@ -433,6 +494,10 @@ class Store(BaseLabel):
|
|
|
433
494
|
def __repr__(self):
|
|
434
495
|
return "store"
|
|
435
496
|
|
|
497
|
+
@property
|
|
498
|
+
def variance(self) -> Variance:
|
|
499
|
+
return Variance.CONTRAVARIANT
|
|
500
|
+
|
|
436
501
|
|
|
437
502
|
class AddN(BaseLabel):
|
|
438
503
|
__slots__ = ("n",)
|
|
@@ -489,7 +554,9 @@ class HasField(BaseLabel):
|
|
|
489
554
|
self.offset = offset
|
|
490
555
|
|
|
491
556
|
def __repr__(self):
|
|
492
|
-
|
|
557
|
+
if self.bits == MAX_POINTSTO_BITS:
|
|
558
|
+
return f"<MAX_POINTSTO_BITS>@{self.offset}"
|
|
559
|
+
return f"<{self.bits} bits>@{self.offset}"
|
|
493
560
|
|
|
494
561
|
|
|
495
562
|
class IsArray(BaseLabel):
|