Skip to content

[backport to 3.5] bpo-29438: Fixed use-after-free in key sharing dict#40

Merged
methane merged 1 commit intopython:3.5from
methane:bpo29438/py35
Feb 13, 2017
Merged

[backport to 3.5] bpo-29438: Fixed use-after-free in key sharing dict#40
methane merged 1 commit intopython:3.5from
methane:bpo29438/py35

Conversation

@methane
Copy link
Copy Markdown
Member

@methane methane commented Feb 12, 2017

No description provided.

@methane methane added the type-bug An unexpected behavior, bug, or error label Feb 12, 2017
@methane methane changed the title bpo-29438: Fixed use-after-free in key sharing dict [backport to 3.5] bpo-29438: Fixed use-after-free in key sharing dict Feb 12, 2017
Comment thread Objects/dictobject.c
}
if (value == NULL) {
res = PyDict_DelItem(dict, key);
if (cached != ((PyDictObject *)dict)->ma_keys) {
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.

Why these lines are deleted?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In Python 3.5, PyDict_DelItem won't resize dict. So cached == dict->ma_keys in most cases.

One exception is callback called by weakref or __del__ inserts some items to the dict and resize happened.
In this case, cached != CACHED_KEYS(tp), so DK_DECREF(cached) will be "use-after-free".

In such case, the insertion from the callback would update CACHED_KEYS(tp) correctly.
So clearing CACHED_KEYS(tp) doesn't make sense for most case.

Even when the callback inserts items through __dict__ (not regular attribute access), skipping CACHED_KEYS(tp) = NULL
doesn't cause uncontrolled memory growth. And it happens very rarely.
So I think this code is not worth enough.

@methane methane merged commit 06a4fcb into python:3.5 Feb 13, 2017
@methane methane deleted the bpo29438/py35 branch February 13, 2017 00:16
jaraco pushed a commit that referenced this pull request Dec 2, 2022
oraluben pushed a commit to oraluben/cpython that referenced this pull request Jun 25, 2023
johnslavik pushed a commit to johnslavik/cpython that referenced this pull request Dec 19, 2025
SonicField added a commit to SonicField/cpython that referenced this pull request Apr 15, 2026
Move bytecode_offset=-1 initialization into hir_c_alloc_instr so the
invariant is structurally enforced — even if hir_c_init_instr is
accidentally skipped, bytecode_offset will be -1 (not 0 from calloc).

Add runtime regression test in hir_instr_c_verify.cpp that verifies
the invariant for all three allocation paths (raw alloc, init_instr,
init_deopt). Runs at startup via __attribute__((constructor)).

Addresses gap flagged 5 times (Pythia python#14, python#40, python#59, librarian x2).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type-bug An unexpected behavior, bug, or error

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants