mirror of
https://github.com/msgpack/msgpack-python.git
synced 2026-06-19 06:02:09 +00:00
Fix Unpacker __init__ re-entry cleanup leaks
This commit is contained in:
parent
6afc0cc2ed
commit
ffc1b206db
2 changed files with 43 additions and 0 deletions
|
|
@ -319,6 +319,7 @@ cdef class Unpacker:
|
|||
|
||||
def __cinit__(self):
|
||||
self.buf = NULL
|
||||
unpack_init(&self.ctx)
|
||||
|
||||
def __dealloc__(self):
|
||||
unpack_clear(&self.ctx)
|
||||
|
|
@ -338,6 +339,12 @@ cdef class Unpacker:
|
|||
Py_ssize_t max_ext_len=-1):
|
||||
cdef const char *cerr=NULL
|
||||
|
||||
unpack_clear(&self.ctx)
|
||||
unpack_init(&self.ctx)
|
||||
if self.buf != NULL:
|
||||
PyMem_Free(self.buf)
|
||||
self.buf = NULL
|
||||
|
||||
self.object_hook = object_hook
|
||||
self.object_pairs_hook = object_pairs_hook
|
||||
self.list_hook = list_hook
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import gc
|
||||
import sys
|
||||
import weakref
|
||||
from io import BytesIO
|
||||
|
||||
from pytest import mark, raises
|
||||
|
|
@ -87,3 +89,37 @@ def test_unpacker_tell_read_bytes():
|
|||
assert obj == unp
|
||||
assert pos == unpacker.tell()
|
||||
assert unpacker.read_bytes(n) == raw
|
||||
|
||||
|
||||
@mark.skipif(
|
||||
Unpacker.__module__ == "msgpack.fallback",
|
||||
reason="specific to C extension reinit leak",
|
||||
)
|
||||
def test_unpacker_reinit_clears_partial_state():
|
||||
refs = []
|
||||
|
||||
class Marker:
|
||||
pass
|
||||
|
||||
def hook(code, data):
|
||||
obj = Marker()
|
||||
refs.append(weakref.ref(obj))
|
||||
return obj
|
||||
|
||||
unpacker = Unpacker(ext_hook=hook, strict_map_key=False)
|
||||
# Keep parser state mid-map with a live key object from ext_hook.
|
||||
# Encodes: [ {ExtType(1, b"a"): <missing value>} ].
|
||||
unpacker.feed(b"\x91\x81\xd4\x01a")
|
||||
with raises(OutOfData):
|
||||
unpacker.unpack()
|
||||
assert len(refs) == 1
|
||||
assert refs[0]() is not None
|
||||
|
||||
unpacker.__init__()
|
||||
gc.collect()
|
||||
assert refs[0]() is None
|
||||
with raises(OutOfData):
|
||||
unpacker.unpack()
|
||||
|
||||
unpacker.feed(packb({"a": 1}))
|
||||
assert unpacker.unpack() == {"a": 1}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue