File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -317,9 +317,6 @@ cdef class Unpacker:
317317 cdef Py_ssize_t max_buffer_size
318318 cdef uint64_t stream_offset
319319
320- def __cinit__(self):
321- self.buf = NULL
322-
323320 def __dealloc__ (self ):
324321 unpack_clear(& self .ctx)
325322 PyMem_Free(self .buf)
@@ -338,6 +335,12 @@ cdef class Unpacker:
338335 Py_ssize_t max_ext_len = - 1 ):
339336 cdef const char * cerr= NULL
340337
338+ unpack_clear(& self .ctx)
339+ unpack_init(& self .ctx)
340+ if self .buf != NULL :
341+ PyMem_Free(self .buf)
342+ self .buf = NULL
343+
341344 self .object_hook = object_hook
342345 self .object_pairs_hook = object_pairs_hook
343346 self .list_hook = list_hook
Original file line number Diff line number Diff line change 1+ import gc
12import sys
3+ import weakref
24from io import BytesIO
35
46from pytest import mark, raises
@@ -87,3 +89,37 @@ def test_unpacker_tell_read_bytes():
8789 assert obj == unp
8890 assert pos == unpacker.tell()
8991 assert unpacker.read_bytes(n) == raw
92+
93+
94+ @mark.skipif(
95+ Unpacker.__module__ == "msgpack.fallback",
96+ reason="specific to C extension reinit leak",
97+ )
98+ def test_unpacker_reinit_clears_partial_state():
99+ refs = []
100+
101+ class Marker:
102+ pass
103+
104+ def hook(code, data):
105+ obj = Marker()
106+ refs.append(weakref.ref(obj))
107+ return obj
108+
109+ unpacker = Unpacker(ext_hook=hook, strict_map_key=False)
110+ # Keep parser state mid-map with a live key object from ext_hook.
111+ # Encodes: [ {ExtType(1, b"a"): <missing value>} ].
112+ unpacker.feed(b"\x91\x81\xd4\x01a")
113+ with raises(OutOfData):
114+ unpacker.unpack()
115+ assert len(refs) == 1
116+ assert refs[0]() is not None
117+
118+ unpacker.__init__()
119+ gc.collect()
120+ assert refs[0]() is None
121+ with raises(OutOfData):
122+ unpacker.unpack()
123+
124+ unpacker.feed(packb({"a": 1}))
125+ assert unpacker.unpack() == {"a": 1}
You can’t perform that action at this time.
0 commit comments