Source code for memobj.property.pointer

from copy import copy
from typing import TYPE_CHECKING, Any, Union

from . import MemoryProperty

if TYPE_CHECKING:
    from memobj.object import MemoryObject


[docs] class Void(MemoryProperty):
[docs] def from_memory(self) -> Any: raise TypeError("cannot read void from memory")
[docs] def to_memory(self, value: Any): raise TypeError("cannot write void to memory")
[docs] def memory_size(self) -> int: return 0
[docs] class Pointer(MemoryProperty): def __init__( self, offset: int | None, pointed_type: Union[str, MemoryProperty, "MemoryObject", type["MemoryObject"]], ): super().__init__(offset) self._pointed_type = pointed_type def _get_prelude(self, preluder: "MemoryObject"): self.memory_object = preluder return self def _set_prelude(self, preluder: "MemoryObject", value): self.memory_object = preluder self.to_memory_deref(value)
[docs] @staticmethod def is_null(addr: int) -> bool: return addr == 0
[docs] def handle_null(self) -> Any: raise ValueError("null pointer cannot be dereferenced")
[docs] def cast(self, new_type: Union[MemoryProperty, "MemoryObject"]) -> "Pointer": # New pointer to same address but with changed type. return Pointer(self.offset, new_type)
[docs] def from_memory(self) -> Any: return self.read_formatted_from_offset(self.pointer_format_string)
[docs] def from_memory_deref(self) -> Any: addr = self.from_memory() if self.is_null(addr): return self.handle_null() # circular import bs from memobj import MemoryObject from memobj.object import MemoryObjectMeta if isinstance(self._pointed_type, MemoryObject): # this is so returned instance isn't overwritten instance = copy(self._pointed_type) instance._base_address = addr instance.memobj_process = self.process return instance elif type(self._pointed_type) is MemoryObjectMeta: return self._pointed_type(address=addr, process=self.process) elif isinstance(self._pointed_type, str): # noinspection PyProtectedMember typed_object_type = MemoryObject._resolve_string_class_lookup( self._pointed_type ) self._pointed_type = typed_object_type() self._pointed_type._base_address = addr self._pointed_type.memobj_process = self.process return self._pointed_type elif isinstance(self._pointed_type, Pointer): self._pointed_type.memory_object = MemoryObject( address=addr, process=self.process, ) return self._pointed_type elif isinstance(self._pointed_type, MemoryProperty): # create a mock object at the address self._pointed_type.memory_object = MemoryObject( address=addr, process=self.process, ) self._pointed_type.offset = 0 return self._pointed_type.from_memory() else: raise TypeError( "pointed-to type is neither MemoryObject nor MemoryProperty" )
[docs] def to_memory(self, value: Any): if not isinstance(value, int): raise TypeError("expected an integer address to write") self.write_formatted_to_offset(self.pointer_format_string, value)
[docs] def to_memory_deref(self, value: Any): addr = self.from_memory() if self.is_null(addr): raise ValueError("null pointer cannot be dereferenced") # circular import bs from memobj import MemoryObject from memobj.object import MemoryObjectMeta if isinstance(self._pointed_type, MemoryObject): if not isinstance(value, type(self._pointed_type)): raise TypeError(f"{value!r} incompatible with {self._pointed_type!r}") self._pointed_type._base_address = addr self._pointed_type.memobj_process = self.process for attribute_name in self._pointed_type.__memory_properties__.keys(): setattr( self._pointed_type, attribute_name, getattr(value, attribute_name) ) # TODO: is there a better way to check for this elif type(self._pointed_type) is MemoryObjectMeta: instance = self._pointed_type(address=addr, process=self.process) for attribute_name in self._pointed_type.__memory_properties__.keys(): setattr(instance, attribute_name, getattr(value, attribute_name)) elif isinstance(self._pointed_type, str): # noinspection PyProtectedMember typed_object_type = MemoryObject._resolve_string_class_lookup( self._pointed_type ) self._pointed_type = typed_object_type instance = self._pointed_type(address=addr, process=self.process) for attribute_name in self._pointed_type.__memory_properties__.keys(): setattr(instance, attribute_name, getattr(value, attribute_name)) elif isinstance(self._pointed_type, MemoryProperty): self._pointed_type.memory_object = MemoryObject( address=addr, process=self.process, ) self._pointed_type.offset = 0 self._pointed_type.to_memory(value) else: raise TypeError( "pointed-to type is neither MemoryObject nor MemoryProperty" )
[docs] def memory_size(self) -> int: return self.pointer_size
[docs] class DereffedPointer(Pointer): def _get_prelude(self, preluder: "MemoryObject"): self.memory_object = preluder return self.from_memory_deref() def _set_prelude(self, preluder: "MemoryObject", value): self.memory_object = preluder self.to_memory_deref(value)
[docs] def handle_null(self): return None