gh-149816: Fix UAF in Modules/_pickle.c#150024
Open
alexkats wants to merge 3 commits into
Open
Conversation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
22 tasks
Member
|
Is it possible to add a test for this? |
Author
Initially I thought no, but I found a way, thanks for asking |
gpshead
reviewed
May 18, 2026
gpshead
reviewed
May 18, 2026
Member
gpshead
left a comment
There was a problem hiding this comment.
otherwise, PR looks good - just a question to answer and maybe an additional check to add.
I reworded the news entry.
f137ba9 to
ba6cf2d
Compare
gpshead
approved these changes
May 19, 2026
Get a strong reference atomically for list item instead of 2 operations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Get a strong reference atomically for list item instead of 2 operations.
Original description of the problem from 91.md:
Vulnerability #91
Title: Racy list item borrow causes UAF
Category: Memory Safety Violations
Tags: write,race,env,dos
CWEs: CWE-416, CWE-367
CVSS: CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:L/VI:L/VA:H/SC:N/SI:N/SA:N
Severity: Medium (5.8)
Location:
cpython/Modules/_pickle.c:3213:3214in functionbatch_list_exactDescription
batch_list_exactreads list elements usingPyList_GET_ITEMand only then increments the reference count (Py_INCREF) without holding the list lock or using a safe strong-ref getter (cpython/Modules/_pickle.c:3213-3214, alsocpython/Modules/_pickle.c:3197-3198). In free-threaded mode,_pickleruns without the GIL (cpython/Modules/_pickle.c:8242), so concurrent list mutation is possible while pickling. A mutator thread can remove/replace the same element and decref it to zero (cpython/Objects/listobject.c:1145-1156) between size check/access inbatch_list_exact(cpython/Modules/_pickle.c:3212-3214), leading toPy_INCREFon freed memory (use-after-free write).Trigger Conditions
Pre-conditions:
_pickleis used (it declares no-GIL operation atcpython/Modules/_pickle.c:8242).listand protocol is greater than 0, sosave_listusesbatch_list_exact(cpython/Modules/_pickle.c:3266-3269).Data flow:
pickle.dumps(shared_list, protocol=5);save_listdispatches tobatch_list_exact(cpython/Modules/_pickle.c:3266-3269).batch_list_exact, Thread A evaluates loop/size and then fetches a borrowed element viaPyList_GET_ITEM(cpython/Modules/_pickle.c:3212-3213).del shared_list[i]orshared_list[i] = other), and list code decrefs the old element (cpython/Objects/listobject.c:1145-1156), potentially freeing it.Py_INCREF(item)on the stale pointer (cpython/Modules/_pickle.c:3214), triggering UAF memory corruption/crash.Impact
This can cause native memory corruption in the interpreter (use-after-free with refcount write), typically leading to process crash (denial of service) and potentially enabling arbitrary code execution in worst case under favorable heap/layout conditions. Exploitability is constrained by requiring a free-threaded build and a concurrent mutation race on the same list object, but the code path is reachable from normal Python APIs (
pickle.dumps) and does not enforce safety against such concurrent access.Remediation
batch_list_exact()(cpython/Modules/_pickle.c), replace both unsafe borrowed-ref reads (PyList_GET_ITEM+Py_INCREF) with a strong-reference API (PyList_GetItemRef/ internal equivalent) so element lifetime is acquired atomically for free-threaded builds.save_list()and passed intobatch_list_exact().RuntimeError(e.g., “list changed size during iteration”) instead of continuing.pickle.dumps()+ list mutation to ensure no UAF/crash, and verify behavior is clean exception-only under race.Reproduction
--with-pydebug).listused by two concurrent threads:> 0(so_pickletakes the fast exact-list path),_picklelist batching /Py_INCREFon a list item.Code Context