https://github.com/python/cpython/commit/daebcac92d422d7fe9611cbe89044af23ea857c3
commit: daebcac92d422d7fe9611cbe89044af23ea857c3
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-21T10:04:25+03:00
summary:

gh-156100: Fix crashes in the sqlite3 Connection.autocommit setter (GH-156104)

Deleting the attribute crashed, and setting it to an integer which does not
fit in C long reported success with OverflowError set.

files:
A Misc/NEWS.d/next/Library/2026-08-20-12-05-00.gh-issue-156100.Lm7qWz.rst
M Lib/test/test_sqlite3/test_transactions.py
M Modules/_sqlite/connection.c

diff --git a/Lib/test/test_sqlite3/test_transactions.py 
b/Lib/test/test_sqlite3/test_transactions.py
index a3de7a7a82ec1cb..2e5d60fe9ba5fc0 100644
--- a/Lib/test/test_sqlite3/test_transactions.py
+++ b/Lib/test/test_sqlite3/test_transactions.py
@@ -389,10 +389,25 @@ def test_autocommit_setget(self):
 
     def test_autocommit_setget_invalid(self):
         msg = "autocommit must be True, False, or.*LEGACY"
-        for mode in "a", 12, (), None:
+        for mode in "a", 12, (), None, 2**1000, -2**1000:
             with self.subTest(mode=mode):
                 with self.assertRaisesRegex(ValueError, msg):
                     sqlite.connect(":memory:", autocommit=mode)
+                with memory_database() as cx:
+                    with self.assertRaisesRegex(ValueError, msg):
+                        cx.autocommit = mode
+                    # a failed assignment does not change the value
+                    self.assertEqual(cx.autocommit,
+                                     sqlite.LEGACY_TRANSACTION_CONTROL)
+
+    def test_autocommit_delete(self):
+        with memory_database() as cx:
+            cx.autocommit = False
+            with self.assertRaisesRegex(AttributeError,
+                                        "cannot delete autocommit attribute"):
+                del cx.autocommit
+            # a failed deletion does not change the value
+            self.assertIs(cx.autocommit, False)
 
     def test_autocommit_disabled(self):
         expected = [
diff --git 
a/Misc/NEWS.d/next/Library/2026-08-20-12-05-00.gh-issue-156100.Lm7qWz.rst 
b/Misc/NEWS.d/next/Library/2026-08-20-12-05-00.gh-issue-156100.Lm7qWz.rst
new file mode 100644
index 000000000000000..8c296a9a8919fc3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-08-20-12-05-00.gh-issue-156100.Lm7qWz.rst
@@ -0,0 +1,4 @@
+Fix crashes in :class:`sqlite3.Connection` when deleting the
+:attr:`~sqlite3.Connection.autocommit` attribute or setting it to an integer
+which does not fit in C :c:expr:`long`.
+Both now raise an exception.
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 892740b05e55c98..ec47471873f7822 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -104,11 +104,16 @@ autocommit_converter(PyObject *val, enum autocommit_mode 
*result)
         *result = AUTOCOMMIT_DISABLED;
         return 1;
     }
-    if (PyLong_Check(val) &&
-        PyLong_AsLong(val) == LEGACY_TRANSACTION_CONTROL)
-    {
-        *result = AUTOCOMMIT_LEGACY;
-        return 1;
+    if (PyLong_Check(val)) {
+        int overflow;
+        long value = PyLong_AsLongAndOverflow(val, &overflow);
+        if (value == -1 && PyErr_Occurred()) {
+            return 0;
+        }
+        if (!overflow && value == LEGACY_TRANSACTION_CONTROL) {
+            *result = AUTOCOMMIT_LEGACY;
+            return 1;
+        }
     }
 
     PyErr_SetString(PyExc_ValueError,
@@ -2621,6 +2626,11 @@ static int
 set_autocommit(PyObject *op, PyObject *val, void *Py_UNUSED(closure))
 {
     pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
+    if (val == NULL) {
+        PyErr_SetString(PyExc_AttributeError,
+                        "cannot delete autocommit attribute");
+        return -1;
+    }
     if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
         return -1;
     }

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to