angr 9.2.96__py3-none-manylinux2014_x86_64.whl → 9.2.98__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/cfg/cfg_base.py +14 -1
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +10 -6
- angr/analyses/complete_calling_conventions.py +27 -11
- angr/analyses/decompiler/ail_simplifier.py +20 -8
- angr/analyses/decompiler/condition_processor.py +2 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +2 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +380 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +4 -1
- angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +71 -3
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +162 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +1 -1
- angr/analyses/decompiler/structured_codegen/c.py +72 -99
- angr/analyses/decompiler/utils.py +5 -1
- angr/analyses/find_objects_static.py +15 -10
- angr/analyses/forward_analysis/forward_analysis.py +15 -1
- angr/analyses/propagator/engine_ail.py +2 -0
- angr/analyses/propagator/engine_vex.py +15 -0
- angr/analyses/propagator/propagator.py +6 -3
- angr/analyses/reaching_definitions/engine_vex.py +6 -0
- angr/analyses/reaching_definitions/rd_state.py +14 -1
- angr/analyses/reaching_definitions/reaching_definitions.py +19 -2
- angr/analyses/variable_recovery/engine_ail.py +6 -6
- angr/analyses/variable_recovery/engine_vex.py +6 -0
- angr/analyses/variable_recovery/irsb_scanner.py +12 -0
- angr/analyses/variable_recovery/variable_recovery_base.py +4 -1
- angr/engines/light/engine.py +134 -16
- angr/knowledge_plugins/functions/function.py +4 -0
- angr/knowledge_plugins/key_definitions/environment.py +11 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +41 -8
- angr/knowledge_plugins/key_definitions/uses.py +18 -4
- angr/knowledge_plugins/propagations/states.py +22 -3
- angr/knowledge_plugins/types.py +6 -0
- angr/knowledge_plugins/variables/variable_manager.py +31 -5
- angr/simos/simos.py +2 -0
- angr/storage/memory_mixins/__init__.py +3 -0
- angr/storage/memory_mixins/multi_value_merger_mixin.py +22 -11
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +20 -2
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +20 -5
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +82 -44
- angr/storage/memory_mixins/simple_interface_mixin.py +4 -0
- angr/utils/cowdict.py +4 -2
- angr/utils/funcid.py +6 -0
- angr/utils/mp.py +1 -1
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/METADATA +6 -6
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/RECORD +51 -49
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/LICENSE +0 -0
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/WHEEL +0 -0
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/entry_points.txt +0 -0
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# pylint:disable=arguments-differ
|
|
2
|
-
from typing import Tuple, Optional
|
|
2
|
+
from typing import Tuple, Optional, Dict, List
|
|
3
3
|
import string
|
|
4
4
|
|
|
5
5
|
from archinfo import Endness
|
|
6
6
|
|
|
7
|
-
from ailment.expression import Const
|
|
7
|
+
from ailment.expression import Const, StackBaseOffset
|
|
8
8
|
from ailment.statement import Call, Store
|
|
9
9
|
|
|
10
10
|
from .base import PeepholeOptimizationStmtBase
|
|
@@ -24,7 +24,7 @@ class InlinedStrcpy(PeepholeOptimizationStmtBase):
|
|
|
24
24
|
NAME = "Simplifying inlined strcpy"
|
|
25
25
|
stmt_classes = (Store,)
|
|
26
26
|
|
|
27
|
-
def optimize(self, stmt: Store, **kwargs):
|
|
27
|
+
def optimize(self, stmt: Store, stmt_idx: int = None, block=None, **kwargs):
|
|
28
28
|
if isinstance(stmt.data, Const):
|
|
29
29
|
r, s = self.is_integer_likely_a_string(stmt.data.value, stmt.data.size, stmt.endness)
|
|
30
30
|
if r:
|
|
@@ -41,8 +41,76 @@ class InlinedStrcpy(PeepholeOptimizationStmtBase):
|
|
|
41
41
|
**stmt.tags,
|
|
42
42
|
)
|
|
43
43
|
|
|
44
|
+
# scan forward in the current block to find all consecutive constant stores
|
|
45
|
+
if block is not None and stmt_idx is not None:
|
|
46
|
+
all_constant_stores: Dict[int, Tuple[int, Optional[Const]]] = self.collect_constant_stores(
|
|
47
|
+
block, stmt_idx
|
|
48
|
+
)
|
|
49
|
+
if all_constant_stores:
|
|
50
|
+
offsets = sorted(all_constant_stores.keys())
|
|
51
|
+
next_offset = min(offsets)
|
|
52
|
+
stride = []
|
|
53
|
+
for offset in offsets:
|
|
54
|
+
if next_offset is not None and offset != next_offset:
|
|
55
|
+
next_offset = None
|
|
56
|
+
stride = []
|
|
57
|
+
stmt_idx_, v = all_constant_stores[offset]
|
|
58
|
+
if v is not None:
|
|
59
|
+
stride.append((offset, stmt_idx_, v))
|
|
60
|
+
next_offset = offset + v.size
|
|
61
|
+
else:
|
|
62
|
+
next_offset = None
|
|
63
|
+
stride = []
|
|
64
|
+
|
|
65
|
+
integer, size = self.stride_to_int(stride)
|
|
66
|
+
r, s = self.is_integer_likely_a_string(integer, size, Endness.BE)
|
|
67
|
+
if r:
|
|
68
|
+
# we remove all involved statements whose statement IDs are greater than the current one
|
|
69
|
+
for _, stmt_idx_, _ in reversed(stride):
|
|
70
|
+
if stmt_idx_ <= stmt_idx:
|
|
71
|
+
continue
|
|
72
|
+
block.statements[stmt_idx_] = None
|
|
73
|
+
block.statements = [ss for ss in block.statements if ss is not None]
|
|
74
|
+
|
|
75
|
+
str_id = self.kb.custom_strings.allocate(s.encode("ascii"))
|
|
76
|
+
return Call(
|
|
77
|
+
stmt.idx,
|
|
78
|
+
"strncpy",
|
|
79
|
+
args=[
|
|
80
|
+
stmt.addr,
|
|
81
|
+
Const(None, None, str_id, stmt.addr.bits, custom_string=True),
|
|
82
|
+
Const(None, None, len(s), self.project.arch.bits),
|
|
83
|
+
],
|
|
84
|
+
**stmt.tags,
|
|
85
|
+
)
|
|
86
|
+
|
|
44
87
|
return None
|
|
45
88
|
|
|
89
|
+
@staticmethod
|
|
90
|
+
def stride_to_int(stride: List[Tuple[int, int, Const]]) -> Tuple[int, int]:
|
|
91
|
+
stride = sorted(stride, key=lambda x: x[0])
|
|
92
|
+
n = 0
|
|
93
|
+
size = 0
|
|
94
|
+
for _, _, v in stride:
|
|
95
|
+
size += v.size
|
|
96
|
+
n <<= v.bits
|
|
97
|
+
n |= v.value
|
|
98
|
+
return n, size
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def collect_constant_stores(block, starting_stmt_idx: int) -> Dict[int, Tuple[int, Optional[Const]]]:
|
|
102
|
+
r = {}
|
|
103
|
+
for idx, stmt in enumerate(block.statements):
|
|
104
|
+
if idx < starting_stmt_idx:
|
|
105
|
+
continue
|
|
106
|
+
if isinstance(stmt, Store) and isinstance(stmt.addr, StackBaseOffset) and isinstance(stmt.addr.offset, int):
|
|
107
|
+
if isinstance(stmt.data, Const):
|
|
108
|
+
r[stmt.addr.offset] = idx, stmt.data
|
|
109
|
+
else:
|
|
110
|
+
r[stmt.addr.offset] = idx, None
|
|
111
|
+
|
|
112
|
+
return r
|
|
113
|
+
|
|
46
114
|
@staticmethod
|
|
47
115
|
def is_integer_likely_a_string(
|
|
48
116
|
v: int, size: int, endness: Endness, min_length: int = 4
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# pylint:disable=arguments-differ
|
|
2
|
+
from typing import Tuple, Optional, Dict, List
|
|
3
|
+
import string
|
|
4
|
+
|
|
5
|
+
from archinfo import Endness
|
|
6
|
+
|
|
7
|
+
from ailment.expression import Const, StackBaseOffset
|
|
8
|
+
from ailment.statement import Call, Store
|
|
9
|
+
|
|
10
|
+
from .base import PeepholeOptimizationStmtBase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
ASCII_PRINTABLES = set(string.printable)
|
|
14
|
+
ASCII_DIGITS = set(string.digits)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InlinedWstrcpy(PeepholeOptimizationStmtBase):
|
|
18
|
+
"""
|
|
19
|
+
Simplifies inlined wide string copying logic into calls to wstrcpy.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__slots__ = ()
|
|
23
|
+
|
|
24
|
+
NAME = "Simplifying inlined wstrcpy"
|
|
25
|
+
stmt_classes = (Store,)
|
|
26
|
+
|
|
27
|
+
def optimize(self, stmt: Store, stmt_idx: int = None, block=None, **kwargs):
|
|
28
|
+
if isinstance(stmt.data, Const):
|
|
29
|
+
r, s = self.is_integer_likely_a_wide_string(stmt.data.value, stmt.data.size, stmt.endness)
|
|
30
|
+
if r:
|
|
31
|
+
# replace it with a call to strncpy
|
|
32
|
+
str_id = self.kb.custom_strings.allocate(s.encode("ascii"))
|
|
33
|
+
return Call(
|
|
34
|
+
stmt.idx,
|
|
35
|
+
"wstrncpy",
|
|
36
|
+
args=[
|
|
37
|
+
stmt.addr,
|
|
38
|
+
Const(None, None, str_id, stmt.addr.bits, custom_string=True),
|
|
39
|
+
Const(None, None, len(s), self.project.arch.bits),
|
|
40
|
+
],
|
|
41
|
+
**stmt.tags,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# scan forward in the current block to find all consecutive constant stores
|
|
45
|
+
if block is not None and stmt_idx is not None:
|
|
46
|
+
all_constant_stores: Dict[int, Tuple[int, Optional[Const]]] = self.collect_constant_stores(
|
|
47
|
+
block, stmt_idx
|
|
48
|
+
)
|
|
49
|
+
if all_constant_stores:
|
|
50
|
+
offsets = sorted(all_constant_stores.keys())
|
|
51
|
+
next_offset = min(offsets)
|
|
52
|
+
stride = []
|
|
53
|
+
for offset in offsets:
|
|
54
|
+
if next_offset is not None and offset != next_offset:
|
|
55
|
+
next_offset = None
|
|
56
|
+
stride = []
|
|
57
|
+
stmt_idx_, v = all_constant_stores[offset]
|
|
58
|
+
if v is not None:
|
|
59
|
+
stride.append((offset, stmt_idx_, v))
|
|
60
|
+
next_offset = offset + v.size
|
|
61
|
+
else:
|
|
62
|
+
next_offset = None
|
|
63
|
+
stride = []
|
|
64
|
+
|
|
65
|
+
integer, size = self.stride_to_int(stride)
|
|
66
|
+
r, s = self.is_integer_likely_a_wide_string(integer, size, Endness.BE)
|
|
67
|
+
if r:
|
|
68
|
+
# we remove all involved statements whose statement IDs are greater than the current one
|
|
69
|
+
for _, stmt_idx_, _ in reversed(stride):
|
|
70
|
+
if stmt_idx_ <= stmt_idx:
|
|
71
|
+
continue
|
|
72
|
+
block.statements[stmt_idx_] = None
|
|
73
|
+
block.statements = [ss for ss in block.statements if ss is not None]
|
|
74
|
+
|
|
75
|
+
str_id = self.kb.custom_strings.allocate(s.encode("ascii"))
|
|
76
|
+
return Call(
|
|
77
|
+
stmt.idx,
|
|
78
|
+
"wstrncpy",
|
|
79
|
+
args=[
|
|
80
|
+
stmt.addr,
|
|
81
|
+
Const(None, None, str_id, stmt.addr.bits, custom_string=True),
|
|
82
|
+
Const(None, None, len(s), self.project.arch.bits),
|
|
83
|
+
],
|
|
84
|
+
**stmt.tags,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def stride_to_int(stride: List[Tuple[int, int, Const]]) -> Tuple[int, int]:
|
|
91
|
+
stride = sorted(stride, key=lambda x: x[0])
|
|
92
|
+
n = 0
|
|
93
|
+
size = 0
|
|
94
|
+
for _, _, v in stride:
|
|
95
|
+
size += v.size
|
|
96
|
+
n <<= v.bits
|
|
97
|
+
n |= v.value
|
|
98
|
+
return n, size
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def collect_constant_stores(block, starting_stmt_idx: int) -> Dict[int, Tuple[int, Optional[Const]]]:
|
|
102
|
+
r = {}
|
|
103
|
+
for idx, stmt in enumerate(block.statements):
|
|
104
|
+
if idx < starting_stmt_idx:
|
|
105
|
+
continue
|
|
106
|
+
if isinstance(stmt, Store) and isinstance(stmt.addr, StackBaseOffset) and isinstance(stmt.addr.offset, int):
|
|
107
|
+
if isinstance(stmt.data, Const):
|
|
108
|
+
r[stmt.addr.offset] = idx, stmt.data
|
|
109
|
+
else:
|
|
110
|
+
r[stmt.addr.offset] = idx, None
|
|
111
|
+
|
|
112
|
+
return r
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def even_offsets_are_zero(lst: List[str]) -> bool:
|
|
116
|
+
return all(ch == "\x00" for i, ch in enumerate(lst) if i % 2 == 0)
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def odd_offsets_are_zero(lst: List[str]) -> bool:
|
|
120
|
+
return all(ch == "\x00" for i, ch in enumerate(lst) if i % 2 == 1)
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def is_integer_likely_a_wide_string(
|
|
124
|
+
v: int, size: int, endness: Endness, min_length: int = 4
|
|
125
|
+
) -> Tuple[bool, Optional[str]]:
|
|
126
|
+
# we need at least four bytes of printable characters
|
|
127
|
+
|
|
128
|
+
chars = []
|
|
129
|
+
if endness == Endness.LE:
|
|
130
|
+
while v != 0:
|
|
131
|
+
byt = v & 0xFF
|
|
132
|
+
if byt != 0 and chr(byt) not in ASCII_PRINTABLES:
|
|
133
|
+
return False, None
|
|
134
|
+
chars.append(chr(byt))
|
|
135
|
+
v >>= 8
|
|
136
|
+
|
|
137
|
+
elif endness == Endness.BE:
|
|
138
|
+
for _ in range(size):
|
|
139
|
+
byt = v & 0xFF
|
|
140
|
+
v >>= 8
|
|
141
|
+
if byt != 0 and chr(byt) not in ASCII_PRINTABLES:
|
|
142
|
+
return False, None
|
|
143
|
+
chars.append(chr(byt))
|
|
144
|
+
chars = chars[::-1]
|
|
145
|
+
else:
|
|
146
|
+
# unsupported endness
|
|
147
|
+
return False, None
|
|
148
|
+
|
|
149
|
+
if InlinedWstrcpy.even_offsets_are_zero(chars):
|
|
150
|
+
chars = [ch for i, ch in enumerate(chars) if i % 2 == 1]
|
|
151
|
+
elif InlinedWstrcpy.odd_offsets_are_zero(chars):
|
|
152
|
+
chars = [ch for i, ch in enumerate(chars) if i % 2 == 0]
|
|
153
|
+
else:
|
|
154
|
+
return False, None
|
|
155
|
+
|
|
156
|
+
if chars and chars[-1] == "\x00":
|
|
157
|
+
chars = chars[:-1]
|
|
158
|
+
if len(chars) >= min_length and all(ch in ASCII_PRINTABLES for ch in chars):
|
|
159
|
+
if len(chars) <= 4 and all(ch in ASCII_DIGITS for ch in chars):
|
|
160
|
+
return False, None
|
|
161
|
+
return True, "".join(chars)
|
|
162
|
+
return False, None
|
|
@@ -5,6 +5,6 @@ from .base import (
|
|
|
5
5
|
PositionMappingElement,
|
|
6
6
|
PositionMapping,
|
|
7
7
|
)
|
|
8
|
-
from .c import CStructuredCodeGenerator
|
|
8
|
+
from .c import CStructuredCodeGenerator, CStructuredCodeWalker
|
|
9
9
|
from .dwarf_import import ImportSourceCode
|
|
10
10
|
from .dummy import DummyStructuredCodeGenerator
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument
|
|
1
|
+
# pylint:disable=missing-class-docstring,too-many-boolean-expressions,unused-argument,no-self-use
|
|
2
2
|
from typing import Optional, Dict, List, Tuple, Set, Any, Union, TYPE_CHECKING, Callable
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
import logging
|
|
@@ -2524,9 +2524,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2524
2524
|
codegen=self,
|
|
2525
2525
|
omit_header=self.omit_func_header,
|
|
2526
2526
|
)
|
|
2527
|
-
self.cfunc = FieldReferenceCleanup.handle(self.cfunc)
|
|
2528
|
-
self.cfunc = PointerArithmeticFixer.handle(self.cfunc)
|
|
2529
|
-
self.cfunc = MakeTypecastsImplicit.handle(self.cfunc)
|
|
2527
|
+
self.cfunc = FieldReferenceCleanup().handle(self.cfunc)
|
|
2528
|
+
self.cfunc = PointerArithmeticFixer().handle(self.cfunc)
|
|
2529
|
+
self.cfunc = MakeTypecastsImplicit().handle(self.cfunc)
|
|
2530
2530
|
|
|
2531
2531
|
# TODO store extern fallback size somewhere lol
|
|
2532
2532
|
self.cexterns = {
|
|
@@ -3554,120 +3554,100 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3554
3554
|
|
|
3555
3555
|
|
|
3556
3556
|
class CStructuredCodeWalker:
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
handler = getattr(cls, "handle_" + type(obj).__name__, cls.handle_default)
|
|
3557
|
+
def handle(self, obj):
|
|
3558
|
+
handler = getattr(self, "handle_" + type(obj).__name__, self.handle_default)
|
|
3560
3559
|
return handler(obj)
|
|
3561
3560
|
|
|
3562
|
-
|
|
3563
|
-
def handle_default(cls, obj):
|
|
3561
|
+
def handle_default(self, obj):
|
|
3564
3562
|
return obj
|
|
3565
3563
|
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
obj.statements = cls.handle(obj.statements)
|
|
3564
|
+
def handle_CFunction(self, obj):
|
|
3565
|
+
obj.statements = self.handle(obj.statements)
|
|
3569
3566
|
return obj
|
|
3570
3567
|
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
obj.statements = [cls.handle(stmt) for stmt in obj.statements]
|
|
3568
|
+
def handle_CStatements(self, obj):
|
|
3569
|
+
obj.statements = [self.handle(stmt) for stmt in obj.statements]
|
|
3574
3570
|
return obj
|
|
3575
3571
|
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
obj.
|
|
3579
|
-
obj.body = cls.handle(obj.body)
|
|
3572
|
+
def handle_CWhileLoop(self, obj):
|
|
3573
|
+
obj.condition = self.handle(obj.condition)
|
|
3574
|
+
obj.body = self.handle(obj.body)
|
|
3580
3575
|
return obj
|
|
3581
3576
|
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
obj.
|
|
3585
|
-
obj.body = cls.handle(obj.body)
|
|
3577
|
+
def handle_CDoWhileLoop(self, obj):
|
|
3578
|
+
obj.condition = self.handle(obj.condition)
|
|
3579
|
+
obj.body = self.handle(obj.body)
|
|
3586
3580
|
return obj
|
|
3587
3581
|
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
obj.
|
|
3591
|
-
obj.
|
|
3592
|
-
obj.
|
|
3593
|
-
obj.body = cls.handle(obj.body)
|
|
3582
|
+
def handle_CForLoop(self, obj):
|
|
3583
|
+
obj.initializer = self.handle(obj.initializer)
|
|
3584
|
+
obj.condition = self.handle(obj.condition)
|
|
3585
|
+
obj.iterator = self.handle(obj.iterator)
|
|
3586
|
+
obj.body = self.handle(obj.body)
|
|
3594
3587
|
return obj
|
|
3595
3588
|
|
|
3596
|
-
|
|
3597
|
-
def handle_CIfElse(cls, obj):
|
|
3589
|
+
def handle_CIfElse(self, obj):
|
|
3598
3590
|
obj.condition_and_nodes = [
|
|
3599
|
-
(
|
|
3591
|
+
(self.handle(condition), self.handle(node)) for condition, node in obj.condition_and_nodes
|
|
3600
3592
|
]
|
|
3601
|
-
obj.else_node =
|
|
3593
|
+
obj.else_node = self.handle(obj.else_node)
|
|
3602
3594
|
return obj
|
|
3603
3595
|
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
obj.condition = cls.handle(obj.condition)
|
|
3596
|
+
def handle_CIfBreak(self, obj):
|
|
3597
|
+
obj.condition = self.handle(obj.condition)
|
|
3607
3598
|
return obj
|
|
3608
3599
|
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
obj.
|
|
3612
|
-
obj.
|
|
3613
|
-
obj.default = cls.handle(obj.default)
|
|
3600
|
+
def handle_CSwitchCase(self, obj):
|
|
3601
|
+
obj.switch = self.handle(obj.switch)
|
|
3602
|
+
obj.cases = [(case, self.handle(body)) for case, body in obj.cases]
|
|
3603
|
+
obj.default = self.handle(obj.default)
|
|
3614
3604
|
return obj
|
|
3615
3605
|
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
obj.
|
|
3619
|
-
obj.rhs = cls.handle(obj.rhs)
|
|
3606
|
+
def handle_CAssignment(self, obj):
|
|
3607
|
+
obj.lhs = self.handle(obj.lhs)
|
|
3608
|
+
obj.rhs = self.handle(obj.rhs)
|
|
3620
3609
|
return obj
|
|
3621
3610
|
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
obj.
|
|
3625
|
-
obj.
|
|
3626
|
-
obj.ret_expr = cls.handle(obj.ret_expr)
|
|
3611
|
+
def handle_CFunctionCall(self, obj):
|
|
3612
|
+
obj.callee_target = self.handle(obj.callee_target)
|
|
3613
|
+
obj.args = [self.handle(arg) for arg in obj.args]
|
|
3614
|
+
obj.ret_expr = self.handle(obj.ret_expr)
|
|
3627
3615
|
return obj
|
|
3628
3616
|
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
obj.retval = cls.handle(obj.retval)
|
|
3617
|
+
def handle_CReturn(self, obj):
|
|
3618
|
+
obj.retval = self.handle(obj.retval)
|
|
3632
3619
|
return obj
|
|
3633
3620
|
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
obj.target = cls.handle(obj.target)
|
|
3621
|
+
def handle_CGoto(self, obj):
|
|
3622
|
+
obj.target = self.handle(obj.target)
|
|
3637
3623
|
return obj
|
|
3638
3624
|
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
obj.
|
|
3642
|
-
obj.index = cls.handle(obj.index)
|
|
3625
|
+
def handle_CIndexedVariable(self, obj):
|
|
3626
|
+
obj.variable = self.handle(obj.variable)
|
|
3627
|
+
obj.index = self.handle(obj.index)
|
|
3643
3628
|
return obj
|
|
3644
3629
|
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
obj.variable = cls.handle(obj.variable)
|
|
3630
|
+
def handle_CVariableField(self, obj):
|
|
3631
|
+
obj.variable = self.handle(obj.variable)
|
|
3648
3632
|
return obj
|
|
3649
3633
|
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
obj.operand = cls.handle(obj.operand)
|
|
3634
|
+
def handle_CUnaryOp(self, obj):
|
|
3635
|
+
obj.operand = self.handle(obj.operand)
|
|
3653
3636
|
return obj
|
|
3654
3637
|
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
obj.
|
|
3658
|
-
obj.rhs = cls.handle(obj.rhs)
|
|
3638
|
+
def handle_CBinaryOp(self, obj):
|
|
3639
|
+
obj.lhs = self.handle(obj.lhs)
|
|
3640
|
+
obj.rhs = self.handle(obj.rhs)
|
|
3659
3641
|
return obj
|
|
3660
3642
|
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
obj.expr = cls.handle(obj.expr)
|
|
3643
|
+
def handle_CTypeCast(self, obj):
|
|
3644
|
+
obj.expr = self.handle(obj.expr)
|
|
3664
3645
|
return obj
|
|
3665
3646
|
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
obj.
|
|
3669
|
-
obj.
|
|
3670
|
-
obj.iffalse = cls.handle(obj.iffalse)
|
|
3647
|
+
def handle_CITE(self, obj):
|
|
3648
|
+
obj.cond = self.handle(obj.cond)
|
|
3649
|
+
obj.iftrue = self.handle(obj.iftrue)
|
|
3650
|
+
obj.iffalse = self.handle(obj.iffalse)
|
|
3671
3651
|
return obj
|
|
3672
3652
|
|
|
3673
3653
|
|
|
@@ -3702,34 +3682,30 @@ class MakeTypecastsImplicit(CStructuredCodeWalker):
|
|
|
3702
3682
|
return cls.collapse(dst_ty, result)
|
|
3703
3683
|
return result
|
|
3704
3684
|
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
obj.rhs = cls.collapse(obj.lhs.type, obj.rhs)
|
|
3685
|
+
def handle_CAssignment(self, obj):
|
|
3686
|
+
obj.rhs = self.collapse(obj.lhs.type, obj.rhs)
|
|
3708
3687
|
return super().handle_CAssignment(obj)
|
|
3709
3688
|
|
|
3710
|
-
|
|
3711
|
-
def handle_CFunctionCall(cls, obj: CFunctionCall):
|
|
3689
|
+
def handle_CFunctionCall(self, obj: CFunctionCall):
|
|
3712
3690
|
for i, (c_arg, arg_ty) in enumerate(zip(obj.args, obj.prototype.args)):
|
|
3713
|
-
obj.args[i] =
|
|
3691
|
+
obj.args[i] = self.collapse(arg_ty, c_arg)
|
|
3714
3692
|
return super().handle_CFunctionCall(obj)
|
|
3715
3693
|
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
obj.retval = cls.collapse(obj.codegen._func.prototype.returnty, obj.retval)
|
|
3694
|
+
def handle_CReturn(self, obj: CReturn):
|
|
3695
|
+
obj.retval = self.collapse(obj.codegen._func.prototype.returnty, obj.retval)
|
|
3719
3696
|
return super().handle_CReturn(obj)
|
|
3720
3697
|
|
|
3721
|
-
|
|
3722
|
-
def handle_CBinaryOp(cls, obj: CBinaryOp):
|
|
3698
|
+
def handle_CBinaryOp(self, obj: CBinaryOp):
|
|
3723
3699
|
obj = super().handle_CBinaryOp(obj)
|
|
3724
3700
|
while True:
|
|
3725
|
-
new_lhs =
|
|
3701
|
+
new_lhs = self.collapse(obj.common_type, obj.lhs)
|
|
3726
3702
|
if (
|
|
3727
3703
|
new_lhs is not obj.lhs
|
|
3728
3704
|
and CBinaryOp.compute_common_type(obj.op, new_lhs.type, obj.rhs.type) == obj.common_type
|
|
3729
3705
|
):
|
|
3730
3706
|
obj.lhs = new_lhs
|
|
3731
3707
|
else:
|
|
3732
|
-
new_rhs =
|
|
3708
|
+
new_rhs = self.collapse(obj.common_type, obj.rhs)
|
|
3733
3709
|
if (
|
|
3734
3710
|
new_rhs is not obj.rhs
|
|
3735
3711
|
and CBinaryOp.compute_common_type(obj.op, obj.lhs.type, new_rhs.type) == obj.common_type
|
|
@@ -3739,11 +3715,10 @@ class MakeTypecastsImplicit(CStructuredCodeWalker):
|
|
|
3739
3715
|
break
|
|
3740
3716
|
return obj
|
|
3741
3717
|
|
|
3742
|
-
|
|
3743
|
-
def handle_CTypeCast(cls, obj: CTypeCast):
|
|
3718
|
+
def handle_CTypeCast(self, obj: CTypeCast):
|
|
3744
3719
|
# note that the expression that this method returns may no longer be a CTypeCast
|
|
3745
3720
|
obj = super().handle_CTypeCast(obj)
|
|
3746
|
-
inner =
|
|
3721
|
+
inner = self.collapse(obj.dst_type, obj.expr)
|
|
3747
3722
|
if inner is not obj.expr:
|
|
3748
3723
|
obj.src_type = inner.type
|
|
3749
3724
|
obj.expr = inner
|
|
@@ -3753,12 +3728,11 @@ class MakeTypecastsImplicit(CStructuredCodeWalker):
|
|
|
3753
3728
|
|
|
3754
3729
|
|
|
3755
3730
|
class FieldReferenceCleanup(CStructuredCodeWalker):
|
|
3756
|
-
|
|
3757
|
-
def handle_CTypeCast(cls, obj):
|
|
3731
|
+
def handle_CTypeCast(self, obj):
|
|
3758
3732
|
if isinstance(obj.dst_type, SimTypePointer) and not isinstance(obj.dst_type.pts_to, SimTypeBottom):
|
|
3759
3733
|
obj = obj.codegen._access_reference(obj.expr, obj.dst_type.pts_to)
|
|
3760
3734
|
if not isinstance(obj, CTypeCast):
|
|
3761
|
-
return
|
|
3735
|
+
return self.handle(obj)
|
|
3762
3736
|
return super().handle_CTypeCast(obj)
|
|
3763
3737
|
|
|
3764
3738
|
|
|
@@ -3776,8 +3750,7 @@ class PointerArithmeticFixer(CStructuredCodeWalker):
|
|
|
3776
3750
|
a_ptr = a_ptr + 1.
|
|
3777
3751
|
"""
|
|
3778
3752
|
|
|
3779
|
-
|
|
3780
|
-
def handle_CBinaryOp(cls, obj):
|
|
3753
|
+
def handle_CBinaryOp(self, obj):
|
|
3781
3754
|
obj: CBinaryOp = super().handle_CBinaryOp(obj)
|
|
3782
3755
|
if (
|
|
3783
3756
|
obj.op in ("Add", "Sub")
|
|
@@ -569,7 +569,10 @@ def peephole_optimize_stmts(block, stmt_opts):
|
|
|
569
569
|
statements = []
|
|
570
570
|
|
|
571
571
|
# run statement optimizers
|
|
572
|
-
|
|
572
|
+
# note that an optimizer may optionally edit or remove statements whose statement IDs are greater than stmt_idx
|
|
573
|
+
stmt_idx = 0
|
|
574
|
+
while stmt_idx < len(block.statements):
|
|
575
|
+
stmt = block.statements[stmt_idx]
|
|
573
576
|
old_stmt = stmt
|
|
574
577
|
redo = True
|
|
575
578
|
while redo:
|
|
@@ -587,6 +590,7 @@ def peephole_optimize_stmts(block, stmt_opts):
|
|
|
587
590
|
any_update = True
|
|
588
591
|
else:
|
|
589
592
|
statements.append(old_stmt)
|
|
593
|
+
stmt_idx += 1
|
|
590
594
|
|
|
591
595
|
return statements, any_update
|
|
592
596
|
|
|
@@ -45,6 +45,7 @@ class NewFunctionHandler(FunctionHandler):
|
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
47
|
def __init__(self, max_addr=None, new_func_addr=None, project=None):
|
|
48
|
+
super().__init__()
|
|
48
49
|
self.max_addr = max_addr
|
|
49
50
|
|
|
50
51
|
# this is a map between an object addr outside the mapped binary and PossibleObject instance
|
|
@@ -104,16 +105,20 @@ class NewFunctionHandler(FunctionHandler):
|
|
|
104
105
|
data.depends(memory_location, value=MultiValues(offset_to_values=offset_to_values))
|
|
105
106
|
self.max_addr += size
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
108
|
+
else:
|
|
109
|
+
if self.project.kb.functions.contains_addr(function_address):
|
|
110
|
+
func = self.project.kb.functions.get_by_addr(function_address)
|
|
111
|
+
if func is not None and "ctor" in func.demangled_name:
|
|
112
|
+
# check if rdi has a possible this pointer/ object address, if so then we can assign this object
|
|
113
|
+
# this class
|
|
114
|
+
# also if the func is a constructor(not stripped binaries)
|
|
115
|
+
for addr, possible_object in self.possible_objects_dict.items():
|
|
116
|
+
v1 = state.registers.load(72, state.arch.bits // state.arch.byte_width).one_value()
|
|
117
|
+
obj_addr = v1.concrete_value if v1 is not None and v1.concrete else None
|
|
118
|
+
if obj_addr is not None and addr == obj_addr:
|
|
119
|
+
col_ind = self.project.kb.functions[function_address].demangled_name.rfind("::")
|
|
120
|
+
class_name = self.project.kb.functions[function_address].demangled_name[:col_ind]
|
|
121
|
+
possible_object.class_name = class_name
|
|
117
122
|
|
|
118
123
|
|
|
119
124
|
class StaticObjectFinder(Analysis):
|
|
@@ -209,6 +209,20 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
209
209
|
|
|
210
210
|
raise NotImplementedError("_merge_states() is not implemented.")
|
|
211
211
|
|
|
212
|
+
def _compare_states(self, node: NodeType, old_state: AnalysisState, new_state: AnalysisState) -> bool:
|
|
213
|
+
"""
|
|
214
|
+
Determine if the analysis has reached fixed point at `node`.
|
|
215
|
+
|
|
216
|
+
You can override this method to implement a faster _compare_states() method.
|
|
217
|
+
|
|
218
|
+
:param node: The node that has been analyzed.
|
|
219
|
+
:param old_state: The original output state out of node.
|
|
220
|
+
:param new_state: The new output state out of node.
|
|
221
|
+
:return: True if the analysis has reached fixed at node. False otherwise.
|
|
222
|
+
"""
|
|
223
|
+
_, has_no_changes = self._merge_states(node, old_state, new_state)
|
|
224
|
+
return has_no_changes
|
|
225
|
+
|
|
212
226
|
def _widen_states(self, *states: AnalysisState) -> AnalysisState:
|
|
213
227
|
raise NotImplementedError("_widen_states() is not implemented.")
|
|
214
228
|
|
|
@@ -288,7 +302,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
|
|
|
288
302
|
reached_fixedpoint = False
|
|
289
303
|
else:
|
|
290
304
|
# is the output state the same as the old one?
|
|
291
|
-
|
|
305
|
+
reached_fixedpoint = self._compare_states(n, self._output_state[self._node_key(n)], output_state)
|
|
292
306
|
self._output_state[self._node_key(n)] = output_state
|
|
293
307
|
|
|
294
308
|
if not reached_fixedpoint:
|
|
@@ -1221,6 +1221,8 @@ class SimEnginePropagatorAIL(
|
|
|
1221
1221
|
bits=expr.bits,
|
|
1222
1222
|
floating_point=expr.floating_point,
|
|
1223
1223
|
rounding_mode=expr.rounding_mode,
|
|
1224
|
+
from_bits=expr.from_bits,
|
|
1225
|
+
to_bits=expr.to_bits,
|
|
1224
1226
|
**expr.tags,
|
|
1225
1227
|
)
|
|
1226
1228
|
return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
|