Skip to content

weakrefobject.c: binary, ternary, or comparison operations ref leak with dead proxy #153058

Description

@aisk

Bug report

Bug description:

Original gist: https://gist.github.com/devdanzin/f7d0c7694b2be2345f4cf85f4eedc3ee

Summary

When first UNWRAP(x) succeeds but second UNWRAP(y) fails (dead proxy), x's new reference is leaked. Affects ~20 binary operators (+, -, *, /, |, &, ^, etc.).

Reproducer

importweakref, sys, gcclassC:
def__add__(self, other): returnNotImplementeddef__radd__(self, other): returnNotImplementedobj=type('D', (), {})()
dead=weakref.proxy(obj)
delobj; gc.collect()
live_obj=C()
live=weakref.proxy(live_obj)
before=sys.gettotalrefcount()
foriinrange(10000):
try:
live+deadexceptReferenceError:
passafter=sys.gettotalrefcount()
print(f"Leaked {after-before} refs (~{(after-before)//10000}/call)")

Actually, ternary, or comparison operations have the same problem.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions