sqlite3 Connection and Cursor segfault if __init__ is bypassed (by subclass or __new__ call)
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 35.9k
- PR マージ指標
- PR 指標を取得中
説明
Crash report
What happened?
import sqlite3
con = sqlite3.Connection.__new__(sqlite3.Connection)
print(con.row_factory)
or, more likely:
import sqlite3
class MyCon(sqlite3.Connection):
def __init__(self, *a, **kw):
if self.row_factory:
pass
super().__init__()
c = MyCon(':memory:')
Both give:
fish: Job 1, './python.exe repro.py' terminated by signal SIGSEGV (Address boundary error)
LLDB:
Process 76976 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
frame #0: 0x0000000100a93df0 _sqlite3.cpython-316d-darwin.so`Py_INCREF(op=0x0000000000000000) at refcount.h:286:31 [opt] [inlined]
283 _Py_atomic_add_ssize(&op->ob_ref_shared, (1 << _Py_REF_SHARED_SHIFT));
284 }
285 #elif SIZEOF_VOID_P > 4
-> 286 uint32_t cur_refcnt = op->ob_refcnt;
287 if (cur_refcnt >= _Py_IMMORTAL_INITIAL_REFCNT) {
288 // the object is immortal
289 _Py_INCREF_IMMORTAL_STAT_INC();
Target 0: (python.exe) stopped.
warning: _sqlite3.cpython-316d-darwin.so was compiled with optimization - stepping may behave oddly; variables may not be available.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
* frame #0: 0x0000000100a93df0 _sqlite3.cpython-316d-darwin.so`Py_INCREF(op=0x0000000000000000) at refcount.h:286:31 [opt] [inlined]
frame #1: 0x0000000100a93df0 _sqlite3.cpython-316d-darwin.so`_Py_NewRef(obj=0x0000000000000000) at refcount.h:536:5 [opt] [inlined]
frame #2: 0x0000000100a93df0 _sqlite3.cpython-316d-darwin.so`connection_get_row_factory(op=0x0000007a371d4040, closure=0x0000000000000000) at connection.c:564:12 [opt]
So, basically, until the tp_init is called, both row_factory and text_factory are NULL, but are treated as always being python objects, causing a number of segfaults.
This was discovered when fixing: gh-152817 / gh-152818 which was a follow-on from: gh-149738 / gh-149754
I think the fix here is to add a tp_new that initializes the fields before python has a chance to mess with the object, and then rely on the associated guards that prevent delattr on those fields (in the above PRs)
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.16.0a0 (heads/main-dirty:c4739533f33, Jul 3 2026, 12:34:46) [Clang 21.0.0 (clang-2100.3.20.102)]
Linked PRs
- gh-152956
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
connection.c の sqlite3 接続実装、特に connection_get_row_factory から始め、tp_init 前のアクセスを示す reproducer を確認してください。リンクされている PR gh-152956 を確認し、報告されている new と subclass の例を実行してください。これらのケースで segfault が発生しなくなり、関連する sqlite3 テストでカバーされれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- c, python
- 領域
- databases
- issue の種類
- バグ
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 活発さ
- 停滞
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 25/100