This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author tehybel
Recipients ghaering, tehybel
Date 2016-08-25.15:36:50
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
The first issue is a type confusion which resides in the sqlite3 module, in the
file connection.c. The function pysqlite_connection_cursor takes an optional
argument, a factory callable:

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
                                     &factory)) {
        return NULL;

If the factory callable is given, it is called to initialize a cursor:

    cursor = PyObject_CallFunction(factory, "O", self);

After this the cursor, which is a PyObject *, is cast directly to a
pysqlite_Cursor without performing any type checking:

    if (cursor && self->row_factory != Py_None) {
        Py_XSETREF(((pysqlite_Cursor *)cursor)->row_factory, self->row_factory);

Here is a small script which is tested on Python-3.5.2, 64-bit, with
--with-pydebug enabled:

--- begin script ---

import sqlite3

conn = sqlite3.connect('poc2.db')
conn.row_factory = 12
conn.cursor(lambda x: "A"*0x10000)

--- end script ---

When run, this produces a segfault:

(gdb) r ./

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6496ad8 in pysqlite_connection_cursor (self=0x7ffff68cc370, args=<optimized out>, kwargs=<optimized out>)
    at /home/xx/Python-3.5.2/Modules/_sqlite/connection.c:322
warning: Source file is more recent than executable.
322         Py_XSETREF(((pysqlite_Cursor *)cursor)->row_factory, self->row_factory);
(gdb) p cursor
$13 = (PyObject *) 0xa46b90
(gdb) p self->row_factory
$14 = (PyObject *) 0x8d05f0 <small_ints+816>
(gdb) x/3i $pc
=> 0x7ffff6496ad8 <pysqlite_connection_cursor+221>: mov    rax,QWORD PTR [rdi+0x10]
   0x7ffff6496adc <pysqlite_connection_cursor+225>: sub    rax,0x1
   0x7ffff6496ae0 <pysqlite_connection_cursor+229>: mov    QWORD PTR [rdi+0x10],rax
(gdb) p $rdi
$15 = 0x4141414141414141

An arbitrary word in memory is decremented.


The second issue exists in the function pysqlite_connection_set_isolation_level
which resides in /Modules/_sqlite/connection.c. It can result in memory getting
freed multiple times.

The problem is that the variable self->isolation_level is not cleared before
being DECREF'd.

The code looks like this:

    static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level)

This call to Py_XDECREF can trigger an arbitrary amount of python code, e.g. via
self->isolation_level's __del__ method. That code could then call 
pysqlite_connection_set_isolation_level again, which would trigger another
Py_XDECREF call on the same self->isolation_level, which can thus be freed an
arbitrary number of times.

One way to fix this is to use Py_CLEAR instead.

Here's a proof-of-concept script which results in a segfault here:

--- begin script ---

import sqlite3

class S(str):
    def __del__(self):
        conn.isolation_level = S("B")

conn = sqlite3.connect('poc6.db')
conn.isolation_level = S("A")
conn.isolation_level = ""

--- end script ---

When run it segfaults here, with Python-3.5.2 and --with-pydebug enabled:

(gdb) r ./
Starting program: /home/xx/Python-3.5.2/python ./

Program received signal SIGSEGV, Segmentation fault.
_Py_ForgetReference (op=op@entry=0x7ffff6d81b80) at Objects/object.c:1757
1757        if (op == &refchain ||
(gdb) bt
#0  _Py_ForgetReference (op=op@entry=0x7ffff6d81b80) at Objects/object.c:1757
#1  0x000000000049f8c0 in _Py_Dealloc (op=0x7ffff6d81b80) at Objects/object.c:1785
#2  0x000000000046ced8 in method_dealloc (im=im@entry=0x7ffff7f25de8) at Objects/classobject.c:198
#3  0x000000000049f8c5 in _Py_Dealloc (op=op@entry=0x7ffff7f25de8) at Objects/object.c:1786
Date User Action Args
2016-08-25 15:36:51tehybelsetrecipients: + tehybel, ghaering
2016-08-25 15:36:51tehybelsetmessageid: <>
2016-08-25 15:36:51tehybellinkissue27861 messages
2016-08-25 15:36:50tehybelcreate