python / python/cpython

Incorrect MRO cache entry is populated for types that do not have a version assigned

オープン
#128,108 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

interpreter-core type-bug
主要言語
Python
スター
77.2k
フォーク
36k
PR マージ指標
PR 指標を取得中

説明

Bug report

Bug description:

_PyType_LookupRefAndVersion will populate the incorrect cache entry if it is called with a type that does not have a version tag (tp_version_tag is 0). I think this only impacts performance, not correctness. The next call to _PyType_LookupRefAndVersion for the same (type, name) pair will miss the cache, but will populate the correct entry, so any subsequent calls will hit the cache. Additionally, this may create some amount of unnecessary thrash on the cache.

The root of the issue is that the version tag is an input to the hash that is used to determine the cache entry and we do not recompute the hash, and the associated cache entry, after assigning a version.

_PyType_LookupRefAndVersion first computes the cache entry:

https://github.com/python/cpython/blob/39e69a7cd54d44c9061db89bb15c460d30fba7a6/Objects/typeobject.c#L5542-L5544

If the cache entry doesn't match, and a type version was assigned successfully, it populates the same entry:

https://github.com/python/cpython/blob/39e69a7cd54d44c9061db89bb15c460d30fba7a6/Objects/typeobject.c#L5629-L5634

The next call for the same (type, name) pair, will find a different entry, because the type version is used to compute the hash that indexes into the cache:

https://github.com/python/cpython/blob/39e69a7cd54d44c9061db89bb15c460d30fba7a6/Objects/typeobject.c#L46-L48

It looks like the change to use the same entry was introduced in gh-113930. cc @DinoV

CPython versions tested on:

3.13, 3.14

Operating systems tested on:

Linux

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

Objects/typeobject.c の _PyType_LookupRefAndVersion と、参照されている行付近のキャッシュハッシュ計算から始めます。バージョンなしのパスと、新しく割り当てられたバージョンのパスを追跡し、その後、繰り返し行われるルックアップが、割り当てられたバージョンをインデックスとするキャッシュエントリを使用し、不要なエントリを残さないことを確認します。適切な回帰チェックでは、ルックアップ結果を変更せずに、修正されたキャッシュ動作を示す必要があります。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
c, python
領域
performance
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。