Skip to content

Commit 2249043

Browse files
authored
[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 4e41636)
1 parent aa07232 commit 2249043

File tree

3 files changed

+16
-2
lines changed

3 files changed

+16
-2
lines changed

Lib/test/test_int.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,18 @@ def test_pylong_int_divmod(self):
859859
a, b = divmod(n*3 + 1, n)
860860
assert a == 3 and b == 1
861861

862+
@support.cpython_only # tests implementation details of CPython.
863+
@unittest.skipUnless(_pylong, "_pylong module required")
864+
def test_pylong_int_divmod_crash(self):
865+
# Regression test for https://github.com/python/cpython/issues/142554.
866+
bad_int_divmod = lambda a, b: (1,)
867+
# 'k' chosen such that divmod(2**(2*k), 2**k) uses _pylong.int_divmod()
868+
k = 10_000
869+
a, b = (1 << (2 * k)), (1 << k)
870+
with mock.patch.object(_pylong, "int_divmod", wraps=bad_int_divmod):
871+
msg = r"tuple of length 2 is required from int_divmod\(\)"
872+
self.assertRaisesRegex(ValueError, msg, divmod, a, b)
873+
862874
def test_pylong_str_to_int(self):
863875
v1 = 1 << 100_000
864876
s = str(v1)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in :func:`divmod` when :func:`!_pylong.int_divmod` does not
2+
return a tuple of length two exactly. Patch by Bénédikt Tran.

Objects/longobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4324,10 +4324,10 @@ pylong_int_divmod(PyLongObject *v, PyLongObject *w,
43244324
if (result == NULL) {
43254325
return -1;
43264326
}
4327-
if (!PyTuple_Check(result)) {
4327+
if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 2) {
43284328
Py_DECREF(result);
43294329
PyErr_SetString(PyExc_ValueError,
4330-
"tuple is required from int_divmod()");
4330+
"tuple of length 2 is required from int_divmod()");
43314331
return -1;
43324332
}
43334333
PyObject *q = PyTuple_GET_ITEM(result, 0);

0 commit comments

Comments
 (0)