Skip to content

gh-146065: Fix NULL dereference in FutureIter_am_send - #146304

Open
VanshAgarwal24036 wants to merge 6 commits into
python:mainfrom
VanshAgarwal24036:gh-146065-fix-futureiter-null-deref
Open

VanshAgarwal24036 wants to merge 6 commits into
python:mainfrom
VanshAgarwal24036:gh-146065-fix-futureiter-null-deref

Conversation

@VanshAgarwal24036

@VanshAgarwal24036 VanshAgarwal24036 commented Mar 22, 2026 •

Copy link
Copy Markdown
Contributor

After throw() or close(), it->future can be NULL. A subsequent send() call would dereference it and crash. This adds a NULL check and raises StopIteration instead.

Comment thread Lib/test/test_asyncio/test_futures.py Outdated
Comment thread Lib/test/test_asyncio/test_futures.py Outdated
Comment thread Lib/test/test_asyncio/test_futures.py Outdated
@bedevere-app

bedevere-app Bot commented Mar 22, 2026

Copy link
Copy Markdown

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@VanshAgarwal24036

Copy link
Copy Markdown
Contributor Author

I have made the requested changes; please review again

@bedevere-app

bedevere-app Bot commented Mar 22, 2026

Copy link
Copy Markdown

Thanks for making the requested changes!

@picnixz: please review the changes made to this pull request.

@bedevere-app
bedevere-app Bot requested a review from picnixz March 22, 2026 19:04
@JArmandoAnaya

JArmandoAnaya commented Mar 24, 2026 •

Copy link
Copy Markdown

I was able to reproduce and verify this fix locally on macOS (x86_64).

Without the fix (NULL check in FutureIter_am_send removed): test_futureiter_send_after_throw_no_crash crashes with a segfault, confirmed NULL dereference in FutureIter_am_send when it->future is NULL after a prior throw().

With the fix (NULL check restored): all three variants of the test pass (CFutureTests, CSubFutureTests, PyFutureTests), and the full test.test_asyncio.test_futures suite passes (186/186 tests OK, no regressions).

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I confirm that test_futureiter_send_after_throw_no_crash() does crash without the fix, and pass with the fix.

@kumaraditya303: Do you want to double check this fix? I didn't work on ayncio recently, and I'm not 100% sure if raising StopIteration is the correct behavior in this case.

Comment thread Misc/NEWS.d/next/Library/2026-03-23-00-04-13.gh-issue-146065.FIdn8D.rst Outdated
…Idn8D.rst

Co-authored-by: Victor Stinner <vstinner@python.org>
@VanshAgarwal24036

Copy link
Copy Markdown
Contributor Author

This failure appears unrelated to the asyncio change. It occurs in test_ssl and looks like an environment-specific difference in SSL error messages (AWS-LC vs OpenSSL), not connected to FutureIter_am_send.

@kumaraditya303

Copy link
Copy Markdown
Contributor

Do you want to double check this fix? I didn't work on ayncio recently, and I'm not 100% sure if raising StopIteration is the correct behavior in this case.

I'll take a closer look later but reading it->future outside the critical section looks unsafe.

@github-actions

github-actions Bot commented May 8, 2026

Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label May 8, 2026
with self.assertRaises(RuntimeError, msg="is already initialized"):
f.__init__(loop=self.loop)

def test_futureiter_send_after_throw_no_crash(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to have an additional test case for the it.close() similar to this.

Comment thread Modules/_asynciomodule.c
PyObject **result)
{
futureiterobject *it = (futureiterobject*)op;
if (it->future == NULL) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but reading it->future outside the critical section looks unsafe.

This was the previous reviewer's @kumaraditya303 review comment.

There is also a read happening in FutureIter_am_send_lock_held (line 1832) which is called from FutureIter_am_send

After reading it->future in a critical section, sending the same object might address it.

@VanshAgarwal24036, I noticed the PR has become state. Would you like to revive it again with these change ?

@github-actions github-actions Bot removed the stale Stale PR or inactive for long period of time. label Jul 5, 2026
@msullivan

Copy link
Copy Markdown
Contributor

Do you want to double check this fix? I didn't work on ayncio recently, and I'm not 100% sure if raising StopIteration is the correct behavior in this case.

I'll take a closer look later but reading it->future outside the critical section looks unsafe.

Yeah, I think you are right about this. I put up #158468 as a version that moves all the accesses into critical sections.

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.

7 participants