Skip to content

Commit 60ebfe0

Browse files
committed
fix: correct various problems in the codebase
1 parent 617abe2 commit 60ebfe0

19 files changed

Lines changed: 464 additions & 30 deletions

libdestruct/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
except ImportError: # pragma: no cover
1212
pass
1313

14+
from libdestruct.backing.resolver import Resolver
1415
from libdestruct.c import c_int, c_long, c_str, c_uint, c_ulong
1516
from libdestruct.common.array import array, array_of
1617
from libdestruct.common.attributes import offset
1718
from libdestruct.common.enum import enum, enum_of
18-
from libdestruct.common.ptr import ptr
19+
from libdestruct.common.ptr.ptr import ptr
1920
from libdestruct.common.struct import ptr_to, ptr_to_self, struct
2021
from libdestruct.libdestruct import inflate, inflater
2122

@@ -35,5 +36,6 @@
3536
"ptr",
3637
"ptr_to",
3738
"ptr_to_self",
39+
"Resolver",
3840
"struct",
3941
]

libdestruct/backing/fake_resolver.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
class FakeResolver(Resolver):
1313
"""A class that can resolve elements in a simulated memory storage."""
1414

15-
def __init__(self: FakeResolver, memory: dict | None = None, address: int | None = 0) -> FakeResolver:
15+
def __init__(self: FakeResolver, memory: dict | None = None, address: int | None = 0) -> None:
1616
"""Initializes a basic fake resolver."""
1717
self.memory = memory if memory is not None else {}
1818
self.address = address
@@ -47,7 +47,7 @@ def resolve(self: FakeResolver, size: int, _: int) -> bytes:
4747
result = b""
4848

4949
while size:
50-
page = self.memory.get(page_address, b"\x00" * (0x1000 - page_offset))
50+
page = self.memory.get(page_address, b"\x00" * 0x1000)
5151
page_size = min(size, 0x1000 - page_offset)
5252
result += page[page_offset : page_offset + page_size]
5353
size -= page_size

libdestruct/backing/memory_resolver.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
class MemoryResolver(Resolver):
1818
"""A class that can resolve itself to a value in a referenced memory storage."""
1919

20-
def __init__(self: MemoryResolver, memory: MutableSequence, address: int | None) -> MemoryResolver:
20+
def __init__(self: MemoryResolver, memory: MutableSequence, address: int | None) -> None:
2121
"""Initializes a basic memory resolver."""
2222
self.memory = memory
2323
self.address = address
@@ -38,7 +38,7 @@ def relative_from_own(self: MemoryResolver, address_offset: int, _: int) -> Memo
3838
new_resolver.offset = address_offset
3939
return new_resolver
4040

41-
def absolute_from_own(self: Resolver, address: int) -> MemoryResolver:
41+
def absolute_from_own(self: MemoryResolver, address: int) -> MemoryResolver:
4242
"""Creates a resolver that has an absolute reference to an object, from the parent's view."""
4343
return MemoryResolver(self.memory, address)
4444

@@ -47,7 +47,7 @@ def resolve(self: MemoryResolver, size: int, _: int) -> bytes:
4747
address = self.resolve_address()
4848
return self.memory[address : address + size]
4949

50-
def modify(self: Resolver, size: int, _: int, value: bytes) -> None:
50+
def modify(self: MemoryResolver, size: int, _: int, value: bytes) -> None:
5151
"""Modifies itself in memory."""
5252
address = self.resolve_address()
5353
self.memory[address : address + size] = value

libdestruct/c/c_str.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get(self: c_str, index: int = -1) -> bytes:
3232
if index == -1:
3333
return self.resolver.resolve(self.count(), 0)
3434

35-
return bytes([self.resolver.resolve(index)[-1]])
35+
return bytes([self.resolver.resolve(index + 1, 0)[-1]])
3636

3737
def to_bytes(self: c_str) -> bytes:
3838
"""Return the serialized representation of the object."""
@@ -50,6 +50,10 @@ def _set(self: c_str, value: bytes, index: int = -1) -> None:
5050
prev = self.resolver.resolve(index, 0)
5151
self.resolver.modify(index + len(value), 0, prev + value)
5252

53+
def __setitem__(self: c_str, index: int, value: bytes) -> None:
54+
"""Set the character at the given index to the given value."""
55+
self._set(value, index)
56+
5357
def __iter__(self: c_str) -> iter:
5458
"""Return an iterator over the string."""
5559
for i in range(self.count()):

libdestruct/c/ctypes_generic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ def _set(self: _ctypes_generic, value: Any) -> None:
3434
def to_bytes(self: _ctypes_generic) -> bytes:
3535
"""Serialize the type to bytes."""
3636
if self._frozen:
37-
return bytes(self._frozen_value)
37+
return bytes(self.backing_type(self._frozen_value))
3838

3939
return self.resolver.resolve(self.size, 0)

libdestruct/c/struct_parser.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ def ptr_to_type(ptr: c_ast.PtrDecl, parent: c_ast.Struct | None = None) -> type[
9696
if not isinstance(ptr, c_ast.PtrDecl):
9797
raise TypeError("Definition must be a pointer.")
9898

99+
# Handle nested pointers (e.g., int **pp) by recursively wrapping in ptr_to
100+
if isinstance(ptr.type, c_ast.PtrDecl):
101+
inner = ptr_to_type(ptr.type, parent)
102+
return ptr_to(inner)
103+
99104
if not isinstance(ptr.type, c_ast.TypeDecl):
100105
raise TypeError("Definition must be a type declaration.")
101106

libdestruct/common/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
# Copyright (c) 2024 Roberto Alessandro Bertolini. All rights reserved.
44
# Licensed under the MIT license. See LICENSE file in the project root for details.
55
#
6+
7+
import libdestruct.common.forward_ref_inflater

libdestruct/common/array/array.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def __len__(self: array) -> int:
2323
return self.count()
2424

2525
@abstractmethod
26-
def get(self: array, index: int) -> object:
27-
"""Return the element at the given index."""
26+
def get(self: array, index: int = -1) -> object:
27+
"""Return the element at the given index, or all elements if index is -1."""
2828

2929
def __getitem__(self: array, index: int) -> object:
3030
"""Return the element at the given index."""

libdestruct/common/array/array_impl.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ def count(self: array_impl) -> int:
4646
"""Get the size of the array."""
4747
return self._count
4848

49-
def get(self: array, index: int) -> object:
50-
"""Return the element at the given index."""
49+
def get(self: array, index: int = -1) -> object:
50+
"""Return the element at the given index, or all elements if index is -1."""
51+
if index == -1:
52+
return [self.backing_type(self.resolver.relative_from_own(i * self.item_size, 0)) for i in range(self._count)]
5153
return self.backing_type(self.resolver.relative_from_own(index * self.item_size, 0))
5254

5355
def _set(self: array_impl, _: list[obj]) -> None:

libdestruct/common/enum/enum.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,4 @@ def to_bytes(self: enum) -> bytes:
5959

6060
def to_str(self: obj, indent: int = 0) -> str:
6161
"""Return a string representation of the object."""
62-
return f"{' ' * indent}{self.get()!r}"
62+
return f"{self.get()!r}"

0 commit comments

Comments
 (0)