Skip to content

Commit 13bf505

Browse files
committed
leverage the existing Array facility
1 parent 4009c6b commit 13bf505

File tree

1 file changed

+31
-34
lines changed

1 file changed

+31
-34
lines changed

volatility3/framework/objects/utility.py

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
#
44

55
import re
6-
7-
from typing import List, Optional, Union
6+
import logging
7+
from typing import Optional, Union
88

99
from volatility3.framework import interfaces, objects, constants, exceptions
1010

11+
vollog = logging.getLogger(__name__)
12+
1113

1214
def rol(value: int, count: int, max_bits: int = 64) -> int:
1315
"""A rotate-left instruction in Python"""
@@ -254,51 +256,46 @@ def array_of_pointers(
254256

255257
def dynamically_sized_array_of_pointers(
256258
context: interfaces.context.ContextInterface,
257-
layer_name: str,
258-
symbol_table_name: str,
259-
array_offset: int,
259+
array: interfaces.objects.ObjectInterface,
260+
iterator_guard_value: int,
261+
subtype: Union[str, interfaces.objects.Template],
260262
stop_value: int = 0,
261-
iterator_guard_value: int = None,
262263
stop_on_invalid_pointers: bool = True,
263-
) -> List[interfaces.objects.ObjectInterface]:
264+
) -> interfaces.objects.ObjectInterface:
264265
"""Iterates over a dynamically sized array of pointers (e.g. NULL-terminated).
266+
Array iteration should always be performed with an arbitrary guard value as maximum size,
267+
to prevent running forever in case something unexpected happens.
265268
266269
Args:
267270
context: The context on which to operate.
268-
layer_name: The layer on which the array should be constructed.
269-
symbol_table_name: The symbol table to use to construct object types.
270-
array_offset: The array offset within the layer, from which to start iterating.
271-
stop_value: Stop value used to determine when to terminate iteration once it is encountered. Defaults to 0 (NULL-terminated arrays).
271+
array: The object to cast to an array.
272272
iterator_guard_value: Stop iterating when the iterator index is greater than this value. This is an extra-safety against smearing.
273+
subtype: The subtype of the array's pointers.
274+
stop_value: Stop value used to determine when to terminate iteration once it is encountered. Defaults to 0 (NULL-terminated arrays).
273275
stop_on_invalid_pointers: Determines whether to stop iterating or not when an invalid pointer is encountered. This can be useful for arrays
274276
that are known to have smeared entries before the end.
275277
276278
Returns:
277279
An array of pointer objects
278280
"""
279-
pointer_type = context.symbol_space.get_type(
280-
symbol_table_name + constants.BANG + "pointer"
281-
)
282-
entry = context.object(
283-
pointer_type,
284-
layer_name=layer_name,
285-
offset=array_offset,
286-
)
287-
i = 0
288-
array = []
289-
# entry and entry.vol.offset aren't the same thing, as
290-
# - entry is naturally represented by the address that the pointer refers to;
291-
# - entry.vol.offset is the offset at which the pointer lives.
292-
while entry != stop_value:
293-
if (not entry.is_readable() and stop_on_invalid_pointers) or (
294-
iterator_guard_value is not None and i >= iterator_guard_value
281+
new_count = 0
282+
for entry in array_of_pointers(
283+
array=array, count=iterator_guard_value, subtype=subtype, context=context
284+
):
285+
# "entry" is naturally represented by the address that the pointer refers to
286+
if (entry == stop_value) or (
287+
not entry.is_readable() and stop_on_invalid_pointers
295288
):
296289
break
297-
array.append(entry)
298-
entry = context.object(
299-
pointer_type,
300-
layer_name=layer_name,
301-
offset=entry.vol.offset + pointer_type.size,
290+
new_count += 1
291+
else:
292+
vollog.log(
293+
constants.LOGLEVEL_V,
294+
f"""Iterator guard value {iterator_guard_value} reached while iterating over array at offset {array.vol.offset:#x}.\
295+
This means that there is a bug (e.g. smearing) with this array, or that it may contain valid entries past the iterator guard value.""",
302296
)
303-
i += 1
304-
return array
297+
298+
# Leverage the "Array" object instead of returning a Python list
299+
return array_of_pointers(
300+
array=array, count=new_count, subtype=subtype, context=context
301+
)

0 commit comments

Comments
 (0)