Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0eaabf1

Browse files
committed
check for overflows in permutations() and product() (closes #23363, closes #23364)
1 parent 6f08229 commit 0eaabf1

3 files changed

Lines changed: 32 additions & 2 deletions

File tree

Lib/test/test_itertools.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,13 @@ def permutations2(iterable, r=None):
418418

419419
self.pickletest(permutations(values, r)) # test pickling
420420

421+
@support.bigaddrspacetest
422+
def test_permutations_overflow(self):
423+
with self.assertRaises(OverflowError):
424+
permutations("A", 2**30)
425+
with self.assertRaises(OverflowError):
426+
permutations("A", 2, 2**30)
427+
421428
@support.impl_detail("tuple resuse is CPython specific")
422429
def test_permutations_tuple_reuse(self):
423430
self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1)
@@ -930,6 +937,11 @@ def product2(*args, **kwds):
930937
args = map(iter, args)
931938
self.assertEqual(len(list(product(*args))), expected_len)
932939

940+
@support.bigaddrspacetest
941+
def test_product_overflow(self):
942+
with self.assertRaises(OverflowError):
943+
product(["a"]*(2**16), repeat=2**16)
944+
933945
@support.impl_detail("tuple reuse is specific to CPython")
934946
def test_product_tuple_reuse(self):
935947
self.assertEqual(len(set(map(id, product('abc', 'def')))), 1)

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ Core and Builtins
1616
Library
1717
-------
1818

19+
- Issue #23363: Fix possible overflow in itertools.permutations.
20+
21+
- Issue #23364: Fix possible overflow in itertools.product.
22+
1923
- Issue #23369: Fixed possible integer overflow in
2024
_json.encode_basestring_ascii.
2125

Modules/itertoolsmodule.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,8 +1998,17 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
19981998
}
19991999
}
20002000

2001-
assert(PyTuple_Check(args));
2002-
nargs = (repeat == 0) ? 0 : PyTuple_GET_SIZE(args);
2001+
assert(PyTuple_CheckExact(args));
2002+
if (repeat == 0) {
2003+
nargs = 0;
2004+
} else {
2005+
nargs = PyTuple_GET_SIZE(args);
2006+
if (repeat > PY_SSIZE_T_MAX/sizeof(Py_ssize_t) ||
2007+
nargs > PY_SSIZE_T_MAX/(repeat * sizeof(Py_ssize_t))) {
2008+
PyErr_SetString(PyExc_OverflowError, "repeat argument too large");
2009+
return NULL;
2010+
}
2011+
}
20032012
npools = nargs * repeat;
20042013

20052014
indices = PyMem_Malloc(npools * sizeof(Py_ssize_t));
@@ -2992,6 +3001,11 @@ permutations_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
29923001
goto error;
29933002
}
29943003

3004+
if (n > PY_SSIZE_T_MAX/sizeof(Py_ssize_t) ||
3005+
r > PY_SSIZE_T_MAX/sizeof(Py_ssize_t)) {
3006+
PyErr_SetString(PyExc_OverflowError, "parameters too large");
3007+
goto error;
3008+
}
29953009
indices = PyMem_Malloc(n * sizeof(Py_ssize_t));
29963010
cycles = PyMem_Malloc(r * sizeof(Py_ssize_t));
29973011
if (indices == NULL || cycles == NULL) {

0 commit comments

Comments
 (0)