GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Stale entries in MRO cache if MRO contains non-base classes · Issue #127773 · python/cpython

Stale entries in MRO cache if MRO contains non-base classes #127773

New issue
Copy link
New issue
Copy link
Closed
Closed
Stale entries in MRO cache if MRO contains non-base classes#127773
Copy link
Assignees
encukou
Labels
3.12only security fixesonly security fixes3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@colesbury
colesbury
opened on Dec 9, 2024
Issue body actions

Bug report

For example the following program fails with either assert WeirdClass.value == 2 or assert WeirdClass.value == 3 in recent Python versions:

import sys

class Base:
    value = 1

class Meta(type):
    def mro(cls):
        return (cls, Base, object)

class WeirdClass(metaclass=Meta):
    pass

assert Base.value == 1
assert WeirdClass.value == 1

Base.value = 2
assert Base.value == 2
assert WeirdClass.value == 2

Base.value = 3
assert Base.value == 3
assert WeirdClass.value == 3

Adding intervening calls to sys _clear_internal_caches() makes the test pass.

Version Result
3.7 OK
3.8 OK
3.9 OK
3.10 AssertionError: assert WeirdClass.value == 2
3.11 AssertionError: assert WeirdClass.value == 2
3.12 AssertionError: assert WeirdClass.value == 2
3.13 AssertionError: assert WeirdClass.value == 3
main AssertionError: assert WeirdClass.value == 3

We have code that checks for this case, but it hasn't worked properly in Python 3.10+:

cpython/Objects/typeobject.c

Lines 1107 to 1112 in 5c89adf

static void
type_mro_modified(PyTypeObject *type, PyObject *bases) {
/*
Check that all base classes or elements of the MRO of type are
able to be cached. This function is called after the base
classes or mro of the type are altered.

We also have a test that partly covers this case, but doesn't detect the bug:

cpython/Lib/test/test_capi/test_type.py

Lines 40 to 66 in 5c89adf

def test_freeze_meta(self):
"""test PyType_Freeze() with overridden MRO"""
type_freeze = _testcapi.type_freeze
class Base:
value = 1
class Meta(type):
def mro(cls):
return (cls, Base, object)
class FreezeThis(metaclass=Meta):
"""This has `Base` in the MRO, but not tp_bases"""
self.assertEqual(FreezeThis.value, 1)
with self.assertRaises(TypeError):
type_freeze(FreezeThis)
Base.value = 2
self.assertEqual(FreezeThis.value, 2)
type_freeze(Base)
with self.assertRaises(TypeError):
Base.value = 3
type_freeze(FreezeThis)
self.assertEqual(FreezeThis.value, 2)

Linked PRs

  • gh-127773: Disable attribute cache on incompatible MRO entries #127924
  • [3.13] gh-127773: Disable attribute cache on incompatible MRO entries (GH-127924) #143729
Reacted by Ken Jin and Petr Viktorin

Activity

  1. colesbury
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    3.12only security fixesonly security fixes
    3.13only security fixesonly security fixes
    3.14bugs and security fixesbugs and security fixes
    on Dec 9, 2024
  2. Eclips4
    added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
    on Dec 9, 2024
  3. colesbury commented on Dec 9, 2024

    @colesbury
    colesbury
    on Dec 9, 2024
    ContributorAuthor
    More actions

    cc @encukou - this broke in a4760cc (GH-27260), which removed Py_TPFLAGS_HAVE_VERSION_TAG.

    The reason for removing Py_TPFLAGS_HAVE_VERSION_TAG was because "the field is always present in the type struct", but the flag indicates whether a type supports the method cache (i.e, supports having a valid version tag) and types with MRO entries that aren't superclasses don't support the method cache.

  4. cfbolz commented on Dec 10, 2024

    @cfbolz
    cfbolz
    on Dec 10, 2024
    Contributor
    More actions

    Great (if very annoying) find, @colesbury! The bug even affects pypy, which has an entirely different architecture for its caches 😳

  5. encukou
    self-assigned this
    on Dec 12, 2024
  6. mpage
    added a commit that references this issue on Dec 20, 2024

    Skip test that triggers pythongh-127773 in refleak tests

    e5e2508
  7. encukou
    added a commit that references this issue on Jan 13, 2025

    gh-127773: Disable attribute cache on incompatible MRO entries (GH-12…

    aa6579c
  8. colesbury commented on Feb 6, 2025

    @colesbury
    colesbury
    on Feb 6, 2025
    ContributorAuthor
    More actions

    I think this was fixed by @encukou

  9. colesbury
    closed this as completedon Feb 6, 2025
  10. encukou commented on Feb 7, 2025

    @encukou
    encukou
    on Feb 7, 2025
    Member
    More actions

    In the main branch. I don't know if I'll get to older branches in time.

  11. encukou
    reopened this on Feb 7, 2025
  12. kumaraditya303 commented on Jan 9, 2026

    @kumaraditya303
    kumaraditya303
    on Jan 9, 2026
    Contributor
    More actions

    @encukou do you want to backport it? Otherwise, this seems complete now.

  13. encukou
    added a commit that references this issue on Jan 12, 2026

    pythongh-127773: Disable attribute cache on incompatible MRO entries (p…

    356fb83
  14. encukou commented on Jan 12, 2026

    @encukou
    encukou
    on Jan 12, 2026
    Member
    More actions

    Oh, thanks for the ping!
    See #143729 for the backport.

  15. encukou
    added a commit that references this issue on Jan 26, 2026

    [3.13] gh-127773: Disable attribute cache on incompatible MRO entries (…

    fdac87a
  16. encukou commented on Jan 26, 2026

    @encukou
    encukou
    on Jan 26, 2026
    Member
    More actions

    I've merged the backport to 3.13.

  17. encukou
    closed this as completedon Jan 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @encukou
    encukou

Labels

3.12only security fixesonly security fixes3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.