sqlite3 Connection and Cursor segfault if __init__ is bypassed (by subclass or __new__ call)
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 35.9k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
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
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với phần triển khai kết nối sqlite3 trong connection.c, đặc biệt là connection_get_row_factory, và xem xét reproducer cho thấy việc truy cập trước tp_init. Kiểm tra PR được liên kết gh-152956 và chạy các ví dụ new và subclass đã được báo cáo. Hoàn thành khi các trường hợp này không còn gây ra segfault và các bài kiểm thử sqlite3 liên quan bao phủ chúng.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- c, python
- Lĩnh vực
- databases
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 25/100