Skip to content

_testcapi._tuple_resize() leaks item references on allocation failure #159514

Closed

Description

@lagergren-oai

Bug report

_PyTuple_Resize() leaks references to the tuple's elements when the underlying PyObject_GC_Resize() fails. It sets the caller's pointer to NULL and frees the old tuple storage with PyObject_GC_Del(), but does not release the references held in that storage.

The old allocation remains valid after the failed resize, so its remaining elements must be decref'ed before it is freed. For a shrinking resize, the removed tail entries have already been cleared; the retained entries still need cleanup if resizing fails.

Reproducer

Run this with a build that includes _testcapi. The helper creates a private copy of the input tuple, satisfying _PyTuple_Resize()'s ownership requirement. The requested size exceeds the GC allocator's checked size limit because of header overhead; this does not depend on exhausting available RAM.

import gc
import struct
import sys
import weakref
import _testcapi

class Item:
    pass

item = Item()
original = (item,)
ref = weakref.ref(item)

try:
    # The helper creates a private copy of the tuple before resizing it.
    # Header overhead makes this exceed the GC allocator's size limit.
    _testcapi._tuple_resize(original, sys.maxsize // struct.calcsize("P"))
except MemoryError:
    pass
else:
    raise AssertionError("expected MemoryError")

del original, item
gc.collect()
print("element released:", ref() is None)
assert ref() is None

Expected: element released: True.
Actual: element released: False, followed by AssertionError.

CPython versions tested on

Reproduced with the unmodified runtime from CPython main at 21a36aa79ca0b2af49995fa1b9216b01ef98f195 (3.16.0a1+dev), with --with-pydebug. Only the new regression test was added; no runtime code was changed for the failing run.

Source inspection also confirms the same cleanup path in release tags v3.14.8 and v3.15.0. Those versions were not executed for this report.

Operating systems tested on

macOS 27.0.1, Apple Silicon.

Related reports

I searched for an existing report. #155053 concerns a caller dereferencing NULL after resize failure; its proposed fix does not address these leaked element references.

The bug was manually spotted and investigated, but AI tools assisted with the investigation, reproducer, and proposed fix. The reproducer and regression test were executed locally before submission.

Linked PRs

Activity

  1. sergey-miryanov commented on Oct 16, 2026

    @sergey-miryanov
    Contributor

    Would you like to open a PR?

  2. added
    type-bugAn unexpected behavior, bug, or error
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    3.14bugs and security fixes
    3.15bugs and security fixes
    3.16new features, bugs and security fixes
    on Oct 16, 2026
  3. changed the title [-]_PyTuple_Resize() leaks item references on allocation failure[/-] [+]_testcapi._tuple_resize() leaks item references on allocation failure[/+] on Oct 16, 2026
  4. vstinner commented on Oct 16, 2026

    @vstinner
    Member

    The leak is in _testcapi._tuple_resize() wrapper (on error), not in _PyTuple_Resize().

  5. added a commit that references this issue on Oct 16, 2026
  6. lagergren commented on Oct 16, 2026

    @lagergren
    1. Would you like to open a PR?

    Looks like someone did already?

  7. sergey-miryanov commented on Oct 16, 2026

    @sergey-miryanov
    Contributor

    Looks like someone did already?

    @zolaski333 Thanks for your time and effort. But it's usually best to check with the original issue author first to see if they're already working on it.

  8. lagergren-oai commented on Oct 19, 2026

    @lagergren-oai
    Author

    Thanks, Sergey and Noah. I've compared the patch in #159526 with my fix. It implements the same cleanup in _PyTuple_Resize() and includes a regression test for the allocation-failure leak.

    I'm happy to proceed with Noah's PR as the upstream fix, so I won't open a duplicate. Thanks @zolaski333 for taking this forward, and @sergey-miryanov for checking with me.

  9. sergey-miryanov commented on Oct 28, 2026

    @sergey-miryanov
    Contributor

    Fixed by #159754

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.14bugs and security fixes3.15bugs and security fixes3.16new features, bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions