-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
Open
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-sqlite3type-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
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
Metadata
Metadata
Assignees
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-sqlite3type-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Projects
Status
No status