[Python-checkins] bpo-27645, sqlite: Fix integer overflow on sleep (#6594)

Victor Stinner webhook-mailer at python.org
Mon Apr 30 06:22:27 EDT 2018


https://github.com/python/cpython/commit/ca405017d5e776a2e3d9291236e62d2e09489dd2
commit: ca405017d5e776a2e3d9291236e62d2e09489dd2
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2018-04-30T12:22:17+02:00
summary:

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).

files:
M Modules/_sqlite/connection.c

diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 6e0576151ccb..ef2daeb0c257 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);



More information about the Python-checkins mailing list