Skip to content

Commit db089a1

Browse files
committed
fix: pointer subclassing now uses correct size for arithmetic operations
1 parent 5bafce7 commit db089a1

2 files changed

Lines changed: 23 additions & 2 deletions

File tree

libdestruct/common/ptr/ptr.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ def _element_size(self: ptr) -> int:
149149
def __add__(self: ptr, n: int) -> ptr:
150150
"""Return a new pointer advanced by n elements."""
151151
new_addr = self.get() + n * self._element_size
152-
return ptr(_ArithmeticResolver(self.resolver, new_addr), self.wrapper)
152+
return type(self)(_ArithmeticResolver(self.resolver, new_addr), self.wrapper)
153153

154154
def __sub__(self: ptr, n: int) -> ptr:
155155
"""Return a new pointer retreated by n elements."""
156156
new_addr = self.get() - n * self._element_size
157-
return ptr(_ArithmeticResolver(self.resolver, new_addr), self.wrapper)
157+
return type(self)(_ArithmeticResolver(self.resolver, new_addr), self.wrapper)
158158

159159
def __getitem__(self: ptr, n: int) -> obj:
160160
"""Return the object at index n relative to this pointer."""

test/scripts/types_test.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,5 +970,26 @@ def test_unwrap_bytes_returns_live_data(self):
970970
self.assertEqual(p.unwrap(4), b"BBBB")
971971

972972

973+
class PtrArithmeticSubclassTest(unittest.TestCase):
974+
"""Pointer arithmetic must preserve subclass identity (e.g. for narrower pointer widths)."""
975+
976+
def test_add_returns_same_subclass(self):
977+
class ptr32(ptr):
978+
size: int = 4
979+
980+
memory = bytearray(32)
981+
p = ptr32(MemoryResolver(memory, 0), c_int)
982+
self.assertIsInstance(p + 1, ptr32)
983+
self.assertEqual((p + 1).size, 4)
984+
985+
def test_sub_returns_same_subclass(self):
986+
class ptr32(ptr):
987+
size: int = 4
988+
989+
memory = bytearray(32)
990+
p = ptr32(MemoryResolver(memory, 0), c_int)
991+
self.assertIsInstance(p - 1, ptr32)
992+
993+
973994
if __name__ == "__main__":
974995
unittest.main()

0 commit comments

Comments
 (0)