Skip to content

gh-145244: Fix use-after-free on borrowed dict key in json encoder#145245

Merged
gpshead merged 3 commits intopython:mainfrom
raminfp:fix-gh-145244-json-uaf-key
Apr 11, 2026
Merged

gh-145244: Fix use-after-free on borrowed dict key in json encoder#145245
gpshead merged 3 commits intopython:mainfrom
raminfp:fix-gh-145244-json-uaf-key

Conversation

@raminfp
Copy link
Copy Markdown
Contributor

@raminfp raminfp commented Feb 26, 2026

Fix use-after-free in encoder_encode_key_value() where borrowed references to dict keys from PyDict_Next() can become dangling pointers if the default callback mutates the dictionary during encoding.

In encoder_encode_key_value(), key is a borrowed reference from
PyDict_Next(). If the default callback mutates or clears the dict,
key becomes a dangling pointer. The error path then calls
_PyErr_FormatNote("%R", key) on freed memory.

Fix by holding strong references to key and value unconditionally
during encoding, not just in the free-threading build.
…j31cp.rst

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
# Conflicts:
#	Lib/test/test_json/test_dump.py
Py_INCREF(key);
Py_INCREF(value);
#endif
if (encoder_encode_key_value(s, writer, first, dct, key, value,
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.

reviewer note for the future: I explored if we could deterministically understand if encoder_encode_key_value was going to call user code which could lead to the problem... it's too complicated. while a couple heuristics exist for a subset of cases, they'd be fragile.

@gpshead gpshead added the needs backport to 3.14 bugs and security fixes label Apr 11, 2026
@gpshead gpshead self-assigned this Apr 11, 2026
@gpshead gpshead enabled auto-merge (squash) April 11, 2026 22:07
@gpshead gpshead merged commit 8a466fa into python:main Apr 11, 2026
61 checks passed
@miss-islington-app
Copy link
Copy Markdown

Thanks @raminfp for the PR, and @gpshead for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14.
🐍🍒⛏🤖

@miss-islington-app
Copy link
Copy Markdown

Sorry, @raminfp and @gpshead, I could not cleanly backport this to 3.14 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker 8a466fa3d90a9e1f04d23c05ee2cf3f3c406ba30 3.14

@gpshead gpshead removed the needs backport to 3.14 bugs and security fixes label Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants