bpo-40956: Fix segfault when Connection.backup is called without target (GH-24503)

This commit is contained in:
Erlend Egeberg Aasland 2021-02-11 00:04:02 +01:00 committed by GitHub
parent 749d40a53f
commit ea46579067
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 22 deletions

View file

@ -17,9 +17,11 @@ class BackupTests(unittest.TestCase):
self.assertEqual(result[0][0], 3) self.assertEqual(result[0][0], 3)
self.assertEqual(result[1][0], 4) self.assertEqual(result[1][0], 4)
def test_bad_target_none(self): def test_bad_target(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
self.cx.backup(None) self.cx.backup(None)
with self.assertRaises(TypeError):
self.cx.backup()
def test_bad_target_filename(self): def test_bad_target_filename(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):

View file

@ -0,0 +1,3 @@
Fix segfault in :meth:`sqlite3.Connection.backup` if no argument was
provided. The regression was introduced by GH-23838. Patch by
Erlend E. Aasland.

View file

@ -519,8 +519,8 @@ pysqlite_connection_iterdump(pysqlite_Connection *self, PyObject *Py_UNUSED(igno
} }
PyDoc_STRVAR(pysqlite_connection_backup__doc__, PyDoc_STRVAR(pysqlite_connection_backup__doc__,
"backup($self, /, target=<unrepresentable>, *, pages=-1, progress=None,\n" "backup($self, /, target, *, pages=-1, progress=None, name=\'main\',\n"
" name=\'main\', sleep=0.25)\n" " sleep=0.25)\n"
"--\n" "--\n"
"\n" "\n"
"Makes a backup of the database. Non-standard."); "Makes a backup of the database. Non-standard.");
@ -541,31 +541,22 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_
static const char * const _keywords[] = {"target", "pages", "progress", "name", "sleep", NULL}; static const char * const _keywords[] = {"target", "pages", "progress", "name", "sleep", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "backup", 0}; static _PyArg_Parser _parser = {NULL, _keywords, "backup", 0};
PyObject *argsbuf[5]; PyObject *argsbuf[5];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
pysqlite_Connection *target = NULL; pysqlite_Connection *target;
int pages = -1; int pages = -1;
PyObject *progress = Py_None; PyObject *progress = Py_None;
const char *name = "main"; const char *name = "main";
double sleep = 0.25; double sleep = 0.25;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) { if (!args) {
goto exit; goto exit;
} }
if (!noptargs) { if (!PyObject_TypeCheck(args[0], pysqlite_ConnectionType)) {
goto skip_optional_pos; _PyArg_BadArgument("backup", "argument 'target'", (pysqlite_ConnectionType)->tp_name, args[0]);
goto exit;
} }
if (args[0]) { target = (pysqlite_Connection *)args[0];
if (!PyObject_TypeCheck(args[0], pysqlite_ConnectionType)) {
_PyArg_BadArgument("backup", "argument 'target'", (pysqlite_ConnectionType)->tp_name, args[0]);
goto exit;
}
target = (pysqlite_Connection *)args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
}
skip_optional_pos:
if (!noptargs) { if (!noptargs) {
goto skip_optional_kwonly; goto skip_optional_kwonly;
} }
@ -719,4 +710,4 @@ exit:
#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */
/*[clinic end generated code: output=7cb13d491a5970aa input=a9049054013a1b77]*/ /*[clinic end generated code: output=c1bf09db3bcd0105 input=a9049054013a1b77]*/

View file

@ -1582,7 +1582,7 @@ finally:
/*[clinic input] /*[clinic input]
_sqlite3.Connection.backup as pysqlite_connection_backup _sqlite3.Connection.backup as pysqlite_connection_backup
target: object(type='pysqlite_Connection *', subclass_of='pysqlite_ConnectionType') = NULL target: object(type='pysqlite_Connection *', subclass_of='pysqlite_ConnectionType')
* *
pages: int = -1 pages: int = -1
progress: object = None progress: object = None
@ -1597,7 +1597,7 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self,
pysqlite_Connection *target, int pages, pysqlite_Connection *target, int pages,
PyObject *progress, const char *name, PyObject *progress, const char *name,
double sleep) double sleep)
/*[clinic end generated code: output=306a3e6a38c36334 input=2f3497ea530144b1]*/ /*[clinic end generated code: output=306a3e6a38c36334 input=30ae45fc420bfd3b]*/
{ {
int rc; int rc;
int callback_error = 0; int callback_error = 0;