diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2016-09-01 19:21:05 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2016-09-01 19:21:05 (GMT) |
commit | af0628e045c024fec27432afd1f20c0d08095197 (patch) | |
tree | 67ca762679d23287ed5eb05db2af9e90f2f7749a /Modules/_sqlite | |
parent | 5c071c1ff4c96ccd9d5a1ae381a3bb3ac4590223 (diff) | |
parent | 2891492d2357253fd832485023c78e593660319d (diff) | |
download | cpython-af0628e045c024fec27432afd1f20c0d08095197.zip cpython-af0628e045c024fec27432afd1f20c0d08095197.tar.gz cpython-af0628e045c024fec27432afd1f20c0d08095197.tar.bz2 |
Issue #27881: Fixed possible bugs when setting sqlite3.Connection.isolation_level.
Based on patch by Xiang Zhang.
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r-- | Modules/_sqlite/connection.c | 72 | ||||
-rw-r--r-- | Modules/_sqlite/connection.h | 5 |
2 files changed, 35 insertions, 42 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 1889dcd..409fa74 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -43,6 +43,14 @@ _Py_IDENTIFIER(cursor); +static const char * const begin_statements[] = { + "BEGIN ", + "BEGIN DEFERRED", + "BEGIN IMMEDIATE", + "BEGIN EXCLUSIVE", + NULL +}; + static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level); static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); @@ -258,9 +266,6 @@ void pysqlite_connection_dealloc(pysqlite_Connection* self) Py_END_ALLOW_THREADS } - if (self->begin_statement) { - PyMem_Free(self->begin_statement); - } Py_XDECREF(self->isolation_level); Py_XDECREF(self->function_pinboard); Py_XDECREF(self->row_factory); @@ -1175,59 +1180,48 @@ static PyObject* pysqlite_connection_get_total_changes(pysqlite_Connection* self static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level) { - PyObject* res; - PyObject* begin_statement; - static PyObject* begin_word; - - Py_XDECREF(self->isolation_level); - - if (self->begin_statement) { - PyMem_Free(self->begin_statement); - self->begin_statement = NULL; - } - if (isolation_level == Py_None) { - Py_INCREF(Py_None); - self->isolation_level = Py_None; - - res = pysqlite_connection_commit(self, NULL); + PyObject *res = pysqlite_connection_commit(self, NULL); if (!res) { return -1; } Py_DECREF(res); + self->begin_statement = NULL; self->inTransaction = 0; } else { - const char *statement; - Py_ssize_t size; - - Py_INCREF(isolation_level); - self->isolation_level = isolation_level; - - if (!begin_word) { - begin_word = PyUnicode_FromString("BEGIN "); - if (!begin_word) return -1; - } - begin_statement = PyUnicode_Concat(begin_word, isolation_level); - if (!begin_statement) { + const char * const *candidate; + PyObject *uppercase_level; + _Py_IDENTIFIER(upper); + + if (!PyUnicode_Check(isolation_level)) { + PyErr_Format(PyExc_TypeError, + "isolation_level must be a string or None, not %.100s", + Py_TYPE(isolation_level)->tp_name); return -1; } - statement = _PyUnicode_AsStringAndSize(begin_statement, &size); - if (!statement) { - Py_DECREF(begin_statement); + uppercase_level = _PyObject_CallMethodIdObjArgs( + (PyObject *)&PyUnicode_Type, &PyId_upper, + isolation_level, NULL); + if (!uppercase_level) { return -1; } - self->begin_statement = PyMem_Malloc(size + 2); - if (!self->begin_statement) { - Py_DECREF(begin_statement); + for (candidate = begin_statements; *candidate; candidate++) { + if (!PyUnicode_CompareWithASCIIString(uppercase_level, *candidate + 6)) + break; + } + Py_DECREF(uppercase_level); + if (!*candidate) { + PyErr_SetString(PyExc_ValueError, + "invalid value for isolation_level"); return -1; } - - strcpy(self->begin_statement, statement); - Py_DECREF(begin_statement); + self->begin_statement = *candidate; } + Py_INCREF(isolation_level); + Py_XSETREF(self->isolation_level, isolation_level); return 0; } diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index fbd9063..adbfb54 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -55,9 +55,8 @@ typedef struct /* None for autocommit, otherwise a PyUnicode with the isolation level */ PyObject* isolation_level; - /* NULL for autocommit, otherwise a string with the BEGIN statement; will be - * freed in connection destructor */ - char* begin_statement; + /* NULL for autocommit, otherwise a string with the BEGIN statement */ + const char* begin_statement; /* 1 if a check should be performed for each API call if the connection is * used from the same thread it was created in */ |