Nico-Posada · GitHub

Bug report

Bug description:

I discovered this while working on #126080. If the func is given a context that isn't None, instead of doing Py_XSETREF it'll just do a regular assignment meaning that whatever was there before wont have its reference count decreased.

} else {
self->task_context = Py_NewRef(context);
}
import asyncio
import sys
# for convenience so I dont have to set up everything else for a Task obj
# and can just focus on the ref leak
class Break:
    def __str__(self):
        raise Exception("break")
async def coro():
    pass
task = asyncio.Task.__new__(asyncio.Task)
co = coro()
obj = object()
print("refcount before bug", sys.getrefcount(obj))
for _ in range(10000):
    try:
        task.__init__(co, context=obj, name=Break())
    except: pass
print("refcount after bug", sys.getrefcount(obj))

Output

refcount before bug 2
refcount after bug 10002

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs

Read the original on github.com ↗