python / python/cpython

Null pointer dereference in `_sqlite` cursor cache via re-entrant parameter iterator

未關閉
#143,198 2 則留言 0 個 reaction 已指派 1 人 在 GitHub 檢視

@picnixz 已經在處理了。

開始於 2025年12月27日。

extension-modules topic-sqlite3 type-crash
主要語言
Python
星號
77.2k
分支
36k
PR 合併指標
PR 指標待擷取

描述

What happened?

cursor.executemany fetches parameters by calling PyObject_GetIter, so a crafted iterable can close the connection during iteration and clear self->connection->db. The cursor then continues into get_statement_from_cache with a NULL connection handle, leading _Py_TYPE to dereference a null pointer when trying to reuse the cached statement.

Proof of Concept:

import sqlite3

class Params:
    def __iter__(self):
        conn.close()
        return iter([(1,)])

conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.executemany('SELECT ?', Params())
Affected Versions
Python Version Status Exit Code
Python 3.9.24+ (heads/3.9:111bbc15b26, Oct 28 2025, 16:51:20) Exception 1
Python 3.10.19+ (heads/3.10:014261980b1, Oct 28 2025, 16:52:08) [Clang 18.1.3 (1ubuntu1)] Exception 1
Python 3.11.14+ (heads/3.11:88f3f5b5f11, Oct 28 2025, 16:53:08) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.12.12+ (heads/3.12:8cb2092bd8c, Oct 28 2025, 16:54:14) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.13.9+ (heads/3.13:9c8eade20c6, Oct 28 2025, 16:55:18) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.14.0+ (heads/3.14:2e216728038, Oct 28 2025, 16:56:16) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.15.0a1+ (heads/main:f5394c257ce, Oct 28 2025, 19:29:54) [GCC 13.3.0] ASAN 1
Vulnerable Code
PyObject *
_pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation, PyObject* second_argument)
{
    PyObject* parameters_list = NULL;
    PyObject* parameters_iter = NULL;
    PyObject* parameters = NULL;
    int i;
    int rc;
    int numcols;
    PyObject* column_name;

    if (!check_cursor(self)) {
        goto error;
    }

    self->locked = 1;

    if (multiple) {
        if (PyIter_Check(second_argument)) {
            /* iterator */
            parameters_iter = Py_NewRef(second_argument);
        } else {
            /* sequence */
            // Bug: Trigger __iter__ method and set self->connection->db to null
            parameters_iter = PyObject_GetIter(second_argument);
            if (!parameters_iter) {
                goto error;
            }
        }
    } else {
        parameters_list = PyList_New(0);
        if (!parameters_list) {
            goto error;
        }

        if (second_argument == NULL) {
            second_argument = PyTuple_New(0);
            if (!second_argument) {
                goto error;
            }
        } else {
            Py_INCREF(second_argument);
        }
        if (PyList_Append(parameters_list, second_argument) != 0) {
            Py_DECREF(second_argument);
            goto error;
        }
        Py_DECREF(second_argument);

        parameters_iter = PyObject_GetIter(parameters_list);
        if (!parameters_iter) {
            goto error;
        }
    }

    /* reset description */
    Py_INCREF(Py_None);
    Py_SETREF(self->description, Py_None);

    if (self->statement) {
        // Reset pending statements on this cursor.
        if (stmt_reset(self->statement) != SQLITE_OK) {
            goto reset_failure;
        }
    }

    // Crash: Use the null pointer without anycheck
    PyObject *stmt = get_statement_from_cache(self, operation);
    Py_XSETREF(self->statement, (pysqlite_Statement *)stmt);
    if (!self->statement) {
        goto error;
    }

    /* ... */
Sanitizer Output
=================================================================
==1701025==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x5d9f40309b11 bp 0x7fff345709e0 sp 0x7fff345709d0 T0)
==1701025==The signal is caused by a READ memory access.
==1701025==Hint: address points to the zero page.
    #0 0x5d9f40309b11 in _Py_TYPE Include/object.h:277
    #1 0x5d9f40309b11 in _PyVectorcall_FunctionInline Include/internal/pycore_call.h:120
    #2 0x5d9f40309b11 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:164
    #3 0x5d9f40309b11 in PyObject_Vectorcall Objects/call.c:327
    #4 0x76a658353bb4 in get_statement_from_cache Modules/_sqlite/cursor.c:562
    #5 0x76a658353bb4 in _pysqlite_query_execute Modules/_sqlite/cursor.c:884
    #6 0x5d9f40309bc7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #7 0x5d9f40309bc7 in PyObject_Vectorcall Objects/call.c:327
    #8 0x5d9f401abb82 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #9 0x5d9f4068a256 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #10 0x5d9f4068a256 in _PyEval_Vector Python/ceval.c:2005
    #11 0x5d9f4068a256 in PyEval_EvalCode Python/ceval.c:888
    #12 0x5d9f407cff8e in run_eval_code_obj Python/pythonrun.c:1365
    #13 0x5d9f407cff8e in run_mod Python/pythonrun.c:1459
    #14 0x5d9f407d4c37 in pyrun_file Python/pythonrun.c:1293
    #15 0x5d9f407d4c37 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #16 0x5d9f407d575c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #17 0x5d9f40847ecc in pymain_run_file_obj Modules/main.c:410
    #18 0x5d9f40847ecc in pymain_run_file Modules/main.c:429
    #19 0x5d9f40847ecc in pymain_run_python Modules/main.c:691
    #20 0x5d9f408497ae in Py_RunMain Modules/main.c:772
    #21 0x5d9f408497ae in pymain_main Modules/main.c:802
    #22 0x5d9f408497ae in Py_BytesMain Modules/main.c:826
    #23 0x76a658a2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #24 0x76a658a2a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #25 0x5d9f401e1694 in _start (/home/jackfromeast/Desktop/entropy/tasks/reproducexx/targets/cpython-main/python+0x20e694) (BuildId: 9b8528ade1939b4eac85ea0eb0dad4843ee8ca4b)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV Include/object.h:277 in _Py_TYPE
==1701025==ABORTING
Linked PRs
  • gh-143210

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。