Skip to content

Disallow multiple initializations of asyncio tasks and futures #142615

@kumaraditya303

Description

@kumaraditya303

Problem

This is a long standing issue of the _asyncio accelerator module where _asyncio.Task and _asyncio.Future define tp_init slot instead of tp_new slot for creating the object. This allows malicious code to re-initialize objects while tasks and futures are executing which can crash the interpreter because internally the fields of tasks and futures are accessed using borrowed references for performance.

There have been multiple reports of this where we previously changed the code to use strong references like #126080 but still there are a lot of places where borrowed references to loop is used etc.

IMO changing the code to use strong references is not the solution here, instead we should make tasks and futures immutable at C level so that this issue would not exist in the first place. Avoiding strong references is also important for performance especially in free-threading.

Proposal

Historically _asyncio.Task and _asyncio.Future define tp_init rather than tp_new, so we cannot change it to use tp_new as it would break compatibility with subclasses. To preserve backward compatibility I propose to to instead allow tp_init to be called exactly once and if user tries to initialize it again, raise RuntimeError that task cannot be re-initialized. This would prevent all these issues while preserving backwards compatibility and performance.

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.15new features, bugs and security fixestopic-asynciotype-featureA feature request or enhancement

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions