René's URL Explorer Experiment


Title: Double free / use-after-free in `list.append()` when the list grows under `MemoryError` (`_CALL_LIST_APPEND`) · Issue #151818 · python/cpython · GitHub

Open Graph Title: Double free / use-after-free in `list.append()` when the list grows under `MemoryError` (`_CALL_LIST_APPEND`) · Issue #151818 · python/cpython

X Title: Double free / use-after-free in `list.append()` when the list grows under `MemoryError` (`_CALL_LIST_APPEND`) · Issue #151818 · python/cpython

Description: Crash report What happened? When list.append(x) has to grow the list's backing array and that allocation fails (i.e. under MemoryError), the appended item x is decref'd twice. If x is referenced elsewhere this is a use-after-free: the in...

Open Graph Description: Crash report What happened? When list.append(x) has to grow the list's backing array and that allocation fails (i.e. under MemoryError), the appended item x is decref'd twice. If x is referenced el...

X Description: Crash report What happened? When list.append(x) has to grow the list's backing array and that allocation fails (i.e. under MemoryError), the appended item x is decref'd twice. If x is refer...

Opengraph URL: https://github.com/python/cpython/issues/151818

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Double free / use-after-free in `list.append()` when the list grows under `MemoryError` (`_CALL_LIST_APPEND`)","articleBody":"# Crash report\n\n### What happened?\n\nWhen `list.append(x)` has to grow the list's backing array and that allocation fails (i.e.\nunder `MemoryError`), the appended item `x` is decref'd **twice**. If `x` is referenced\nelsewhere this is a use-after-free: the interpreter aborts with `_Py_NegativeRefcount` on a\ndebug build, or **segfaults** on a release build, instead of raising a recoverable\n`MemoryError`.\n\nThis is reachable under genuine memory pressure (a real `RLIMIT_AS` reproducer with no test\nAPI is included below), so a program that correctly catches `MemoryError` can still be left\nwith a corrupted interpreter.\n\n### Reproducer\n\nDeterministic, pure Python, using `_testcapi.set_nomemory` to fail the grow allocation at a\ncontrolled point:\n\n```python\nimport _testcapi\n\nclass C:\n    __slots__ = (\"ref\",)\n    def __init__(self, ref):\n        self.ref = ref\n\ndef fill():\n    items = [C(str(i) + \"_unique\") for i in range(200)]\n    out = []\n    for it in items:\n        out.append(it.ref)          # CALL_LIST_APPEND; it.ref is also held by the C instance\n\nfill()                              # warm up: specialize out.append(...) to CALL_LIST_APPEND\nfor start in range(1500):\n    _testcapi.set_nomemory(start, start + 1)   # fail one allocation, then resume\n    try:\n        try:\n            fill()\n        finally:\n            _testcapi.remove_mem_hooks()\n    except BaseException:\n        pass\n```\n\nOn a `--with-pydebug` build this aborts:\n\n```\n./Include/refcount.h:520: _Py_NegativeRefcount: Assertion failed: object has negative ref count\nFatal Python error: _PyObject_AssertFailed\n```\n\nOn a release build it segfaults.\n\n### Without any test API (real `MemoryError`)\n\nThe same double-free fires under a genuine allocation failure. With an `RLIMIT_AS` cap so the\nlist's grow allocation returns NULL naturally (run on a non-ASan build):\n\n```python\nimport resource\n\npool = [object() for _ in range(8_000_000)]      # uniquely-referenced items, built before the cap\nwarm = []\nfor i in range(3000):\n    warm.append(pool[i])                          # specialize CALL_LIST_APPEND\ndel warm\n\ncur = int(open(\"/proc/self/statm\").read().split()[0]) * 4096   # current virtual size\nresource.setrlimit(resource.RLIMIT_AS, (cur + 24 * 1024 * 1024,) * 2)\n\nout = []\nfor x in pool:\n    out.append(x)                                 # real list_resize failure -\u003e double-free -\u003e SIGSEGV\n```\n\n```\n$ ./python natural.py\nSegmentation fault            # faulthandler pins the crash to the `out.append(x)` line\n```\n\nUnder the same cap, when the failing allocation is *not* a list-append grow (e.g. appending\nlarge `bytes`), Python raises a clean, catchable `MemoryError` and does not crash — so the\nsegfault is specific to the buggy append path.\n\n## Root cause\n\nIn the specialized append bytecode `_CALL_LIST_APPEND` (`Python/bytecodes.c`):\n\n```c\nop(_CALL_LIST_APPEND, (callable, self, arg -- none, c, s)) {\n    ...\n    int err = _PyList_AppendTakeRef((PyListObject *)self_o, PyStackRef_AsPyObjectSteal(arg));\n    UNLOCK_OBJECT(self_o);\n    if (err) {\n        ERROR_NO_POP();\n    }\n    ...\n}\n```\n\n`arg` is **stolen** via `PyStackRef_AsPyObjectSteal` and handed to `_PyList_AppendTakeRef`,\nwhich consumes the reference on every path — including decref'ing the item when the grow\nfails (`_PyList_AppendTakeRefListResize` → `if (list_resize(...) \u003c 0) { Py_DECREF(newitem);\nreturn -1; }`, `Objects/listobject.c`).\n\nBut on that failure the uop takes `ERROR_NO_POP()`, which jumps to exception handling\n**without removing `arg` from the value stack**. Since `arg`'s reference was already\nconsumed, the stale `arg` stackref is now dangling. The eval loop's `exception_unwind` then\npops the frame's value stack and `PyStackRef_XCLOSE`s every slot, closing the stale `arg`\nslot — a **second** decref of the item.\n\n(Confirmed with ASan on a `--with-pymalloc` build: the item is freed by `PyStackRef_XCLOSE`\n← `_PyEval_EvalFrameDefault` (the `exception_unwind` handler); both the item's allocation and\nthe second, use-after-free decref are visible in the report.)\n\n## Suggested fix\n\n`_CALL_LIST_APPEND` must account for the consumed `arg` on the error path — once\n`_PyList_AppendTakeRef` has taken the reference, the `arg` stackref is dead and must not be\nleft on the value stack for `exception_unwind` to close. The sibling ops already show the two\ncorrect idioms:\n\n- the comprehension element-adds (`LIST_APPEND`, `SET_ADD`, `MAP_ADD`) call the same kind of\n  steal/`*TakeRef` helper but use `ERROR_IF(...)`, so the codegen drops the consumed input on\n  the error path. Concretely, `[x for x in ...]` (`LIST_APPEND`, the *same*\n  `_PyList_AppendTakeRef` helper) does **not** crash where `lst.append(x)`\n  (`_CALL_LIST_APPEND`) does;\n- the consuming call ops (`_DO_CALL_FUNCTION_EX`, `_PY_FRAME_EX`) call `INPUTS_DEAD();\n  SYNC_SP();` before `ERROR_NO_POP()`.\n\nI audited the other specialized ops: `_CALL_LIST_APPEND` is the only one that steals a\nstack input and then takes a bare `ERROR_NO_POP()` without either form of accounting, which\nis why it is the lone op affected.\n\n## Environment\n\n- CPython `main` (3.16.0a0); reproduced on `--with-pydebug` builds (abort) and release builds\n  (segfault), both free-threaded and default GIL.\n\n---\n\n*This report and the reduced reproducers were drafted with the assistance of Claude Code; I\nhave reviewed and reproduced them.*\n\n### CPython versions tested on:\n\nCPython main branch, 3.16\n\n### Operating systems tested on:\n\nLinux\n\n### Output from running 'python -VV' on the command line:\n\nPython 3.16.0a0 (heads/main:aec0aed1978, Jun 20 2026, 17:44:00) [Clang 22.1.2 (1ubuntu1)]\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-151826\n* gh-152114\n* gh-152117\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/devdanzin","@type":"Person","name":"devdanzin"},"datePublished":"2026-06-20T22:13:16.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":6},"url":"https://github.com/151818/cpython/issues/151818"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:d16ea0c4-2376-9449-ed50-333612e8cd6c
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idE616:17F12E:513ACF:6B9948:6A52D5FE
html-safe-nonce9e34deff2730d966317cd05f928c992cfe0429171dfbe35a3f38d17e08eaf3be
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFNjE2OjE3RjEyRTo1MTNBQ0Y6NkI5OTQ4OjZBNTJENUZFIiwidmlzaXRvcl9pZCI6Ijg4MDE2OTUzODc5MjI2NTA2MjIiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmacaf9d57e7b4c76c831c106ad293d4adc738c9166cc43c52810bda0c8e2ef0d45b
hovercard-subject-tagissue:4708528195
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/151818/issue_layout
twitter:imagehttps://opengraph.githubassets.com/adcb3fb411a0e16349bee62ededc1c41574ff3b1f5ac7c104999b7512e1db374/python/cpython/issues/151818
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/adcb3fb411a0e16349bee62ededc1c41574ff3b1f5ac7c104999b7512e1db374/python/cpython/issues/151818
og:image:altCrash report What happened? When list.append(x) has to grow the list's backing array and that allocation fails (i.e. under MemoryError), the appended item x is decref'd twice. If x is referenced el...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamedevdanzin
hostnamegithub.com
expected-hostnamegithub.com
Noneb9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb
turbo-cache-controlno-preview
go-importgithub.com/python/cpython git https://github.com/python/cpython.git
octolytics-dimension-user_id1525981
octolytics-dimension-user_loginpython
octolytics-dimension-repository_id81598961
octolytics-dimension-repository_nwopython/cpython
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id81598961
octolytics-dimension-repository_network_root_nwopython/cpython
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release07a982c1d40157c619b364352b704c3ce66bb332
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/python/cpython/issues/151818#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fcpython%2Fissues%2F151818
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fcpython%2Fissues%2F151818
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=python%2Fcpython
Reloadhttps://github.com/python/cpython/issues/151818
Reloadhttps://github.com/python/cpython/issues/151818
Reloadhttps://github.com/python/cpython/issues/151818
Please reload this pagehttps://github.com/python/cpython/issues/151818
python https://github.com/python
cpythonhttps://github.com/python/cpython
Please reload this pagehttps://github.com/python/cpython/issues/151818
Notifications https://github.com/login?return_to=%2Fpython%2Fcpython
Fork 35k https://github.com/login?return_to=%2Fpython%2Fcpython
Star 73.8k https://github.com/login?return_to=%2Fpython%2Fcpython
Code https://github.com/python/cpython
Issues 5k+ https://github.com/python/cpython/issues
Pull requests 2.3k https://github.com/python/cpython/pulls
Actions https://github.com/python/cpython/actions
Projects https://github.com/python/cpython/projects
Security and quality 0 https://github.com/python/cpython/security
Insights https://github.com/python/cpython/pulse
Code https://github.com/python/cpython
Issues https://github.com/python/cpython/issues
Pull requests https://github.com/python/cpython/pulls
Actions https://github.com/python/cpython/actions
Projects https://github.com/python/cpython/projects
Security and quality https://github.com/python/cpython/security
Insights https://github.com/python/cpython/pulse
Double free / use-after-free in list.append() when the list grows under MemoryError (_CALL_LIST_APPEND)https://github.com/python/cpython/issues/151818#top
interpreter-core(Objects, Python, Grammar, and Parser dirs)https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22interpreter-core%22
type-crashA hard crash of the interpreter, possibly with a core dumphttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-crash%22
https://github.com/devdanzin
devdanzinhttps://github.com/devdanzin
on Jun 20, 2026https://github.com/python/cpython/issues/151818#issue-4708528195
gh-151818: Fix double-free in _CALL_LIST_APPEND on allocation failure #151826https://github.com/python/cpython/pull/151826
gh-151818: Fix CALL_LIST_APPEND opcode error path #152114https://github.com/python/cpython/pull/152114
[WIP] gh-151818: Add a test on CALL_LIST_APPEND error path #152117https://github.com/python/cpython/pull/152117
interpreter-core(Objects, Python, Grammar, and Parser dirs)https://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22interpreter-core%22
type-crashA hard crash of the interpreter, possibly with a core dumphttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-crash%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.