summaryrefslogtreecommitdiff
path: root/Modules/_sqlite
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2018-04-30 12:22:17 +0200
committerGitHub <noreply@github.com>2018-04-30 12:22:17 +0200
commitca405017d5e776a2e3d9291236e62d2e09489dd2 (patch)
tree54f7f13f52fde86c9ec8d89dd9a13c18a6ca3e72 /Modules/_sqlite
parent5ff3a161c8a6b525c5e5b3e36e9c43f5a95bda60 (diff)
downloadcpython-git-ca405017d5e776a2e3d9291236e62d2e09489dd2.tar.gz
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).
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r--Modules/_sqlite/connection.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 6e0576151c..ef2daeb0c2 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -1461,17 +1461,33 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
const char *name = "main";
int rc;
int callback_error = 0;
- double sleep_secs = 0.250;
+ PyObject *sleep_obj = NULL;
+ int sleep_ms = 250;
sqlite3 *bck_conn;
sqlite3_backup *bck_handle;
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,
- &pages, &progress, &name, &sleep_secs)) {
+ &pages, &progress, &name, &sleep_obj)) {
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)) {
return NULL;
}
@@ -1531,7 +1547,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
the engine could not make any progress */
if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) {
Py_BEGIN_ALLOW_THREADS
- sqlite3_sleep(sleep_secs * 1000.0);
+ sqlite3_sleep(sleep_ms);
Py_END_ALLOW_THREADS
}
} while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED);