Skip to content

gh-150868: Fix incorrect specialized deallocation of float subclasses in sum()#150869

Open
opale-c wants to merge 1 commit into
python:mainfrom
opale-c:main
Open

gh-150868: Fix incorrect specialized deallocation of float subclasses in sum()#150869
opale-c wants to merge 1 commit into
python:mainfrom
opale-c:main

Conversation

@opale-c
Copy link
Copy Markdown

@opale-c opale-c commented Jun 3, 2026

In the complex-number fast path of builtin_sum_impl (Python/bltinmodule.c),
items are tested with PyFloat_Check() but then released with
_Py_DECREF_SPECIALIZED(item, _PyFloat_ExactDealloc). PyFloat_Check() also
matches float subclasses, whereas _PyFloat_ExactDealloc is only valid for
exact float objects. As a result, when summing instances of a float
subclass into a complex start value, the subclass instances are deallocated as
exact floats, bypassing their real tp_dealloc (instance __dict__, weakref,
and GC cleanup). This can leak memory and leave the GC in an inconsistent state.

The adjacent float fast path already guards the same specialized dealloc with
PyFloat_CheckExact(); this change brings the complex path in line by using
PyFloat_CheckExact() as well. Subclass instances then fall through to the
generic PyNumber_Add path with a normal Py_DECREF, preserving numeric
behavior while fixing the deallocation.

Reproducer

class F(float):
    pass

sum([F(1.0), F(2.0)], 0j)  # subclass instances were freed as exact floats

Change: in the complex branch of builtin_sum_impl, replace
PyFloat_Check(item) with PyFloat_CheckExact(item) (one line).

Fix incorrect specialized deallocation of float subclasses in sum()

In the complex-number fast path of builtin_sum_impl ( Python/bltinmodule.c ), items are tested with PyFloat_Check() but then released with _Py_DECREF_SPECIALIZED(item, _PyFloat_ExactDealloc) . PyFloat_Check() also matches float subclasses, whereas _PyFloat_ExactDealloc is only valid for exact float objects. As a result, when summing instances of a float subclass into a complex start value, the subclass instances are deallocated as exact floats, bypassing their real tp_dealloc (instance __dict__ , weakref, and GC cleanup). This can leak memory and leave the GC in an inconsistent state.

The adjacent float fast path already guards the same specialized dealloc with PyFloat_CheckExact() ; this change brings the complex path in line by using PyFloat_CheckExact() as well. Subclass instances then fall through to the generic PyNumber_Add path with a normal Py_DECREF , preserving numeric behavior while fixing the deallocation.

Reproducer:

class F(float):
    pass

sum([F(1.0), F(2.0)], 0j)  # subclass instances were freed as exact floats

Change: in the complex branch of builtin_sum_impl , replace PyFloat_Check(item) with PyFloat_CheckExact(item) (one line).
@python-cla-bot
Copy link
Copy Markdown

python-cla-bot Bot commented Jun 3, 2026

The following commit authors need to sign the Contributor License Agreement:

CLA not signed

@bedevere-app

This comment was marked as resolved.

@skirpichev
Copy link
Copy Markdown
Member

@opale-c, could you please sign CLA?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants