bpo-27645, sqlite: Fix integer overflow on sleep (#6594)

Use the _PyTime_t type and round away from zero (ROUND_UP,
_PyTime_ROUND_TIMEOUT) the sleep duration, when converting a Python
object to seconds and then to milliseconds. Raise an OverflowError in
case of overflow.

Previously the (int)double conversion rounded towards zero
(ROUND_DOWN).
This commit is contained in:
Victor Stinner 2018-04-30 12:22:17 +02:00 committed by GitHub
parent 5ff3a161c8
commit ca405017d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 20 additions and 4 deletions

View File

@ -1461,17 +1461,33 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
const char *name = "main"; const char *name = "main";
int rc; int rc;
int callback_error = 0; int callback_error = 0;
double sleep_secs = 0.250; PyObject *sleep_obj = NULL;
int sleep_ms = 250;
sqlite3 *bck_conn; sqlite3 *bck_conn;
sqlite3_backup *bck_handle; sqlite3_backup *bck_handle;
static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL}; static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsd:backup", keywords, if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsO:backup", keywords,
&pysqlite_ConnectionType, &target, &pysqlite_ConnectionType, &target,
&pages, &progress, &name, &sleep_secs)) { &pages, &progress, &name, &sleep_obj)) {
return NULL; return NULL;
} }
if (sleep_obj != NULL) {
_PyTime_t sleep_secs;
if (_PyTime_FromSecondsObject(&sleep_secs, sleep_obj,
_PyTime_ROUND_TIMEOUT)) {
return NULL;
}
_PyTime_t ms = _PyTime_AsMilliseconds(sleep_secs,
_PyTime_ROUND_TIMEOUT);
if (ms < INT_MIN || ms > INT_MAX) {
PyErr_SetString(PyExc_OverflowError, "sleep is too large");
return NULL;
}
sleep_ms = (int)ms;
}
if (!pysqlite_check_connection((pysqlite_Connection *)target)) { if (!pysqlite_check_connection((pysqlite_Connection *)target)) {
return NULL; return NULL;
} }
@ -1531,7 +1547,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
the engine could not make any progress */ the engine could not make any progress */
if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) { if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) {
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
sqlite3_sleep(sleep_secs * 1000.0); sqlite3_sleep(sleep_ms);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
} while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED);