]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-142554: avoid `divmod` crashes due to bad `_pylong.int_divmod` (GH-142673...
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>
Sun, 14 Dec 2025 09:03:14 +0000 (10:03 +0100)
committerGitHub <noreply@github.com>
Sun, 14 Dec 2025 09:03:14 +0000 (09:03 +0000)
gh-142554: avoid `divmod` crashes due to bad `_pylong.int_divmod` (#142673)

(cherry picked from commit 4e4163676add8caab2dec6cdb93e1b317cf02a2e)

Lib/test/test_int.py
Misc/NEWS.d/next/Core and Builtins/2025-12-13-17-20-38.gh-issue-142554.wNtEFF.rst [new file with mode: 0644]
Objects/longobject.c

index 48825f46911b67abc6e6932fbcc7048552980c4e..072c676c742fa1686e15c141eba9326ee0425362 100644 (file)
@@ -859,6 +859,18 @@ class PyLongModuleTests(unittest.TestCase):
         a, b = divmod(n*3 + 1, n)
         assert a == 3 and b == 1
 
+    @support.cpython_only  # tests implementation details of CPython.
+    @unittest.skipUnless(_pylong, "_pylong module required")
+    def test_pylong_int_divmod_crash(self):
+        # Regression test for https://github.com/python/cpython/issues/142554.
+        bad_int_divmod = lambda a, b: (1,)
+        # 'k' chosen such that divmod(2**(2*k), 2**k) uses _pylong.int_divmod()
+        k = 10_000
+        a, b = (1 << (2 * k)), (1 << k)
+        with mock.patch.object(_pylong, "int_divmod", wraps=bad_int_divmod):
+            msg = r"tuple of length 2 is required from int_divmod\(\)"
+            self.assertRaisesRegex(ValueError, msg, divmod, a, b)
+
     def test_pylong_str_to_int(self):
         v1 = 1 << 100_000
         s = str(v1)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2025-12-13-17-20-38.gh-issue-142554.wNtEFF.rst b/Misc/NEWS.d/next/Core and Builtins/2025-12-13-17-20-38.gh-issue-142554.wNtEFF.rst
new file mode 100644 (file)
index 0000000..d0aafe2
--- /dev/null
@@ -0,0 +1,2 @@
+Fix a crash in :func:`divmod` when :func:`!_pylong.int_divmod` does not
+return a tuple of length two exactly. Patch by Bénédikt Tran.
index 23f50c7ed28abb606845d807b1323fa8b455abdd..06d9ae4742ffc84b79f045fae04cf8ccf7716193 100644 (file)
@@ -4324,10 +4324,10 @@ pylong_int_divmod(PyLongObject *v, PyLongObject *w,
     if (result == NULL) {
         return -1;
     }
-    if (!PyTuple_Check(result)) {
+    if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 2) {
         Py_DECREF(result);
         PyErr_SetString(PyExc_ValueError,
-                        "tuple is required from int_divmod()");
+                        "tuple of length 2 is required from int_divmod()");
         return -1;
     }
     PyObject *q = PyTuple_GET_ITEM(result, 0);