angr 9.2.118__py3-none-manylinux2014_aarch64.whl → 9.2.119__py3-none-manylinux2014_aarch64.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
|
@@ -60,12 +60,12 @@ class InlinedStringTransformationState:
|
|
|
60
60
|
def _get_weakref(self):
|
|
61
61
|
return self
|
|
62
62
|
|
|
63
|
-
def reg_store(self, reg: Register, value: claripy.Bits) -> None:
|
|
63
|
+
def reg_store(self, reg: Register, value: claripy.ast.Bits) -> None:
|
|
64
64
|
self.registers.store(
|
|
65
65
|
reg.reg_offset, value, size=value.size() // self.arch.byte_width, endness=str(self.arch.register_endness)
|
|
66
66
|
)
|
|
67
67
|
|
|
68
|
-
def reg_load(self, reg: Register) -> claripy.Bits | None:
|
|
68
|
+
def reg_load(self, reg: Register) -> claripy.ast.Bits | None:
|
|
69
69
|
try:
|
|
70
70
|
return self.registers.load(
|
|
71
71
|
reg.reg_offset, size=reg.size, endness=self.arch.register_endness, fill_missing=False
|
|
@@ -73,19 +73,19 @@ class InlinedStringTransformationState:
|
|
|
73
73
|
except SimMemoryMissingError:
|
|
74
74
|
return None
|
|
75
75
|
|
|
76
|
-
def mem_store(self, addr: int, value: claripy.Bits, endness: str) -> None:
|
|
76
|
+
def mem_store(self, addr: int, value: claripy.ast.Bits, endness: str) -> None:
|
|
77
77
|
self.memory.store(addr, value, size=value.size() // self.arch.byte_width, endness=endness)
|
|
78
78
|
|
|
79
|
-
def mem_load(self, addr: int, size: int, endness) -> claripy.Bits | None:
|
|
79
|
+
def mem_load(self, addr: int, size: int, endness) -> claripy.ast.Bits | None:
|
|
80
80
|
try:
|
|
81
81
|
return self.memory.load(addr, size=size, endness=str(endness), fill_missing=False)
|
|
82
82
|
except SimMemoryMissingError:
|
|
83
83
|
return None
|
|
84
84
|
|
|
85
|
-
def vvar_store(self, vvar: VirtualVariable, value: claripy.Bits | None) -> None:
|
|
85
|
+
def vvar_store(self, vvar: VirtualVariable, value: claripy.ast.Bits | None) -> None:
|
|
86
86
|
self.virtual_variables[vvar.varid] = value
|
|
87
87
|
|
|
88
|
-
def vvar_load(self, vvar: VirtualVariable) -> claripy.Bits | None:
|
|
88
|
+
def vvar_load(self, vvar: VirtualVariable) -> claripy.ast.Bits | None:
|
|
89
89
|
if vvar.varid in self.virtual_variables:
|
|
90
90
|
return self.virtual_variables[vvar.varid]
|
|
91
91
|
return None
|
|
@@ -109,7 +109,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
109
109
|
self.MASK = 0xFFFF_FFFF if self.arch.bits == 32 else 0xFFFF_FFFF_FFFF_FFFF
|
|
110
110
|
|
|
111
111
|
state = InlinedStringTransformationState(project)
|
|
112
|
-
self.stack_accesses: defaultdict[int, list[tuple[str, CodeLocation, claripy.Bits]]] = defaultdict(list)
|
|
112
|
+
self.stack_accesses: defaultdict[int, list[tuple[str, CodeLocation, claripy.ast.Bits]]] = defaultdict(list)
|
|
113
113
|
self.finished: bool = False
|
|
114
114
|
|
|
115
115
|
i = 0
|
|
@@ -140,7 +140,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
140
140
|
if v0_and_type is not None:
|
|
141
141
|
v0 = v0_and_type[0]
|
|
142
142
|
v1 = self._expr(addr.operands[1])
|
|
143
|
-
if isinstance(v1, claripy.Bits) and v1.concrete:
|
|
143
|
+
if isinstance(v1, claripy.ast.Bits) and v1.concrete:
|
|
144
144
|
return (v0 + v1.concrete_value) & self.MASK, "stack"
|
|
145
145
|
return None
|
|
146
146
|
|
|
@@ -148,7 +148,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
148
148
|
if isinstance(stmt.dst, VirtualVariable):
|
|
149
149
|
if stmt.dst.was_reg:
|
|
150
150
|
val = self._expr(stmt.src)
|
|
151
|
-
if isinstance(val, claripy.Bits):
|
|
151
|
+
if isinstance(val, claripy.ast.Bits):
|
|
152
152
|
self.state.vvar_store(stmt.dst, val)
|
|
153
153
|
elif stmt.dst.was_stack:
|
|
154
154
|
addr = (stmt.dst.stack_offset + self.STACK_BASE) & self.MASK
|
|
@@ -190,9 +190,9 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
190
190
|
if isinstance(stmt.true_target, Const) and isinstance(stmt.false_target, Const):
|
|
191
191
|
cond = self._expr(stmt.condition)
|
|
192
192
|
if cond is not None:
|
|
193
|
-
if isinstance(cond, claripy.Bits) and cond.concrete_value == 1:
|
|
193
|
+
if isinstance(cond, claripy.ast.Bits) and cond.concrete_value == 1:
|
|
194
194
|
self.pc = stmt.true_target.value
|
|
195
|
-
elif isinstance(cond, claripy.Bits) and cond.concrete_value == 0:
|
|
195
|
+
elif isinstance(cond, claripy.ast.Bits) and cond.concrete_value == 0:
|
|
196
196
|
self.pc = stmt.false_target.value
|
|
197
197
|
|
|
198
198
|
def _handle_Const(self, expr):
|
|
@@ -220,7 +220,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
220
220
|
if expr.was_stack:
|
|
221
221
|
addr = (expr.stack_offset + self.STACK_BASE) & self.MASK
|
|
222
222
|
v = self.state.mem_load(addr, expr.size, self.arch.memory_endness)
|
|
223
|
-
if isinstance(v, claripy.Bits):
|
|
223
|
+
if isinstance(v, claripy.ast.Bits):
|
|
224
224
|
# log it
|
|
225
225
|
for i in range(expr.size):
|
|
226
226
|
byte_off = i
|
|
@@ -240,7 +240,7 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
240
240
|
|
|
241
241
|
def _handle_Convert(self, expr: Convert):
|
|
242
242
|
v = self._expr(expr.operand)
|
|
243
|
-
if isinstance(v, claripy.Bits):
|
|
243
|
+
if isinstance(v, claripy.ast.Bits):
|
|
244
244
|
if expr.to_bits > expr.from_bits:
|
|
245
245
|
if not expr.is_signed:
|
|
246
246
|
return claripy.ZeroExt(expr.to_bits - expr.from_bits, v)
|
|
@@ -252,37 +252,37 @@ class InlinedStringTransformationAILEngine(SimEngineLightAILMixin):
|
|
|
252
252
|
|
|
253
253
|
def _handle_CmpEQ(self, expr):
|
|
254
254
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
255
|
-
if isinstance(op0, claripy.Bits) and isinstance(op1, claripy.Bits) and op0.concrete and op1.concrete:
|
|
255
|
+
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
256
256
|
return claripy.BVV(1, 1) if op0.concrete_value == op1.concrete_value else claripy.BVV(0, 1)
|
|
257
257
|
return None
|
|
258
258
|
|
|
259
259
|
def _handle_CmpNE(self, expr):
|
|
260
260
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
261
|
-
if isinstance(op0, claripy.Bits) and isinstance(op1, claripy.Bits) and op0.concrete and op1.concrete:
|
|
261
|
+
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
262
262
|
return claripy.BVV(1, 1) if op0.concrete_value != op1.concrete_value else claripy.BVV(0, 1)
|
|
263
263
|
return None
|
|
264
264
|
|
|
265
265
|
def _handle_CmpLT(self, expr):
|
|
266
266
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
267
|
-
if isinstance(op0, claripy.Bits) and isinstance(op1, claripy.Bits) and op0.concrete and op1.concrete:
|
|
267
|
+
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
268
268
|
return claripy.BVV(1, 1) if op0.concrete_value < op1.concrete_value else claripy.BVV(0, 1)
|
|
269
269
|
return None
|
|
270
270
|
|
|
271
271
|
def _handle_CmpLE(self, expr):
|
|
272
272
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
273
|
-
if isinstance(op0, claripy.Bits) and isinstance(op1, claripy.Bits) and op0.concrete and op1.concrete:
|
|
273
|
+
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
274
274
|
return claripy.BVV(1, 1) if op0.concrete_value <= op1.concrete_value else claripy.BVV(0, 1)
|
|
275
275
|
return None
|
|
276
276
|
|
|
277
277
|
def _handle_CmpGT(self, expr):
|
|
278
278
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
279
|
-
if isinstance(op0, claripy.Bits) and isinstance(op1, claripy.Bits) and op0.concrete and op1.concrete:
|
|
279
|
+
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
280
280
|
return claripy.BVV(1, 1) if op0.concrete_value > op1.concrete_value else claripy.BVV(0, 1)
|
|
281
281
|
return None
|
|
282
282
|
|
|
283
283
|
def _handle_CmpGE(self, expr):
|
|
284
284
|
op0, op1 = self._expr(expr.operands[0]), self._expr(expr.operands[1])
|
|
285
|
-
if isinstance(op0, claripy.Bits) and isinstance(op1, claripy.Bits) and op0.concrete and op1.concrete:
|
|
285
|
+
if isinstance(op0, claripy.ast.Bits) and isinstance(op1, claripy.ast.Bits) and op0.concrete and op1.concrete:
|
|
286
286
|
return claripy.BVV(1, 1) if op0.concrete_value >= op1.concrete_value else claripy.BVV(0, 1)
|
|
287
287
|
return None
|
|
288
288
|
|
|
@@ -31,6 +31,8 @@ from ....sim_type import (
|
|
|
31
31
|
SimTypeLength,
|
|
32
32
|
SimTypeReg,
|
|
33
33
|
dereference_simtype,
|
|
34
|
+
SimTypeInt128,
|
|
35
|
+
SimTypeInt256,
|
|
34
36
|
)
|
|
35
37
|
from ....knowledge_plugins.functions import Function
|
|
36
38
|
from ....sim_variable import SimVariable, SimTemporaryVariable, SimStackVariable, SimMemoryVariable
|
|
@@ -3479,8 +3481,13 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3479
3481
|
|
|
3480
3482
|
def _handle_Expr_Convert(self, expr: Expr.Convert, **kwargs):
|
|
3481
3483
|
# width of converted type is easy
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
+
dst_type: SimTypeInt | SimTypeChar
|
|
3485
|
+
if 258 >= expr.to_bits > 128:
|
|
3486
|
+
dst_type = SimTypeInt256()
|
|
3487
|
+
elif 128 >= expr.to_bits > 64:
|
|
3488
|
+
dst_type = SimTypeInt128()
|
|
3489
|
+
elif 64 >= expr.to_bits > 32:
|
|
3490
|
+
dst_type = SimTypeLongLong()
|
|
3484
3491
|
elif 32 >= expr.to_bits > 16:
|
|
3485
3492
|
dst_type = SimTypeInt()
|
|
3486
3493
|
elif 16 >= expr.to_bits > 8:
|
|
@@ -767,7 +767,7 @@ class DreamStructurer(StructurerBase):
|
|
|
767
767
|
if (
|
|
768
768
|
arg.op == "__eq__"
|
|
769
769
|
and arg.args[0] is jumptable_var
|
|
770
|
-
and isinstance(arg.args[1], claripy.Bits)
|
|
770
|
+
and isinstance(arg.args[1], claripy.ast.Bits)
|
|
771
771
|
and arg.args[1].concrete
|
|
772
772
|
):
|
|
773
773
|
# found it
|
|
@@ -780,7 +780,7 @@ class DreamStructurer(StructurerBase):
|
|
|
780
780
|
# unsupported
|
|
781
781
|
return None
|
|
782
782
|
elif cond.op == "__eq__":
|
|
783
|
-
if cond.args[0] is jumptable_var and isinstance(cond.args[1], claripy.Bits) and cond.args[1].concrete:
|
|
783
|
+
if cond.args[0] is jumptable_var and isinstance(cond.args[1], claripy.ast.Bits) and cond.args[1].concrete:
|
|
784
784
|
# found it
|
|
785
785
|
eq_condition = cond
|
|
786
786
|
true_node = cond_node.true_node
|
|
@@ -800,7 +800,8 @@ class DreamStructurer(StructurerBase):
|
|
|
800
800
|
return None
|
|
801
801
|
|
|
802
802
|
return CodeNode(
|
|
803
|
-
ConditionNode(cond_node.addr, claripy.true, remaining_cond, true_node, false_node=false_node),
|
|
803
|
+
ConditionNode(cond_node.addr, claripy.true(), remaining_cond, true_node, false_node=false_node),
|
|
804
|
+
eq_condition,
|
|
804
805
|
)
|
|
805
806
|
|
|
806
807
|
def _switch_check_existence_of_jumptable_entries(
|
|
@@ -942,11 +943,11 @@ class DreamStructurer(StructurerBase):
|
|
|
942
943
|
)
|
|
943
944
|
],
|
|
944
945
|
)
|
|
945
|
-
case_node = SequenceNode(0, nodes=[CodeNode(case_inner_node, claripy.true)])
|
|
946
|
+
case_node = SequenceNode(0, nodes=[CodeNode(case_inner_node, claripy.true())])
|
|
946
947
|
converted_nodes[entry_addr] = case_node
|
|
947
948
|
continue
|
|
948
949
|
|
|
949
|
-
case_node = SequenceNode(entry_node.addr, nodes=[CodeNode(entry_node.node, claripy.true)])
|
|
950
|
+
case_node = SequenceNode(entry_node.addr, nodes=[CodeNode(entry_node.node, claripy.true())])
|
|
950
951
|
to_remove.add(entry_node)
|
|
951
952
|
entry_node_idx = seq.nodes.index(entry_node)
|
|
952
953
|
|
|
@@ -966,7 +967,7 @@ class DreamStructurer(StructurerBase):
|
|
|
966
967
|
)
|
|
967
968
|
],
|
|
968
969
|
)
|
|
969
|
-
case_node = SequenceNode(0, nodes=[CodeNode(case_inner_node, claripy.true)])
|
|
970
|
+
case_node = SequenceNode(0, nodes=[CodeNode(case_inner_node, claripy.true())])
|
|
970
971
|
converted_nodes[entry_addr] = case_node
|
|
971
972
|
continue
|
|
972
973
|
|
|
@@ -1097,7 +1098,7 @@ class DreamStructurer(StructurerBase):
|
|
|
1097
1098
|
def _nodes_guarded_by_common_subexpr(seq, common_subexpr, starting_idx):
|
|
1098
1099
|
candidates = []
|
|
1099
1100
|
|
|
1100
|
-
if common_subexpr is claripy.true:
|
|
1101
|
+
if common_subexpr is claripy.true():
|
|
1101
1102
|
return []
|
|
1102
1103
|
for j, node_1 in enumerate(seq.nodes[starting_idx:]):
|
|
1103
1104
|
rcond_1 = getattr(node_1, "reaching_condition", None)
|
|
@@ -368,7 +368,7 @@ class PhoenixStructurer(StructurerBase):
|
|
|
368
368
|
jump_node = Block(last_stmt.ins_addr, None, statements=[cond_jump])
|
|
369
369
|
cond_jump_node = ConditionNode(last_stmt.ins_addr, None, edge_cond_right, jump_node)
|
|
370
370
|
new_node = SequenceNode(node.addr, nodes=[node, cond_jump_node, left])
|
|
371
|
-
loop_node = LoopNode("while", claripy.true, new_node, addr=node.addr)
|
|
371
|
+
loop_node = LoopNode("while", claripy.true(), new_node, addr=node.addr)
|
|
372
372
|
|
|
373
373
|
# on the original graph
|
|
374
374
|
self.replace_nodes(graph, node, loop_node, old_node_1=left, self_loop=False)
|
|
@@ -392,7 +392,7 @@ class PhoenixStructurer(StructurerBase):
|
|
|
392
392
|
self._remove_last_statement_if_jump(head_block)
|
|
393
393
|
cond_break = ConditionalBreakNode(node.addr, edge_cond_right, right.addr)
|
|
394
394
|
new_node = SequenceNode(node.addr, nodes=[node, cond_break, left])
|
|
395
|
-
loop_node = LoopNode("while", claripy.true, new_node, addr=node.addr)
|
|
395
|
+
loop_node = LoopNode("while", claripy.true(), new_node, addr=node.addr)
|
|
396
396
|
|
|
397
397
|
# on the original graph
|
|
398
398
|
self.replace_nodes(graph, node, loop_node, old_node_1=left, self_loop=False)
|
|
@@ -572,7 +572,7 @@ class PhoenixStructurer(StructurerBase):
|
|
|
572
572
|
seen_nodes.add(next_node)
|
|
573
573
|
seq_node.nodes.append(next_node)
|
|
574
574
|
|
|
575
|
-
loop_node = LoopNode("while", claripy.true, seq_node, addr=node.addr)
|
|
575
|
+
loop_node = LoopNode("while", claripy.true(), seq_node, addr=node.addr)
|
|
576
576
|
|
|
577
577
|
# on the original graph
|
|
578
578
|
for node_ in seq_node.nodes:
|
|
@@ -141,13 +141,14 @@ class SimEnginePropagatorAIL(
|
|
|
141
141
|
size = data_v.size() // self.arch.byte_width
|
|
142
142
|
to_store = PropValue.from_value_and_details(data_v, size, expr, self._codeloc())
|
|
143
143
|
else:
|
|
144
|
+
expr = data.one_expr
|
|
144
145
|
size = stmt.size
|
|
145
146
|
to_store = data.with_details(
|
|
146
147
|
stmt.size, data.one_expr if data.one_expr is not None else stmt.data, self._codeloc()
|
|
147
148
|
)
|
|
148
149
|
|
|
149
150
|
# ensure there isn't a Tmp variable in the data
|
|
150
|
-
if not self.has_tmpexpr(expr):
|
|
151
|
+
if expr is None or not self.has_tmpexpr(expr):
|
|
151
152
|
# Storing data to a stack variable
|
|
152
153
|
self.state.store_stack_variable(sp_offset, to_store, endness=stmt.endness)
|
|
153
154
|
|
|
@@ -370,10 +370,14 @@ class FunctionHandler:
|
|
|
370
370
|
data.prototype = state.analysis.project.factory.function_prototype()
|
|
371
371
|
data.guessed_prototype = True
|
|
372
372
|
|
|
373
|
-
if data.prototype is not None
|
|
373
|
+
if data.prototype is not None:
|
|
374
374
|
# make sure the function prototype is resolved.
|
|
375
375
|
# TODO: Cache resolved function prototypes globally
|
|
376
|
-
prototype_libname =
|
|
376
|
+
prototype_libname = (
|
|
377
|
+
data.function.prototype_libname
|
|
378
|
+
if data.function is not None and data.function.prototype_libname
|
|
379
|
+
else hook_libname
|
|
380
|
+
)
|
|
377
381
|
type_collections = []
|
|
378
382
|
if prototype_libname is not None:
|
|
379
383
|
prototype_lib = SIM_LIBRARIES[prototype_libname]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# pylint:disable=abstract-method,ungrouped-imports
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import Any, TYPE_CHECKING
|
|
5
5
|
import re
|
|
6
6
|
import logging
|
|
7
7
|
from collections import defaultdict
|
|
@@ -179,7 +179,13 @@ class FrozenStackPointerTrackerState:
|
|
|
179
179
|
|
|
180
180
|
__slots__ = "regs", "memory", "is_tracking_memory", "resilient"
|
|
181
181
|
|
|
182
|
-
def __init__(
|
|
182
|
+
def __init__(
|
|
183
|
+
self,
|
|
184
|
+
regs,
|
|
185
|
+
memory,
|
|
186
|
+
is_tracking_memory,
|
|
187
|
+
resilient,
|
|
188
|
+
):
|
|
183
189
|
self.regs = regs
|
|
184
190
|
self.memory = memory
|
|
185
191
|
self.is_tracking_memory = is_tracking_memory
|
|
@@ -193,8 +199,10 @@ class FrozenStackPointerTrackerState:
|
|
|
193
199
|
return hash((FrozenStackPointerTrackerState, self.regs, self.memory, self.is_tracking_memory))
|
|
194
200
|
return hash((FrozenStackPointerTrackerState, self.regs, self.is_tracking_memory))
|
|
195
201
|
|
|
196
|
-
def merge(
|
|
197
|
-
|
|
202
|
+
def merge(
|
|
203
|
+
self, other, addr: int, reg_merge_cache: dict[tuple[int, int], Any], mem_merge_cache: dict[tuple[int, int], Any]
|
|
204
|
+
):
|
|
205
|
+
return self.unfreeze().merge(other.unfreeze(), addr, reg_merge_cache, mem_merge_cache).freeze()
|
|
198
206
|
|
|
199
207
|
def __eq__(self, other):
|
|
200
208
|
if type(other) is FrozenStackPointerTrackerState or isinstance(other, FrozenStackPointerTrackerState):
|
|
@@ -278,16 +286,18 @@ class StackPointerTrackerState:
|
|
|
278
286
|
return hash((StackPointerTrackerState, self.regs, self.memory, self.is_tracking_memory))
|
|
279
287
|
return hash((StackPointerTrackerState, self.regs, self.is_tracking_memory))
|
|
280
288
|
|
|
281
|
-
def merge(
|
|
289
|
+
def merge(
|
|
290
|
+
self, other, addr: int, reg_merge_cache: dict[tuple[int, int], Any], mem_merge_cache: dict[tuple[int, int], Any]
|
|
291
|
+
):
|
|
282
292
|
return StackPointerTrackerState(
|
|
283
|
-
regs=_dict_merge(self.regs, other.regs, self.resilient),
|
|
284
|
-
memory=_dict_merge(self.memory, other.memory, self.resilient),
|
|
293
|
+
regs=_dict_merge(self.regs, other.regs, self.resilient, addr, reg_merge_cache),
|
|
294
|
+
memory=_dict_merge(self.memory, other.memory, self.resilient, addr, mem_merge_cache),
|
|
285
295
|
is_tracking_memory=self.is_tracking_memory and other.is_tracking_memory,
|
|
286
296
|
resilient=self.resilient or other.resilient,
|
|
287
297
|
)
|
|
288
298
|
|
|
289
299
|
|
|
290
|
-
def _dict_merge(d1, d2, resilient: bool):
|
|
300
|
+
def _dict_merge(d1, d2, resilient: bool, addr: int, merge_cache: dict[tuple[int, int], Any]):
|
|
291
301
|
all_keys = set(d1.keys()) | set(d2.keys())
|
|
292
302
|
merged = {}
|
|
293
303
|
for k in all_keys:
|
|
@@ -299,7 +309,12 @@ def _dict_merge(d1, d2, resilient: bool):
|
|
|
299
309
|
merged[k] = d1[k]
|
|
300
310
|
else: # d1[k] != d2[k]
|
|
301
311
|
if resilient and isinstance(d1[k], OffsetVal) and isinstance(d2[k], OffsetVal):
|
|
302
|
-
|
|
312
|
+
if (addr, k) in merge_cache:
|
|
313
|
+
merged[k] = merge_cache[(addr, k)]
|
|
314
|
+
else:
|
|
315
|
+
v = min(d1[k], d2[k])
|
|
316
|
+
merge_cache[(addr, k)] = v
|
|
317
|
+
merged[k] = v
|
|
303
318
|
else:
|
|
304
319
|
merged[k] = TOP
|
|
305
320
|
return merged
|
|
@@ -350,6 +365,9 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
|
|
|
350
365
|
self._reg_value_at_block_start = defaultdict(dict)
|
|
351
366
|
self.cross_insn_opt = cross_insn_opt
|
|
352
367
|
self._resilient = resilient
|
|
368
|
+
# in resilience mode, cache previously merged values to ensure we reach a fixed point
|
|
369
|
+
self._reg_merge_cache = {}
|
|
370
|
+
self._mem_merge_cache = {}
|
|
353
371
|
|
|
354
372
|
if initial_reg_values:
|
|
355
373
|
self._reg_value_at_block_start[func.addr if func is not None else block.addr] = initial_reg_values
|
|
@@ -492,7 +510,7 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
|
|
|
492
510
|
def _set_state(self, addr, new_val, pre_or_post):
|
|
493
511
|
previous_val = self._state_for(addr, pre_or_post)
|
|
494
512
|
if previous_val is not None:
|
|
495
|
-
new_val = previous_val.merge(new_val)
|
|
513
|
+
new_val = previous_val.merge(new_val, addr, self._reg_merge_cache, self._mem_merge_cache)
|
|
496
514
|
if addr not in self.states:
|
|
497
515
|
self.states[addr] = {}
|
|
498
516
|
self.states[addr][pre_or_post] = new_val
|
|
@@ -808,7 +826,7 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
|
|
|
808
826
|
def _merge_states(self, node, *states: StackPointerTrackerState):
|
|
809
827
|
merged_state = states[0]
|
|
810
828
|
for other in states[1:]:
|
|
811
|
-
merged_state = merged_state.merge(other)
|
|
829
|
+
merged_state = merged_state.merge(other, node.addr, self._reg_merge_cache, self._mem_merge_cache)
|
|
812
830
|
return merged_state, merged_state == states[0]
|
|
813
831
|
|
|
814
832
|
def _find_callees(self, node) -> list[Function]:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# pylint:disable=unused-argument,no-self-use
|
|
1
2
|
from __future__ import annotations
|
|
2
3
|
from itertools import count
|
|
3
4
|
|
|
@@ -8,11 +9,15 @@ from .typeconsts import TypeConstant
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class SimTypeTempRef(sim_type.SimType):
|
|
12
|
+
"""
|
|
13
|
+
Represents a temporary reference to another type. TypeVariableReference is translated to SimTypeTempRef.
|
|
14
|
+
"""
|
|
15
|
+
|
|
11
16
|
def __init__(self, typevar):
|
|
12
17
|
super().__init__()
|
|
13
18
|
self.typevar = typevar
|
|
14
19
|
|
|
15
|
-
def c_repr(self):
|
|
20
|
+
def c_repr(self, **kwargs):
|
|
16
21
|
return "<SimTypeTempRef>"
|
|
17
22
|
|
|
18
23
|
|
|
@@ -141,7 +146,10 @@ class TypeTranslator:
|
|
|
141
146
|
return sim_type.SimTypeLongLong(signed=False).with_arch(self.arch)
|
|
142
147
|
|
|
143
148
|
def _translate_Int128(self, tc): # pylint:disable=unused-argument
|
|
144
|
-
return sim_type.
|
|
149
|
+
return sim_type.SimTypeInt128(signed=False).with_arch(self.arch)
|
|
150
|
+
|
|
151
|
+
def _translate_Int256(self, tc): # pylint:disable=unused-argument
|
|
152
|
+
return sim_type.SimTypeInt256(signed=False).with_arch(self.arch)
|
|
145
153
|
|
|
146
154
|
def _translate_TypeVariableReference(self, tc):
|
|
147
155
|
if tc.typevar in self.translated:
|
|
@@ -176,6 +184,12 @@ class TypeTranslator:
|
|
|
176
184
|
# SimType handlers
|
|
177
185
|
#
|
|
178
186
|
|
|
187
|
+
def _translate_SimTypeInt128(self, st: sim_type.SimTypeChar) -> typeconsts.Int128:
|
|
188
|
+
return typeconsts.Int128()
|
|
189
|
+
|
|
190
|
+
def _translate_SimTypeInt256(self, st: sim_type.SimTypeChar) -> typeconsts.Int256:
|
|
191
|
+
return typeconsts.Int256()
|
|
192
|
+
|
|
179
193
|
def _translate_SimTypeInt(self, st: sim_type.SimTypeInt) -> typeconsts.Int32:
|
|
180
194
|
return typeconsts.Int32()
|
|
181
195
|
|
|
@@ -220,6 +234,7 @@ TypeConstHandlers = {
|
|
|
220
234
|
typeconsts.Int32: TypeTranslator._translate_Int32,
|
|
221
235
|
typeconsts.Int64: TypeTranslator._translate_Int64,
|
|
222
236
|
typeconsts.Int128: TypeTranslator._translate_Int128,
|
|
237
|
+
typeconsts.Int256: TypeTranslator._translate_Int256,
|
|
223
238
|
typeconsts.TypeVariableReference: TypeTranslator._translate_TypeVariableReference,
|
|
224
239
|
}
|
|
225
240
|
|
|
@@ -230,6 +245,8 @@ SimTypeHandlers = {
|
|
|
230
245
|
sim_type.SimTypeLong: TypeTranslator._translate_SimTypeLong,
|
|
231
246
|
sim_type.SimTypeLongLong: TypeTranslator._translate_SimTypeLongLong,
|
|
232
247
|
sim_type.SimTypeChar: TypeTranslator._translate_SimTypeChar,
|
|
248
|
+
sim_type.SimTypeInt128: TypeTranslator._translate_SimTypeInt128,
|
|
249
|
+
sim_type.SimTypeInt256: TypeTranslator._translate_SimTypeInt256,
|
|
233
250
|
sim_type.SimStruct: TypeTranslator._translate_SimStruct,
|
|
234
251
|
sim_type.SimTypeArray: TypeTranslator._translate_SimTypeArray,
|
|
235
252
|
}
|
|
@@ -100,6 +100,13 @@ class Int128(Int):
|
|
|
100
100
|
return "int128"
|
|
101
101
|
|
|
102
102
|
|
|
103
|
+
class Int256(Int):
|
|
104
|
+
SIZE = 32
|
|
105
|
+
|
|
106
|
+
def __repr__(self, memo=None):
|
|
107
|
+
return "int256"
|
|
108
|
+
|
|
109
|
+
|
|
103
110
|
class FloatBase(TypeConstant):
|
|
104
111
|
def __repr__(self, memo=None):
|
|
105
112
|
return "floatbase"
|
|
@@ -282,6 +289,7 @@ def int_type(bits: int) -> Int | None:
|
|
|
282
289
|
32: Int32,
|
|
283
290
|
64: Int64,
|
|
284
291
|
128: Int128,
|
|
292
|
+
256: Int256,
|
|
285
293
|
}
|
|
286
294
|
if bits in mapping:
|
|
287
295
|
return mapping[bits]()
|
|
@@ -254,10 +254,13 @@ class SimEngineVRVEX(
|
|
|
254
254
|
typevar = typevars.DerivedTypeVariable(r0.typevar, typevars.AddN(r1.data.concrete_value))
|
|
255
255
|
|
|
256
256
|
sum_ = r0.data + r1.data
|
|
257
|
+
tc = set()
|
|
258
|
+
if r0.typevar is not None and r1.typevar is not None:
|
|
259
|
+
tc.add(typevars.Subtype(r0.typevar, r1.typevar))
|
|
257
260
|
return RichR(
|
|
258
261
|
sum_,
|
|
259
262
|
typevar=typevar,
|
|
260
|
-
type_constraints=
|
|
263
|
+
type_constraints=tc,
|
|
261
264
|
)
|
|
262
265
|
|
|
263
266
|
def _handle_Sub(self, expr):
|
|
@@ -501,6 +504,9 @@ class SimEngineVRVEX(
|
|
|
501
504
|
def _handle_Clz(self, expr):
|
|
502
505
|
return RichR(self.state.top(expr.result_size(self.tyenv)))
|
|
503
506
|
|
|
507
|
+
def _handle_Ctz(self, expr):
|
|
508
|
+
return RichR(self.state.top(expr.result_size(self.tyenv)))
|
|
509
|
+
|
|
504
510
|
def _handle_Mull(self, expr):
|
|
505
511
|
return RichR(self.state.top(expr.result_size(self.tyenv)))
|
|
506
512
|
|
|
@@ -553,15 +559,6 @@ class SimEngineVRVEX(
|
|
|
553
559
|
_, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
554
560
|
return RichR(self.state.top(expr.result_size(self.tyenv)))
|
|
555
561
|
|
|
556
|
-
def _handle_Clz(self, expr):
|
|
557
|
-
arg0 = expr.args[0]
|
|
558
|
-
expr_0 = self._expr(arg0)
|
|
559
|
-
if expr_0 is None:
|
|
560
|
-
return None
|
|
561
|
-
if self.state.is_top(expr_0.data):
|
|
562
|
-
return RichR(self.state.top(expr_0.data.size()))
|
|
563
|
-
return RichR(self.state.top(expr_0.data.size()))
|
|
564
|
-
|
|
565
562
|
_handle_CmpEQ_v = _handle_Cmp_v
|
|
566
563
|
_handle_CmpNE_v = _handle_Cmp_v
|
|
567
564
|
_handle_CmpLE_v = _handle_Cmp_v
|