https://github.com/python/cpython/commit/4e4163676add8caab2dec6cdb93e1b317cf02a2e
commit: 4e4163676add8caab2dec6cdb93e1b317cf02a2e
branch: main
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2025-12-14T09:38:23+01:00
summary:
gh-142554: avoid `divmod` crashes due to bad `_pylong.int_divmod` (#142673)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2025-12-13-17-20-38.gh-issue-142554.wNtEFF.rst
M Lib/test/test_int.py
M Objects/longobject.c
diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py
index 7a7cb73f673787..fa675f626cbe10 100644
--- a/Lib/test/test_int.py
+++ b/Lib/test/test_int.py
@@ -778,6 +778,18 @@ def test_pylong_int_divmod(self):
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
index 00000000000000..d0aafe2c44bb4a
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-13-17-20-38.gh-issue-142554.wNtEFF.rst
@@ -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.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 43c0db753a0fb9..8ba1fd65078f48 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -4434,10 +4434,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);
_______________________________________________
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]