Skip to content

Instantly share code, notes, and snippets.

@devdanzin
Created March 18, 2026 10:07
Show Gist options
  • Select an option

  • Save devdanzin/f7d0c7694b2be2345f4cf85f4eedc3ee to your computer and use it in GitHub Desktop.

Select an option

Save devdanzin/f7d0c7694b2be2345f4cf85f4eedc3ee to your computer and use it in GitHub Desktop.
weakrefobject.c: WRAP_BINARY ref leak with dead proxy

weakrefobject.c: WRAP_BINARY ref leak with dead proxy

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

import weakref, sys, gc

class C:
    def __add__(self, other): return NotImplemented
    def __radd__(self, other): return NotImplemented

obj = type('D', (), {})()
dead = weakref.proxy(obj)
del obj; gc.collect()

live_obj = C()
live = weakref.proxy(live_obj)

before = sys.gettotalrefcount()
for i in range(10000):
    try:
        live + dead
    except ReferenceError:
        pass
after = sys.gettotalrefcount()
print(f"Leaked {after - before} refs (~{(after-before)//10000}/call)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment