Harden `Unpacker.__init__` re-entry cleanup to prevent buffer/context leaks by Copilot · Pull Request #687 · msgpack/msgpack-python
Unpacker.__init__ did not safely handle repeated initialization: it replaced self.buf without freeing the previous allocation and reinitialized parser state without clearing in-flight stack objects. This PR makes re-entry cleanup explicit and deterministic.
-
Unpackerlifecycle cleanup- Initialize parser context in
__cinit__(unpack_init(&self.ctx)) so cleanup paths always operate on initialized state. - On every
__init__entry:- clear parse-stack state (
unpack_clear(&self.ctx)), - reset parser bookkeeping (
unpack_init(&self.ctx)), - free old internal buffer when present (
PyMem_Free(self.buf)), - null out the pointer before reallocating (
self.buf = NULL).
- clear parse-stack state (
- Initialize parser context in
-
Regression coverage for re-initialization
- Add a focused unpacker test that drives a mid-parse state (live object held in parse stack), re-calls
__init__, and asserts:- prior stack-held object is released,
- parser is reset to empty state,
- unpacker remains reusable for new input.
- Add a focused unpacker test that drives a mid-parse state (live object held in parse stack), re-calls
# __init__ re-entry prologue unpack_clear(&self.ctx) unpack_init(&self.ctx) if self.buf != NULL: PyMem_Free(self.buf) self.buf = NULL
Original prompt
Create a pull request in repository
msgpack/msgpack-pythonto fix the twoUnpacker.__init__re-initialization bugs described in issue #683.Repository:
msgpack/msgpack-pythonIssue context:
- Issue A (tentative) TODO list? (Generated from Claude Code plugins) #683 reports two related bugs in
Unpacker.__init__:
Unpacker.__init__overwritesself.bufviaPyMem_Mallocwithout first freeing the existing buffer, so re-calling__init__(including subclasssuper().__init__(...)) leaks the previous allocation.Unpacker.__init__callsunpack_initrather than clearing existing parser state first, so any livePyObject*references inctx->stack[1..top]are leaked when re-initializing a mid-streamUnpacker.Requested change:
- Update the
Unpacker.__init__implementation in the Cython source so that, before allocating a new buffer or reinitializing the unpack context, it safely cleans up any existing state.- Specifically, if the instance already has an allocated buffer / active unpack context, clear parser state with
unpack_clear(&self.ctx), free the old buffer withPyMem_Free(self.buf), and resetself.bufappropriately before continuing initialization.Requirements:
- Make the fix in the relevant Cython source file for
Unpacker.- Ensure the cleanup path is safe for first initialization as well as repeated
__init__calls.- Keep the PR focused on these two
Unpacker.__init__bugs only.- Regenerate checked-in generated files only if the repository expects that for Cython source changes.
- Add or update tests if there is an appropriate place to cover re-initialization behavior.
- Open a pull request that references issue A (tentative) TODO list? (Generated from Claude Code plugins) #683 and explains that it fixes both the buffer leak and parse-stack leak on
Unpacker.__init__re-entry.Suggested validation:
- Run relevant tests for unpacker behavior.
- If practical, add a regression test covering repeated
__init__calls or subclass reinitialization.The following is the prior conversation context from the user's chat exploration (may be truncated):
User:
Packer.__getbuffer__と__releasebuffer__に@cython.critical_sectionを追加するPRを作って。Assistant: PR作成の確認待ちです。GitHub 側の承認が完了したら、その変更で続けて進めます。
User: @copilot Accepted Confirmation: Confirm cloud agent session
Assistant: 開始しました。進捗はタスクページで追えます。
User: "Unpacker.init overwrites self.buf via PyMem_Malloc without first freeing" と "Unpacker.init calls unpack_init (not unpack_clear) before re-initializing" を修正するPRを作成して。
Assistant: 確認待ちです。GitHub の承認ダイアログで許可してもらえれば、この PR 作成を続けます。
This pull request was created from Copilot chat.