From: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Date: Sun, 14 Dec 2025 09:03:14 +0000 (+0100) Subject: [3.13] gh-142554: avoid `divmod` crashes due to bad `_pylong.int_divmod` (GH-142673... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22490438749339c22f1544e1ddc82502623102a5;p=thirdparty%2FPython%2Fcpython.git [3.13] gh-142554: avoid `divmod` crashes due to bad `_pylong.int_divmod` (GH-142673) (#142697) gh-142554: avoid `divmod` crashes due to bad `_pylong.int_divmod` (#142673) (cherry picked from commit 4e4163676add8caab2dec6cdb93e1b317cf02a2e) --- diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index 48825f46911b..072c676c742f 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -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 index 000000000000..d0aafe2c44bb --- /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 23f50c7ed28a..06d9ae4742ff 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -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);