python / python/cpython

sqlite3 Connection and Cursor segfault if __init__ is bypassed (by subclass or __new__ call)

Đang mở
#152,954 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

extension-modules topic-sqlite3 type-crash
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

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. 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

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.