angr 9.2.156__cp310-cp310-manylinux2014_aarch64.whl → 9.2.157__cp310-cp310-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/cfg/cfg_base.py +87 -71
- angr/analyses/cfg/cfg_fast.py +5 -0
- angr/analyses/decompiler/clinic.py +182 -104
- angr/analyses/decompiler/decompiler.py +11 -0
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +1 -1
- angr/analyses/decompiler/structured_codegen/c.py +18 -5
- angr/analyses/disassembly.py +5 -11
- angr/analyses/s_propagator.py +2 -4
- angr/analyses/stack_pointer_tracker.py +3 -7
- angr/analyses/typehoon/simple_solver.py +3 -3
- angr/analyses/variable_recovery/engine_base.py +2 -8
- angr/analyses/variable_recovery/variable_recovery.py +4 -3
- angr/calling_conventions.py +3 -3
- angr/engines/hook.py +1 -1
- angr/engines/icicle.py +229 -0
- angr/engines/pcode/behavior.py +1 -4
- angr/engines/pcode/emulate.py +1 -4
- angr/engines/pcode/lifter.py +2 -10
- angr/engines/vex/claripy/irop.py +2 -2
- angr/knowledge_plugins/functions/function.py +18 -10
- angr/knowledge_plugins/functions/function_manager.py +68 -5
- angr/knowledge_plugins/variables/variable_manager.py +15 -3
- angr/rustylib.cpython-310-aarch64-linux-gnu.so +0 -0
- angr/sim_variable.py +31 -0
- angr/storage/memory_mixins/address_concretization_mixin.py +2 -2
- angr/storage/memory_mixins/convenient_mappings_mixin.py +1 -1
- {angr-9.2.156.dist-info → angr-9.2.157.dist-info}/METADATA +7 -8
- {angr-9.2.156.dist-info → angr-9.2.157.dist-info}/RECORD +33 -33
- {angr-9.2.156.dist-info → angr-9.2.157.dist-info}/WHEEL +1 -1
- angr/rustylib.pyi +0 -165
- {angr-9.2.156.dist-info → angr-9.2.157.dist-info}/entry_points.txt +0 -0
- {angr-9.2.156.dist-info → angr-9.2.157.dist-info}/licenses/LICENSE +0 -0
- {angr-9.2.156.dist-info → angr-9.2.157.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/analyses/cfg/cfg_base.py
CHANGED
|
@@ -1147,7 +1147,8 @@ class CFGBase(Analysis):
|
|
|
1147
1147
|
graph = self.graph
|
|
1148
1148
|
|
|
1149
1149
|
smallest_nodes = {} # indexed by end address of the node
|
|
1150
|
-
|
|
1150
|
+
end_addr_to_node = {} # a dictionary from node key to node *if* only one node exists for the key
|
|
1151
|
+
end_addr_to_nodes = defaultdict(list) # a dictionary from node key to nodes *if* more than one node exist
|
|
1151
1152
|
|
|
1152
1153
|
for n in graph.nodes():
|
|
1153
1154
|
if n.is_simprocedure:
|
|
@@ -1155,76 +1156,89 @@ class CFGBase(Analysis):
|
|
|
1155
1156
|
end_addr = n.addr + n.size
|
|
1156
1157
|
key = (end_addr, n.callstack_key)
|
|
1157
1158
|
# add the new item
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1159
|
+
if key not in end_addr_to_node:
|
|
1160
|
+
# this is the first node of this key
|
|
1161
|
+
end_addr_to_node[key] = n
|
|
1162
|
+
else:
|
|
1163
|
+
# this is the 2nd+ node of this key
|
|
1164
|
+
if key not in end_addr_to_nodes:
|
|
1165
|
+
end_addr_to_nodes[key].append(end_addr_to_node[key])
|
|
1166
|
+
end_addr_to_nodes[key].append(n)
|
|
1167
|
+
|
|
1168
|
+
# update smallest_nodes
|
|
1169
|
+
for key, node in end_addr_to_node.items():
|
|
1170
|
+
if key in end_addr_to_nodes:
|
|
1171
|
+
continue
|
|
1172
|
+
smallest_nodes[key] = node
|
|
1173
|
+
del end_addr_to_node # micro memory optimization
|
|
1164
1174
|
|
|
1165
|
-
while
|
|
1175
|
+
while end_addr_to_nodes:
|
|
1166
1176
|
key_to_find = (None, None)
|
|
1167
|
-
for tpl
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1177
|
+
for tpl in list(end_addr_to_nodes):
|
|
1178
|
+
x = end_addr_to_nodes[tpl]
|
|
1179
|
+
if len(x) <= 1:
|
|
1180
|
+
continue
|
|
1181
|
+
key_to_find = tpl
|
|
1171
1182
|
|
|
1172
|
-
|
|
1173
|
-
|
|
1183
|
+
end_addr, callstack_key = key_to_find
|
|
1184
|
+
all_nodes = end_addr_to_nodes[key_to_find]
|
|
1174
1185
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1186
|
+
all_nodes = sorted(all_nodes, key=lambda node: node.addr, reverse=True)
|
|
1187
|
+
smallest_node = all_nodes[0] # take the one that has the highest address
|
|
1188
|
+
other_nodes = all_nodes[1:]
|
|
1178
1189
|
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1190
|
+
self._normalize_core(
|
|
1191
|
+
graph, callstack_key, smallest_node, other_nodes, smallest_nodes, end_addr_to_nodes
|
|
1192
|
+
)
|
|
1182
1193
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1194
|
+
del end_addr_to_nodes[key_to_find]
|
|
1195
|
+
# make sure the smallest node is stored in end_addresses
|
|
1196
|
+
smallest_nodes[key_to_find] = smallest_node
|
|
1197
|
+
|
|
1198
|
+
# corner case
|
|
1199
|
+
# sometimes two overlapping blocks may not end at the instruction. this might happen when one of the
|
|
1200
|
+
# blocks (the bigger one) hits the instruction count limit or bytes limit before reaching the end
|
|
1201
|
+
# address of the smaller block. in this case we manually pick up those blocks.
|
|
1202
|
+
if not end_addr_to_nodes:
|
|
1203
|
+
# find if there are still overlapping blocks
|
|
1204
|
+
sorted_smallest_nodes = defaultdict(list) # callstack_key is the key of this dict
|
|
1205
|
+
for k, node in smallest_nodes.items():
|
|
1206
|
+
_, callstack_key = k
|
|
1207
|
+
sorted_smallest_nodes[callstack_key].append(node)
|
|
1208
|
+
for k in sorted_smallest_nodes:
|
|
1209
|
+
sorted_smallest_nodes[k] = sorted(sorted_smallest_nodes[k], key=lambda node: node.addr)
|
|
1210
|
+
|
|
1211
|
+
for callstack_key, lst in sorted_smallest_nodes.items():
|
|
1212
|
+
lst_len = len(lst)
|
|
1213
|
+
for i, node in enumerate(lst):
|
|
1214
|
+
if i == lst_len - 1:
|
|
1215
|
+
break
|
|
1216
|
+
next_node = lst[i + 1]
|
|
1217
|
+
if node is not next_node and node.addr <= next_node.addr < node.addr + node.size:
|
|
1218
|
+
# umm, those nodes are overlapping, but they must have different end addresses
|
|
1219
|
+
nodekey_a = node.addr + node.size, callstack_key
|
|
1220
|
+
nodekey_b = next_node.addr + next_node.size, callstack_key
|
|
1221
|
+
if nodekey_a == nodekey_b:
|
|
1222
|
+
# error handling: this will only happen if we have completely overlapping nodes
|
|
1223
|
+
# caused by different jumps (one of the jumps is probably incorrect), which usually
|
|
1224
|
+
# indicates an error in CFG recovery. we print a warning and skip this node
|
|
1225
|
+
l.warning(
|
|
1226
|
+
"Found completely overlapping nodes %s. It usually indicates an error in CFG "
|
|
1227
|
+
"recovery. Skip.",
|
|
1228
|
+
node,
|
|
1229
|
+
)
|
|
1230
|
+
continue
|
|
1231
|
+
|
|
1232
|
+
if nodekey_a in smallest_nodes and nodekey_b in smallest_nodes:
|
|
1233
|
+
# misuse end_addresses_to_nodes
|
|
1234
|
+
key = node.addr + node.size, callstack_key
|
|
1235
|
+
if node not in end_addr_to_nodes[key]:
|
|
1236
|
+
end_addr_to_nodes[key].append(node)
|
|
1237
|
+
if next_node not in end_addr_to_nodes[key]:
|
|
1238
|
+
end_addr_to_nodes[key].append(next_node)
|
|
1239
|
+
|
|
1240
|
+
smallest_nodes.pop(nodekey_a, None)
|
|
1241
|
+
smallest_nodes.pop(nodekey_b, None)
|
|
1228
1242
|
|
|
1229
1243
|
self.normalized = True
|
|
1230
1244
|
|
|
@@ -1235,7 +1249,7 @@ class CFGBase(Analysis):
|
|
|
1235
1249
|
smallest_node,
|
|
1236
1250
|
other_nodes,
|
|
1237
1251
|
smallest_nodes,
|
|
1238
|
-
|
|
1252
|
+
end_addr_to_nodes,
|
|
1239
1253
|
):
|
|
1240
1254
|
# Break other nodes
|
|
1241
1255
|
for n in other_nodes:
|
|
@@ -1254,8 +1268,8 @@ class CFGBase(Analysis):
|
|
|
1254
1268
|
# the logic below is a little convoluted. we check if key exists in either end_address_to_nodes or
|
|
1255
1269
|
# smallest_nodes, since we don't always add the new node back to end_addresses_to_nodes dict - we only do so
|
|
1256
1270
|
# when there are more than one node with that key.
|
|
1257
|
-
if key in
|
|
1258
|
-
new_node = next((i for i in
|
|
1271
|
+
if key in end_addr_to_nodes:
|
|
1272
|
+
new_node = next((i for i in end_addr_to_nodes[key] if i.addr == n.addr), None)
|
|
1259
1273
|
if new_node is None and key in smallest_nodes and smallest_nodes[key].addr == n.addr:
|
|
1260
1274
|
new_node = smallest_nodes[key]
|
|
1261
1275
|
|
|
@@ -1304,8 +1318,10 @@ class CFGBase(Analysis):
|
|
|
1304
1318
|
|
|
1305
1319
|
# Put the new node into end_addresses list
|
|
1306
1320
|
if key in smallest_nodes:
|
|
1307
|
-
|
|
1308
|
-
|
|
1321
|
+
if smallest_nodes[key] not in end_addr_to_nodes[key]:
|
|
1322
|
+
end_addr_to_nodes[key].append(smallest_nodes[key])
|
|
1323
|
+
if new_node not in end_addr_to_nodes[key]:
|
|
1324
|
+
end_addr_to_nodes[key].append(new_node)
|
|
1309
1325
|
else:
|
|
1310
1326
|
smallest_nodes[key] = new_node
|
|
1311
1327
|
|
|
@@ -1936,7 +1952,7 @@ class CFGBase(Analysis):
|
|
|
1936
1952
|
# skip empty blocks (that are usually caused by lifting failures)
|
|
1937
1953
|
continue
|
|
1938
1954
|
block = func_0.get_block(block_node.addr, block_node.size)
|
|
1939
|
-
if block.
|
|
1955
|
+
if block.vex_nostmt.jumpkind not in ("Ijk_Boring", "Ijk_InvalICache"):
|
|
1940
1956
|
continue
|
|
1941
1957
|
# Skip alignment blocks
|
|
1942
1958
|
if self._is_noop_block(self.project.arch, block):
|
angr/analyses/cfg/cfg_fast.py
CHANGED
|
@@ -2841,6 +2841,11 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2841
2841
|
def _process_irsb_data_refs(self, irsb_addr, data_refs):
|
|
2842
2842
|
assumption = self._decoding_assumptions.get(irsb_addr & ~1)
|
|
2843
2843
|
for ref in data_refs:
|
|
2844
|
+
# data_addr + data_size might overflow; we ignore such cases
|
|
2845
|
+
max_addr = 0xFFFF_FFFF if self.project.arch.bits == 32 else 0xFFFF_FFFF_FFFF_FFFF
|
|
2846
|
+
if ref.data_addr + ref.data_size > max_addr:
|
|
2847
|
+
continue
|
|
2848
|
+
|
|
2844
2849
|
if ref.data_type_str == "integer(store)":
|
|
2845
2850
|
data_type_str = "integer"
|
|
2846
2851
|
is_store = True
|