angr 9.2.101__py3-none-win_amd64.whl → 9.2.103__py3-none-win_amd64.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 +7 -6
- angr/analyses/calling_convention.py +33 -35
- angr/analyses/cdg.py +2 -4
- angr/analyses/cfg/cfb.py +4 -3
- angr/analyses/cfg/cfg_base.py +14 -14
- angr/analyses/cfg/cfg_emulated.py +3 -4
- angr/analyses/cfg/cfg_fast.py +46 -46
- angr/analyses/cfg/cfg_fast_soot.py +1 -2
- angr/analyses/cfg/cfg_job_base.py +2 -2
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +14 -13
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +5 -5
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +3 -3
- angr/analyses/complete_calling_conventions.py +13 -12
- angr/analyses/data_dep/data_dependency_analysis.py +24 -24
- angr/analyses/data_dep/dep_nodes.py +3 -3
- angr/analyses/ddg.py +1 -2
- angr/analyses/decompiler/ail_simplifier.py +35 -34
- angr/analyses/decompiler/block_io_finder.py +20 -20
- angr/analyses/decompiler/block_similarity.py +4 -6
- angr/analyses/decompiler/block_simplifier.py +17 -16
- angr/analyses/decompiler/callsite_maker.py +25 -10
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -3
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +2 -4
- angr/analyses/decompiler/clinic.py +250 -45
- angr/analyses/decompiler/condition_processor.py +15 -8
- angr/analyses/decompiler/decompilation_cache.py +7 -7
- angr/analyses/decompiler/decompilation_options.py +4 -4
- angr/analyses/decompiler/decompiler.py +19 -15
- angr/analyses/decompiler/expression_counters.py +10 -9
- angr/analyses/decompiler/goto_manager.py +2 -4
- angr/analyses/decompiler/graph_region.py +9 -9
- angr/analyses/decompiler/jump_target_collector.py +1 -2
- angr/analyses/decompiler/optimization_passes/__init__.py +4 -3
- angr/analyses/decompiler/optimization_passes/code_motion.py +5 -6
- angr/analyses/decompiler/optimization_passes/const_derefs.py +4 -4
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +73 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +25 -3
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +6 -5
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +3 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +2 -2
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +17 -17
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +12 -13
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +25 -21
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +3 -3
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +1 -2
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +7 -7
- angr/analyses/decompiler/optimization_passes/spilled_register_finder.py +18 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +2 -3
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +1 -2
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/__init__.py +4 -3
- angr/analyses/decompiler/peephole_optimizations/base.py +13 -15
- angr/analyses/decompiler/peephole_optimizations/bswap.py +1 -3
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +72 -0
- angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +1 -2
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +1 -1
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +5 -10
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +3 -4
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +7 -10
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +2 -3
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +1 -2
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +4 -4
- angr/analyses/decompiler/redundant_label_remover.py +4 -5
- angr/analyses/decompiler/region_identifier.py +4 -5
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +1 -2
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +19 -20
- angr/analyses/decompiler/region_simplifiers/goto.py +2 -3
- angr/analyses/decompiler/region_simplifiers/loop.py +1 -2
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +1 -2
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +1 -3
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +19 -19
- angr/analyses/decompiler/return_maker.py +1 -2
- angr/analyses/decompiler/structured_codegen/base.py +5 -6
- angr/analyses/decompiler/structured_codegen/c.py +39 -38
- angr/analyses/decompiler/structuring/__init__.py +1 -1
- angr/analyses/decompiler/structuring/dream.py +17 -16
- angr/analyses/decompiler/structuring/phoenix.py +45 -46
- angr/analyses/decompiler/structuring/recursive_structurer.py +4 -4
- angr/analyses/decompiler/structuring/structurer_base.py +16 -15
- angr/analyses/decompiler/structuring/structurer_nodes.py +10 -9
- angr/analyses/decompiler/utils.py +17 -16
- angr/analyses/disassembly.py +7 -6
- angr/analyses/flirt.py +9 -9
- angr/analyses/forward_analysis/forward_analysis.py +15 -14
- angr/analyses/forward_analysis/visitors/function_graph.py +1 -2
- angr/analyses/forward_analysis/visitors/graph.py +16 -15
- angr/analyses/propagator/engine_ail.py +30 -26
- angr/analyses/propagator/outdated_definition_walker.py +8 -7
- angr/analyses/propagator/propagator.py +11 -13
- angr/analyses/proximity_graph.py +21 -21
- angr/analyses/reaching_definitions/__init__.py +3 -3
- angr/analyses/reaching_definitions/call_trace.py +3 -6
- angr/analyses/reaching_definitions/dep_graph.py +41 -48
- angr/analyses/reaching_definitions/engine_ail.py +11 -5
- angr/analyses/reaching_definitions/engine_vex.py +9 -8
- angr/analyses/reaching_definitions/function_handler.py +51 -34
- angr/analyses/reaching_definitions/heap_allocator.py +3 -4
- angr/analyses/reaching_definitions/rd_initializer.py +8 -8
- angr/analyses/reaching_definitions/rd_state.py +57 -58
- angr/analyses/reaching_definitions/reaching_definitions.py +18 -17
- angr/analyses/reaching_definitions/subject.py +2 -3
- angr/analyses/stack_pointer_tracker.py +15 -6
- angr/analyses/typehoon/dfa.py +4 -4
- angr/analyses/typehoon/simple_solver.py +48 -52
- angr/analyses/typehoon/translator.py +3 -6
- angr/analyses/typehoon/typeconsts.py +13 -14
- angr/analyses/typehoon/typehoon.py +9 -9
- angr/analyses/typehoon/typevars.py +18 -17
- angr/analyses/variable_recovery/engine_ail.py +5 -5
- angr/analyses/variable_recovery/engine_base.py +25 -21
- angr/analyses/variable_recovery/irsb_scanner.py +8 -9
- angr/analyses/variable_recovery/variable_recovery.py +1 -2
- angr/analyses/variable_recovery/variable_recovery_base.py +14 -13
- angr/analyses/variable_recovery/variable_recovery_fast.py +8 -8
- angr/analyses/veritesting.py +1 -2
- angr/analyses/vfg.py +57 -56
- angr/analyses/xrefs.py +1 -2
- angr/angrdb/db.py +7 -7
- angr/angrdb/serializers/kb.py +16 -13
- angr/angrdb/serializers/loader.py +1 -2
- angr/angrdb/serializers/structured_code.py +2 -2
- angr/annocfg.py +1 -2
- angr/block.py +16 -6
- angr/calling_conventions.py +27 -27
- angr/code_location.py +8 -8
- angr/codenode.py +1 -2
- angr/concretization_strategies/max.py +1 -3
- angr/distributed/server.py +1 -3
- angr/distributed/worker.py +1 -2
- angr/engines/engine.py +2 -3
- angr/engines/light/engine.py +4 -4
- angr/engines/pcode/behavior.py +20 -2
- angr/engines/pcode/emulate.py +1 -1
- angr/engines/pcode/engine.py +7 -7
- angr/engines/pcode/lifter.py +78 -77
- angr/engines/vex/claripy/ccall.py +1 -2
- angr/engines/vex/claripy/datalayer.py +1 -2
- angr/engines/vex/light/light.py +1 -2
- angr/exploration_techniques/tracer.py +4 -4
- angr/factory.py +12 -15
- angr/flirt/__init__.py +8 -8
- angr/flirt/build_sig.py +2 -3
- angr/keyed_region.py +2 -2
- angr/knowledge_base/knowledge_base.py +3 -3
- angr/knowledge_plugins/callsite_prototypes.py +4 -6
- angr/knowledge_plugins/cfg/cfg_manager.py +19 -6
- angr/knowledge_plugins/cfg/cfg_model.py +26 -27
- angr/knowledge_plugins/cfg/cfg_node.py +2 -2
- angr/knowledge_plugins/cfg/indirect_jump.py +6 -8
- angr/knowledge_plugins/cfg/memory_data.py +8 -9
- angr/knowledge_plugins/custom_strings.py +1 -3
- angr/knowledge_plugins/debug_variables.py +2 -2
- angr/knowledge_plugins/functions/function.py +21 -22
- angr/knowledge_plugins/functions/function_manager.py +5 -5
- angr/knowledge_plugins/indirect_jumps.py +1 -3
- angr/knowledge_plugins/key_definitions/atoms.py +7 -7
- angr/knowledge_plugins/key_definitions/definition.py +14 -14
- angr/knowledge_plugins/key_definitions/environment.py +5 -7
- angr/knowledge_plugins/key_definitions/heap_address.py +1 -3
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +3 -2
- angr/knowledge_plugins/key_definitions/live_definitions.py +60 -59
- angr/knowledge_plugins/key_definitions/liveness.py +16 -16
- angr/knowledge_plugins/key_definitions/rd_model.py +15 -15
- angr/knowledge_plugins/key_definitions/uses.py +11 -11
- angr/knowledge_plugins/patches.py +4 -8
- angr/knowledge_plugins/propagations/prop_value.py +10 -9
- angr/knowledge_plugins/propagations/propagation_manager.py +3 -5
- angr/knowledge_plugins/propagations/propagation_model.py +9 -9
- angr/knowledge_plugins/propagations/states.py +52 -22
- angr/knowledge_plugins/structured_code/manager.py +2 -2
- angr/knowledge_plugins/sync/sync_controller.py +3 -3
- angr/knowledge_plugins/variables/variable_access.py +4 -4
- angr/knowledge_plugins/variables/variable_manager.py +56 -39
- angr/knowledge_plugins/xrefs/xref.py +9 -11
- angr/knowledge_plugins/xrefs/xref_manager.py +3 -4
- angr/lib/angr_native.dll +0 -0
- angr/misc/ansi.py +1 -2
- angr/misc/autoimport.py +3 -3
- angr/misc/plugins.py +9 -9
- angr/procedures/definitions/__init__.py +16 -16
- angr/procedures/definitions/linux_kernel.py +1 -1
- angr/procedures/definitions/parse_win32json.py +1 -1
- angr/procedures/java_jni/__init__.py +1 -1
- angr/procedures/java_jni/array_operations.py +1 -2
- angr/procedures/java_jni/method_calls.py +1 -2
- angr/procedures/posix/inet_ntoa.py +1 -2
- angr/procedures/stubs/format_parser.py +3 -3
- angr/project.py +13 -11
- angr/sim_manager.py +12 -12
- angr/sim_procedure.py +7 -3
- angr/sim_state.py +2 -2
- angr/sim_type.py +60 -45
- angr/sim_variable.py +5 -5
- angr/simos/simos.py +1 -2
- angr/simos/userland.py +1 -2
- angr/state_plugins/callstack.py +3 -2
- angr/state_plugins/history.py +1 -2
- angr/state_plugins/solver.py +34 -34
- angr/storage/memory_mixins/__init__.py +4 -3
- angr/storage/memory_mixins/actions_mixin.py +1 -3
- angr/storage/memory_mixins/address_concretization_mixin.py +1 -3
- angr/storage/memory_mixins/convenient_mappings_mixin.py +3 -4
- angr/storage/memory_mixins/default_filler_mixin.py +1 -1
- angr/storage/memory_mixins/label_merger_mixin.py +2 -2
- angr/storage/memory_mixins/multi_value_merger_mixin.py +4 -3
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +9 -8
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +12 -11
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +8 -8
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +2 -3
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +10 -11
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +11 -10
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +18 -17
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +12 -11
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +3 -3
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +3 -2
- angr/storage/memory_mixins/regioned_memory/region_data.py +1 -2
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +2 -2
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +3 -3
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +18 -21
- angr/storage/memory_mixins/size_resolution_mixin.py +1 -2
- angr/storage/memory_mixins/symbolic_merger_mixin.py +3 -2
- angr/storage/memory_mixins/top_merger_mixin.py +3 -2
- angr/storage/memory_object.py +2 -4
- angr/utils/algo.py +3 -2
- angr/utils/dynamic_dictlist.py +5 -5
- angr/utils/formatting.py +4 -4
- angr/utils/funcid.py +1 -2
- angr/utils/graph.py +5 -6
- angr/utils/library.py +5 -5
- angr/utils/mp.py +5 -4
- angr/utils/segment_list.py +3 -4
- angr/utils/typing.py +3 -2
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/METADATA +9 -11
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/RECORD +240 -237
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/LICENSE +0 -0
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/WHEEL +0 -0
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/entry_points.txt +0 -0
- {angr-9.2.101.dist-info → angr-9.2.103.dist-info}/top_level.txt +0 -0
angr/analyses/disassembly.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections import defaultdict
|
|
3
|
-
from typing import Union,
|
|
3
|
+
from typing import Union, Any
|
|
4
|
+
from collections.abc import Sequence
|
|
4
5
|
|
|
5
6
|
import pyvex
|
|
6
7
|
import archinfo
|
|
@@ -963,11 +964,11 @@ class Disassembly(Analysis):
|
|
|
963
964
|
|
|
964
965
|
def __init__(
|
|
965
966
|
self,
|
|
966
|
-
function:
|
|
967
|
-
ranges:
|
|
967
|
+
function: Function | None = None,
|
|
968
|
+
ranges: Sequence[tuple[int, int]] | None = None,
|
|
968
969
|
thumb: bool = False,
|
|
969
970
|
include_ir: bool = False,
|
|
970
|
-
block_bytes:
|
|
971
|
+
block_bytes: bytes | None = None,
|
|
971
972
|
):
|
|
972
973
|
self.raw_result = []
|
|
973
974
|
self.raw_result_map = {
|
|
@@ -1156,7 +1157,7 @@ class Disassembly(Analysis):
|
|
|
1156
1157
|
show_edges: bool = True,
|
|
1157
1158
|
show_addresses: bool = True,
|
|
1158
1159
|
show_bytes: bool = False,
|
|
1159
|
-
ascii_only:
|
|
1160
|
+
ascii_only: bool | None = None,
|
|
1160
1161
|
color: bool = True,
|
|
1161
1162
|
) -> str:
|
|
1162
1163
|
"""
|
|
@@ -1188,7 +1189,7 @@ class Disassembly(Analysis):
|
|
|
1188
1189
|
"format_callback": lambda item, s: ansi_color(s, formatting["colors"].get(type(item), None)),
|
|
1189
1190
|
}
|
|
1190
1191
|
|
|
1191
|
-
def col(item: Any) ->
|
|
1192
|
+
def col(item: Any) -> str | None:
|
|
1192
1193
|
try:
|
|
1193
1194
|
return formatting["colors"][item]
|
|
1194
1195
|
except KeyError:
|
angr/analyses/flirt.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
2
|
from functools import partial
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
import logging
|
|
@@ -30,11 +30,11 @@ class FlirtAnalysis(Analysis):
|
|
|
30
30
|
current binary, and then match all possible signatures for the architecture.
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
def __init__(self, sig:
|
|
33
|
+
def __init__(self, sig: FlirtSignature | str | None = None):
|
|
34
34
|
self._is_arm = is_arm_arch(self.project.arch)
|
|
35
|
-
self._all_suggestions:
|
|
36
|
-
self._suggestions:
|
|
37
|
-
self.matched_suggestions:
|
|
35
|
+
self._all_suggestions: dict[str, dict[str, dict[int, str]]] = {}
|
|
36
|
+
self._suggestions: dict[int, str] = {}
|
|
37
|
+
self.matched_suggestions: dict[str, tuple[FlirtSignature, dict[int, str]]] = {}
|
|
38
38
|
self._temporary_sig = False
|
|
39
39
|
|
|
40
40
|
if sig:
|
|
@@ -64,7 +64,7 @@ class FlirtAnalysis(Analysis):
|
|
|
64
64
|
self.signatures = list(self._find_hits_by_strings(mem_regions))
|
|
65
65
|
_l.debug("Identified %d signatures to apply.", len(self.signatures))
|
|
66
66
|
|
|
67
|
-
path_to_sig:
|
|
67
|
+
path_to_sig: dict[str, FlirtSignature] = {}
|
|
68
68
|
for sig_ in self.signatures:
|
|
69
69
|
self._match_all_against_one_signature(sig_)
|
|
70
70
|
if sig_.sig_name not in self._all_suggestions:
|
|
@@ -90,8 +90,8 @@ class FlirtAnalysis(Analysis):
|
|
|
90
90
|
)
|
|
91
91
|
self.matched_suggestions[lib] = (sig_, sig_to_suggestions[max_suggestion_sig_path])
|
|
92
92
|
|
|
93
|
-
def _find_hits_by_strings(self, regions:
|
|
94
|
-
library_hits:
|
|
93
|
+
def _find_hits_by_strings(self, regions: list[bytes]) -> list[FlirtSignature]:
|
|
94
|
+
library_hits: dict[str, int] = defaultdict(int)
|
|
95
95
|
for s, libs in STRING_TO_LIBRARIES.items():
|
|
96
96
|
for region in regions:
|
|
97
97
|
if s.encode("ascii") in region:
|
|
@@ -173,7 +173,7 @@ class FlirtAnalysis(Analysis):
|
|
|
173
173
|
func_name = f"unknown_function_{func.addr:x}"
|
|
174
174
|
self._suggestions[func.addr] = func_name
|
|
175
175
|
|
|
176
|
-
def _apply_changes(self, library_name:
|
|
176
|
+
def _apply_changes(self, library_name: str | None, suggestion: dict[int, str]) -> None:
|
|
177
177
|
for func_addr, suggested_name in suggestion.items():
|
|
178
178
|
func = self.kb.functions.get_by_addr(func_addr)
|
|
179
179
|
func.name = suggested_name
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, Optional, Generic, TypeVar, TYPE_CHECKING
|
|
3
|
+
from collections.abc import Callable
|
|
3
4
|
|
|
4
5
|
import networkx
|
|
5
6
|
|
|
@@ -41,7 +42,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
41
42
|
order_jobs=False,
|
|
42
43
|
allow_merging=False,
|
|
43
44
|
allow_widening=False,
|
|
44
|
-
status_callback:
|
|
45
|
+
status_callback: Callable[[type["ForwardAnalysis"]], Any] | None = None,
|
|
45
46
|
graph_visitor: "Optional[GraphVisitor[NodeType]]" = None,
|
|
46
47
|
):
|
|
47
48
|
"""
|
|
@@ -69,15 +70,15 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
69
70
|
self._should_abort = False
|
|
70
71
|
|
|
71
72
|
# All remaining jobs
|
|
72
|
-
self._job_info_queue:
|
|
73
|
+
self._job_info_queue: list[JobInfo[JobType, JobKey]] = []
|
|
73
74
|
|
|
74
75
|
# A map between job key to job. Jobs with the same key will be merged by calling _merge_jobs()
|
|
75
|
-
self._job_map:
|
|
76
|
+
self._job_map: dict[JobKey, JobInfo[JobType, JobKey]] = {}
|
|
76
77
|
|
|
77
78
|
# A mapping between node and its input states
|
|
78
|
-
self._input_states:
|
|
79
|
+
self._input_states: dict[NodeType, list[AnalysisState]] = defaultdict(list)
|
|
79
80
|
# A mapping between node and its output state
|
|
80
|
-
self._output_state:
|
|
81
|
+
self._output_state: dict[NodeType, AnalysisState] = {}
|
|
81
82
|
|
|
82
83
|
# The graph!
|
|
83
84
|
# Analysis results (nodes) are stored here
|
|
@@ -149,16 +150,16 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
149
150
|
def _job_key(self, job: JobType) -> JobKey:
|
|
150
151
|
raise NotImplementedError("_job_key() is not implemented.")
|
|
151
152
|
|
|
152
|
-
def _get_successors(self, job: JobType) ->
|
|
153
|
+
def _get_successors(self, job: JobType) -> list[SimState] | list[JobType]:
|
|
153
154
|
raise NotImplementedError("_get_successors() is not implemented.")
|
|
154
155
|
|
|
155
156
|
def _pre_job_handling(self, job: JobType) -> None:
|
|
156
157
|
raise NotImplementedError("_pre_job_handling() is not implemented.")
|
|
157
158
|
|
|
158
|
-
def _post_job_handling(self, job: JobType, new_jobs, successors:
|
|
159
|
+
def _post_job_handling(self, job: JobType, new_jobs, successors: list[SimState]) -> None:
|
|
159
160
|
raise NotImplementedError("_post_job_handling() is not implemented.")
|
|
160
161
|
|
|
161
|
-
def _handle_successor(self, job: JobType, successor: SimState, successors:
|
|
162
|
+
def _handle_successor(self, job: JobType, successor: SimState, successors: list[SimState]) -> list[JobType]:
|
|
162
163
|
raise NotImplementedError("_handle_successor() is not implemented.")
|
|
163
164
|
|
|
164
165
|
def _job_queue_empty(self) -> None:
|
|
@@ -179,7 +180,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
179
180
|
"""
|
|
180
181
|
return node
|
|
181
182
|
|
|
182
|
-
def _run_on_node(self, node: NodeType, state: AnalysisState) ->
|
|
183
|
+
def _run_on_node(self, node: NodeType, state: AnalysisState) -> tuple[bool, AnalysisState]:
|
|
183
184
|
"""
|
|
184
185
|
The analysis routine that runs on each node in the graph.
|
|
185
186
|
|
|
@@ -197,7 +198,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
197
198
|
|
|
198
199
|
raise NotImplementedError("_run_on_node() is not implemented.")
|
|
199
200
|
|
|
200
|
-
def _merge_states(self, node: NodeType, *states: AnalysisState) ->
|
|
201
|
+
def _merge_states(self, node: NodeType, *states: AnalysisState) -> tuple[AnalysisState, bool]:
|
|
201
202
|
"""
|
|
202
203
|
Merge multiple abstract states into one.
|
|
203
204
|
|
|
@@ -311,7 +312,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
311
312
|
for succ in successors_to_visit:
|
|
312
313
|
self._graph_visitor.revisit_node(succ)
|
|
313
314
|
|
|
314
|
-
def _add_input_state(self, node: NodeType, input_state: AnalysisState) ->
|
|
315
|
+
def _add_input_state(self, node: NodeType, input_state: AnalysisState) -> set[NodeType]:
|
|
315
316
|
"""
|
|
316
317
|
Add the input state to all successors of the given node.
|
|
317
318
|
|
|
@@ -334,7 +335,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
334
335
|
|
|
335
336
|
return successors
|
|
336
337
|
|
|
337
|
-
def _get_and_update_input_state(self, node: NodeType) ->
|
|
338
|
+
def _get_and_update_input_state(self, node: NodeType) -> AnalysisState | None:
|
|
338
339
|
"""
|
|
339
340
|
Get the input abstract state for this node, and remove it from the state map.
|
|
340
341
|
|
|
@@ -348,7 +349,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
348
349
|
return input_state
|
|
349
350
|
return None
|
|
350
351
|
|
|
351
|
-
def _get_input_state(self, node: NodeType) ->
|
|
352
|
+
def _get_input_state(self, node: NodeType) -> AnalysisState | None:
|
|
352
353
|
"""
|
|
353
354
|
Get the input abstract state for this node.
|
|
354
355
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from typing import List, Tuple
|
|
2
1
|
import logging
|
|
3
2
|
|
|
4
3
|
import networkx
|
|
@@ -74,7 +73,7 @@ class FunctionGraphVisitor(GraphVisitor):
|
|
|
74
73
|
|
|
75
74
|
return sorted_nodes
|
|
76
75
|
|
|
77
|
-
def back_edges(self) ->
|
|
76
|
+
def back_edges(self) -> list[tuple[NodeType, NodeType]]:
|
|
78
77
|
start_nodes = [node for node in self.graph if node.addr == self.function.addr]
|
|
79
78
|
if not start_nodes:
|
|
80
79
|
start_nodes = [node for node in self.graph if self.graph.in_degree(node) == 0]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from typing import TypeVar, Generic
|
|
1
|
+
from typing import TypeVar, Generic
|
|
2
|
+
from collections.abc import Collection, Iterator
|
|
2
3
|
from collections import defaultdict
|
|
3
4
|
|
|
4
5
|
from ....misc.ux import deprecated
|
|
@@ -25,21 +26,21 @@ class GraphVisitor(Generic[NodeType]):
|
|
|
25
26
|
)
|
|
26
27
|
|
|
27
28
|
def __init__(self):
|
|
28
|
-
self._sorted_nodes:
|
|
29
|
-
self._worklist:
|
|
30
|
-
self._nodes_set:
|
|
31
|
-
self._node_to_index:
|
|
32
|
-
self._reached_fixedpoint:
|
|
33
|
-
self._back_edges_by_src:
|
|
34
|
-
self._back_edges_by_dst:
|
|
29
|
+
self._sorted_nodes: list[NodeType] = [] # a list of sorted nodes. do not change until we get a new graph
|
|
30
|
+
self._worklist: list[NodeType] = [] # a list of nodes that the analysis should work on and finally exhaust
|
|
31
|
+
self._nodes_set: set[NodeType] = set()
|
|
32
|
+
self._node_to_index: dict[NodeType, int] = {}
|
|
33
|
+
self._reached_fixedpoint: set[NodeType] = set()
|
|
34
|
+
self._back_edges_by_src: dict[NodeType, set[NodeType]] | None = None
|
|
35
|
+
self._back_edges_by_dst: dict[NodeType, set[NodeType]] | None = None
|
|
35
36
|
|
|
36
|
-
self._pending_nodes:
|
|
37
|
+
self._pending_nodes: dict[NodeType, set[NodeType]] = defaultdict(set)
|
|
37
38
|
|
|
38
39
|
#
|
|
39
40
|
# Interfaces
|
|
40
41
|
#
|
|
41
42
|
|
|
42
|
-
def successors(self, node: NodeType) ->
|
|
43
|
+
def successors(self, node: NodeType) -> list[NodeType]:
|
|
43
44
|
"""
|
|
44
45
|
Get successors of a node. The node should be in the graph.
|
|
45
46
|
|
|
@@ -50,7 +51,7 @@ class GraphVisitor(Generic[NodeType]):
|
|
|
50
51
|
|
|
51
52
|
raise NotImplementedError()
|
|
52
53
|
|
|
53
|
-
def predecessors(self, node: NodeType) ->
|
|
54
|
+
def predecessors(self, node: NodeType) -> list[NodeType]:
|
|
54
55
|
"""
|
|
55
56
|
Get predecessors of a node. The node should be in the graph.
|
|
56
57
|
|
|
@@ -60,7 +61,7 @@ class GraphVisitor(Generic[NodeType]):
|
|
|
60
61
|
|
|
61
62
|
raise NotImplementedError()
|
|
62
63
|
|
|
63
|
-
def sort_nodes(self, nodes:
|
|
64
|
+
def sort_nodes(self, nodes: Collection[NodeType] | None = None) -> list[NodeType]:
|
|
64
65
|
"""
|
|
65
66
|
Get a list of all nodes sorted in an optimal traversal order.
|
|
66
67
|
|
|
@@ -70,7 +71,7 @@ class GraphVisitor(Generic[NodeType]):
|
|
|
70
71
|
|
|
71
72
|
raise NotImplementedError()
|
|
72
73
|
|
|
73
|
-
def back_edges(self) ->
|
|
74
|
+
def back_edges(self) -> list[tuple[NodeType, NodeType]]:
|
|
74
75
|
"""
|
|
75
76
|
Get a list of back edges. This function is optional. If not overriden, the traverser cannot achieve an optimal
|
|
76
77
|
graph traversal order.
|
|
@@ -122,7 +123,7 @@ class GraphVisitor(Generic[NodeType]):
|
|
|
122
123
|
|
|
123
124
|
self._populate_back_edges()
|
|
124
125
|
|
|
125
|
-
def next_node(self) ->
|
|
126
|
+
def next_node(self) -> NodeType | None:
|
|
126
127
|
"""
|
|
127
128
|
Get the next node to visit.
|
|
128
129
|
|
|
@@ -167,7 +168,7 @@ class GraphVisitor(Generic[NodeType]):
|
|
|
167
168
|
|
|
168
169
|
return node
|
|
169
170
|
|
|
170
|
-
def all_successors(self, node: NodeType, skip_reached_fixedpoint=False) ->
|
|
171
|
+
def all_successors(self, node: NodeType, skip_reached_fixedpoint=False) -> set[NodeType]:
|
|
171
172
|
"""
|
|
172
173
|
Returns all successors to the specific node.
|
|
173
174
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# pylint:disable=arguments-differ,arguments-renamed,isinstance-second-argument-not-valid-type
|
|
2
|
-
from typing import Optional,
|
|
2
|
+
from typing import Optional, TYPE_CHECKING
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
import claripy
|
|
@@ -34,12 +34,12 @@ class SimEnginePropagatorAIL(
|
|
|
34
34
|
|
|
35
35
|
state: "PropagatorAILState"
|
|
36
36
|
|
|
37
|
-
def _is_top(self, expr:
|
|
37
|
+
def _is_top(self, expr: claripy.ast.Base | Expr.StackBaseOffset) -> bool:
|
|
38
38
|
if isinstance(expr, Expr.StackBaseOffset):
|
|
39
39
|
return False
|
|
40
40
|
return super()._is_top(expr)
|
|
41
41
|
|
|
42
|
-
def extract_offset_to_sp(self, expr:
|
|
42
|
+
def extract_offset_to_sp(self, expr: claripy.ast.Base | Expr.StackBaseOffset) -> int | None:
|
|
43
43
|
if isinstance(expr, Expr.StackBaseOffset):
|
|
44
44
|
return expr.offset
|
|
45
45
|
elif isinstance(expr, Expr.Expression):
|
|
@@ -288,7 +288,7 @@ class SimEnginePropagatorAIL(
|
|
|
288
288
|
#
|
|
289
289
|
|
|
290
290
|
# this method exists so that I can annotate the return type
|
|
291
|
-
def _expr(self, expr) ->
|
|
291
|
+
def _expr(self, expr) -> PropValue | None: # pylint:disable=useless-super-delegation
|
|
292
292
|
return super()._expr(expr)
|
|
293
293
|
|
|
294
294
|
def _ail_handle_Tmp(self, expr: Expr.Tmp) -> PropValue:
|
|
@@ -361,7 +361,7 @@ class SimEnginePropagatorAIL(
|
|
|
361
361
|
|
|
362
362
|
return PropValue(self.state.top(expr.size * self.arch.byte_width))
|
|
363
363
|
|
|
364
|
-
def _ail_handle_Register(self, expr: Expr.Register) ->
|
|
364
|
+
def _ail_handle_Register(self, expr: Expr.Register) -> PropValue | None:
|
|
365
365
|
self.state: "PropagatorAILState"
|
|
366
366
|
|
|
367
367
|
# Special handling for SP and BP
|
|
@@ -527,19 +527,19 @@ class SimEnginePropagatorAIL(
|
|
|
527
527
|
bp_as_gpr=self.bp_as_gpr,
|
|
528
528
|
)
|
|
529
529
|
elif all_subexprs and None not in all_subexprs and len(all_subexprs) == 1:
|
|
530
|
-
# if the expression has been replaced before, we should remove previous replacements
|
|
531
|
-
reg_defs = self._reaching_definitions.get_defs(
|
|
532
|
-
Register(expr.reg_offset, expr.size), self._codeloc(), OP_BEFORE
|
|
533
|
-
)
|
|
534
|
-
if len(reg_defs) == 1:
|
|
535
|
-
reg_def = next(iter(reg_defs))
|
|
536
|
-
else:
|
|
537
|
-
reg_def = None
|
|
538
|
-
updated_codelocs = self.state.revert_past_replacements(
|
|
539
|
-
all_subexprs[0], to_replace=expr, to_replace_def=reg_def
|
|
540
|
-
)
|
|
541
|
-
# scan through the code locations and recursively remove assignment replacements
|
|
542
530
|
if self._reaching_definitions is not None:
|
|
531
|
+
# if the expression has been replaced before, we should remove previous replacements
|
|
532
|
+
reg_defs = self._reaching_definitions.get_defs(
|
|
533
|
+
Register(expr.reg_offset, expr.size), self._codeloc(), OP_BEFORE
|
|
534
|
+
)
|
|
535
|
+
if len(reg_defs) == 1:
|
|
536
|
+
reg_def = next(iter(reg_defs))
|
|
537
|
+
else:
|
|
538
|
+
reg_def = None
|
|
539
|
+
updated_codelocs = self.state.revert_past_replacements(
|
|
540
|
+
all_subexprs[0], to_replace=expr, to_replace_def=reg_def
|
|
541
|
+
)
|
|
542
|
+
# scan through the code locations and recursively remove assignment replacements
|
|
543
543
|
while updated_codelocs:
|
|
544
544
|
new_updated_codelocs = set()
|
|
545
545
|
for u_codeloc in updated_codelocs:
|
|
@@ -576,7 +576,7 @@ class SimEnginePropagatorAIL(
|
|
|
576
576
|
|
|
577
577
|
return PropValue.from_value_and_details(self.state.top(expr.bits), expr.size, expr, self._codeloc())
|
|
578
578
|
|
|
579
|
-
def _ail_handle_Load(self, expr: Expr.Load) ->
|
|
579
|
+
def _ail_handle_Load(self, expr: Expr.Load) -> PropValue | None:
|
|
580
580
|
self.state: "PropagatorAILState"
|
|
581
581
|
|
|
582
582
|
addr = self._expr(expr.addr)
|
|
@@ -633,6 +633,11 @@ class SimEnginePropagatorAIL(
|
|
|
633
633
|
def _ail_handle_Convert(self, expr: Expr.Convert) -> PropValue:
|
|
634
634
|
o_value = self._expr(expr.operand)
|
|
635
635
|
|
|
636
|
+
if not (expr.from_type == Expr.Convert.TYPE_INT and expr.to_type == Expr.Convert.TYPE_INT):
|
|
637
|
+
# we do not support floating-point conversions
|
|
638
|
+
new_value = self.state.top(expr.to_bits)
|
|
639
|
+
return PropValue.from_value_and_details(new_value, expr.size, expr, self._codeloc())
|
|
640
|
+
|
|
636
641
|
if o_value is None or self.state.is_top(o_value.value):
|
|
637
642
|
new_value = self.state.top(expr.to_bits)
|
|
638
643
|
else:
|
|
@@ -739,16 +744,14 @@ class SimEnginePropagatorAIL(
|
|
|
739
744
|
v = claripy.BVV(expr.value, expr.bits)
|
|
740
745
|
return PropValue.from_value_and_details(v, expr.size, expr, self._codeloc())
|
|
741
746
|
|
|
742
|
-
def _ail_handle_DirtyExpression(
|
|
743
|
-
self, expr: Expr.DirtyExpression
|
|
744
|
-
) -> Optional[PropValue]: # pylint:disable=no-self-use
|
|
747
|
+
def _ail_handle_DirtyExpression(self, expr: Expr.DirtyExpression) -> PropValue | None: # pylint:disable=no-self-use
|
|
745
748
|
if isinstance(expr.dirty_expr, Expr.VEXCCallExpression):
|
|
746
749
|
for operand in expr.dirty_expr.operands:
|
|
747
750
|
_ = self._expr(operand)
|
|
748
751
|
|
|
749
752
|
return PropValue.from_value_and_details(self.state.top(expr.bits), expr.size, expr, self._codeloc())
|
|
750
753
|
|
|
751
|
-
def _ail_handle_ITE(self, expr: Expr.ITE) ->
|
|
754
|
+
def _ail_handle_ITE(self, expr: Expr.ITE) -> PropValue | None:
|
|
752
755
|
# pylint:disable=unused-variable
|
|
753
756
|
self._expr(expr.cond) # cond
|
|
754
757
|
self._expr(expr.iftrue) # iftrue
|
|
@@ -756,7 +759,7 @@ class SimEnginePropagatorAIL(
|
|
|
756
759
|
|
|
757
760
|
return PropValue.from_value_and_details(self.state.top(expr.bits), expr.size, expr, self._codeloc())
|
|
758
761
|
|
|
759
|
-
def _ail_handle_Reinterpret(self, expr: Expr.Reinterpret) ->
|
|
762
|
+
def _ail_handle_Reinterpret(self, expr: Expr.Reinterpret) -> PropValue | None:
|
|
760
763
|
arg = self._expr(expr.operand)
|
|
761
764
|
|
|
762
765
|
if self.state.is_top(arg.value):
|
|
@@ -768,7 +771,7 @@ class SimEnginePropagatorAIL(
|
|
|
768
771
|
|
|
769
772
|
return PropValue.from_value_and_details(arg.value, expr.size, expr, self._codeloc())
|
|
770
773
|
|
|
771
|
-
def _ail_handle_CallExpr(self, expr_stmt: Stmt.Call) ->
|
|
774
|
+
def _ail_handle_CallExpr(self, expr_stmt: Stmt.Call) -> PropValue | None:
|
|
772
775
|
if isinstance(expr_stmt.target, Expr.Expression):
|
|
773
776
|
_ = self._expr(expr_stmt.target)
|
|
774
777
|
|
|
@@ -847,6 +850,7 @@ class SimEnginePropagatorAIL(
|
|
|
847
850
|
_ail_handle_CmpGTs = _ail_handle_Cmp
|
|
848
851
|
_ail_handle_CmpEQ = _ail_handle_Cmp
|
|
849
852
|
_ail_handle_CmpNE = _ail_handle_Cmp
|
|
853
|
+
_ail_handle_CmpORD = _ail_handle_Cmp
|
|
850
854
|
|
|
851
855
|
def _ail_handle_Add(self, expr: Expr.BinaryOp) -> PropValue:
|
|
852
856
|
o0_value = self._expr(expr.operands[0])
|
|
@@ -1492,8 +1496,8 @@ class SimEnginePropagatorAIL(
|
|
|
1492
1496
|
expr: Expr.Expression,
|
|
1493
1497
|
expr_defat: Optional["CodeLocation"],
|
|
1494
1498
|
current_loc: "CodeLocation",
|
|
1495
|
-
avoid:
|
|
1496
|
-
) ->
|
|
1499
|
+
avoid: Expr.Expression | None = None,
|
|
1500
|
+
) -> tuple[bool, bool]:
|
|
1497
1501
|
if self._reaching_definitions is None:
|
|
1498
1502
|
l.warning(
|
|
1499
1503
|
"Reaching definition information is not provided to propagator. Assume the definition is out-dated."
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# pylint:disable=consider-using-in
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
from collections.abc import Callable
|
|
3
4
|
|
|
4
5
|
from ailment import Block, Stmt, Expr, AILBlockWalker
|
|
5
6
|
|
|
@@ -25,7 +26,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
|
|
|
25
26
|
current_loc: CodeLocation,
|
|
26
27
|
state: "PropagatorAILState",
|
|
27
28
|
arch: "Arch",
|
|
28
|
-
avoid:
|
|
29
|
+
avoid: Expr.Expression | None = None,
|
|
29
30
|
extract_offset_to_sp: Callable = None,
|
|
30
31
|
rda: "ReachingDefinitionsModel" = None,
|
|
31
32
|
):
|
|
@@ -46,13 +47,13 @@ class OutdatedDefinitionWalker(AILBlockWalker):
|
|
|
46
47
|
self.rda = rda
|
|
47
48
|
|
|
48
49
|
# pylint:disable=unused-argument
|
|
49
|
-
def _handle_Tmp(self, expr_idx: int, expr: Expr.Tmp, stmt_idx: int, stmt: Stmt.Assignment, block:
|
|
50
|
+
def _handle_Tmp(self, expr_idx: int, expr: Expr.Tmp, stmt_idx: int, stmt: Stmt.Assignment, block: Block | None):
|
|
50
51
|
if self.avoid is not None and expr.likes(self.avoid):
|
|
51
52
|
self.has_avoid = True
|
|
52
53
|
|
|
53
54
|
# pylint:disable=unused-argument
|
|
54
55
|
def _handle_Register(
|
|
55
|
-
self, expr_idx: int, expr: Expr.Register, stmt_idx: int, stmt: Stmt.Assignment, block:
|
|
56
|
+
self, expr_idx: int, expr: Expr.Register, stmt_idx: int, stmt: Stmt.Assignment, block: Block | None
|
|
56
57
|
):
|
|
57
58
|
if (
|
|
58
59
|
self.avoid is not None
|
|
@@ -70,7 +71,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
|
|
|
70
71
|
if not (codelocs_defat and codelocs_currentloc and codelocs_defat == codelocs_currentloc):
|
|
71
72
|
self.out_dated = True
|
|
72
73
|
|
|
73
|
-
def _handle_Load(self, expr_idx: int, expr: Expr.Load, stmt_idx: int, stmt: Stmt.Statement, block:
|
|
74
|
+
def _handle_Load(self, expr_idx: int, expr: Expr.Load, stmt_idx: int, stmt: Stmt.Statement, block: Block | None):
|
|
74
75
|
if self.avoid is not None and (expr == self.avoid or expr.addr == self.avoid):
|
|
75
76
|
self.has_avoid = True
|
|
76
77
|
|
|
@@ -131,7 +132,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
|
|
|
131
132
|
self.out_dated = True
|
|
132
133
|
|
|
133
134
|
def _handle_VEXCCallExpression(
|
|
134
|
-
self, expr_idx: int, expr: Expr.VEXCCallExpression, stmt_idx: int, stmt: Stmt.Statement, block:
|
|
135
|
+
self, expr_idx: int, expr: Expr.VEXCCallExpression, stmt_idx: int, stmt: Stmt.Statement, block: Block | None
|
|
135
136
|
):
|
|
136
137
|
if self.avoid is not None:
|
|
137
138
|
if any(op == self.avoid for op in expr.operands):
|
|
@@ -148,7 +149,7 @@ class OutdatedDefinitionWalker(AILBlockWalker):
|
|
|
148
149
|
return False
|
|
149
150
|
|
|
150
151
|
@staticmethod
|
|
151
|
-
def _check_store_precedes_load(store_defat:
|
|
152
|
+
def _check_store_precedes_load(store_defat: CodeLocation | None, load_defat: CodeLocation | None) -> bool:
|
|
152
153
|
"""
|
|
153
154
|
Check if store precedes load based on their AIL statement IDs.
|
|
154
155
|
"""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# pylint:disable=isinstance-second-argument-not-valid-type
|
|
2
|
-
from typing import Optional, Any,
|
|
2
|
+
from typing import Optional, Any, TYPE_CHECKING
|
|
3
3
|
import logging
|
|
4
4
|
import time
|
|
5
5
|
|
|
@@ -61,10 +61,10 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
61
61
|
do_binops=True,
|
|
62
62
|
store_tops=True,
|
|
63
63
|
vex_cross_insn_opt=False,
|
|
64
|
-
func_addr:
|
|
65
|
-
gp:
|
|
64
|
+
func_addr: int | None = None,
|
|
65
|
+
gp: int | None = None,
|
|
66
66
|
cache_results: bool = False,
|
|
67
|
-
key_prefix:
|
|
67
|
+
key_prefix: str | None = None,
|
|
68
68
|
reaching_definitions: Optional["ReachingDefinitionsModel"] = None,
|
|
69
69
|
immediate_stmt_removal: bool = False,
|
|
70
70
|
profiling: bool = False,
|
|
@@ -103,7 +103,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
103
103
|
self._cache_results = cache_results
|
|
104
104
|
self._reaching_definitions = reaching_definitions
|
|
105
105
|
self._initial_codeloc: CodeLocation
|
|
106
|
-
self.stmts_to_remove:
|
|
106
|
+
self.stmts_to_remove: set[CodeLocation] = set()
|
|
107
107
|
if self.flavor == "function":
|
|
108
108
|
self._initial_codeloc = CodeLocation(self._func_addr, stmt_idx=0, ins_addr=self._func_addr)
|
|
109
109
|
else: # flavor == "block"
|
|
@@ -124,11 +124,11 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
124
124
|
else:
|
|
125
125
|
cache_used = True
|
|
126
126
|
|
|
127
|
-
graph_visitor:
|
|
127
|
+
graph_visitor: visitors.SingleNodeGraphVisitor | visitors.FunctionGraphVisitor
|
|
128
128
|
if self.flavor == "block":
|
|
129
129
|
graph_visitor = None
|
|
130
130
|
if self._cache_results:
|
|
131
|
-
graph_visitor:
|
|
131
|
+
graph_visitor: visitors.SingleNodeGraphVisitor | None = self.model.graph_visitor
|
|
132
132
|
|
|
133
133
|
if graph_visitor is None:
|
|
134
134
|
graph_visitor = visitors.SingleNodeGraphVisitor(block)
|
|
@@ -136,7 +136,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
136
136
|
elif self.flavor == "function":
|
|
137
137
|
graph_visitor = None
|
|
138
138
|
if self._cache_results:
|
|
139
|
-
graph_visitor:
|
|
139
|
+
graph_visitor: visitors.FunctionGraphVisitor | None = self.model.graph_visitor
|
|
140
140
|
if graph_visitor is not None:
|
|
141
141
|
# resume
|
|
142
142
|
resumed = graph_visitor.resume_with_new_graph(func_graph if func_graph is not None else func.graph)
|
|
@@ -209,7 +209,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
209
209
|
_l.warning(" Analyzed statements: %d", self._analyzed_statements)
|
|
210
210
|
|
|
211
211
|
@property
|
|
212
|
-
def prop_key(self) ->
|
|
212
|
+
def prop_key(self) -> tuple[str | None, str, int, bool, bool, bool]:
|
|
213
213
|
"""
|
|
214
214
|
Gets a key that represents the function and the "flavor" of the propagation result.
|
|
215
215
|
"""
|
|
@@ -228,7 +228,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
228
228
|
# Main analysis routines
|
|
229
229
|
#
|
|
230
230
|
|
|
231
|
-
def _node_key(self, node:
|
|
231
|
+
def _node_key(self, node: ailment.Block | pyvex.IRSB) -> Any:
|
|
232
232
|
if type(node) is ailment.Block:
|
|
233
233
|
return node.addr, node.idx
|
|
234
234
|
elif type(node) is pyvex.IRSB:
|
|
@@ -327,9 +327,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
327
327
|
else:
|
|
328
328
|
return False, state
|
|
329
329
|
|
|
330
|
-
def _process_input_state_for_successor(
|
|
331
|
-
self, node, successor, input_state: Union[PropagatorAILState, PropagatorVEXState]
|
|
332
|
-
):
|
|
330
|
+
def _process_input_state_for_successor(self, node, successor, input_state: PropagatorAILState | PropagatorVEXState):
|
|
333
331
|
if self._only_consts:
|
|
334
332
|
if isinstance(input_state, PropagatorAILState):
|
|
335
333
|
key = node.addr, successor.addr
|