Skip to content

Commit c468b53

Browse files
committed
2 parents f635dc3 + 0eaabf1 commit c468b53

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

Lib/test/test_itertools.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,13 @@ def permutations2(iterable, r=None):
426426
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
427427
self.pickletest(proto, permutations(values, r)) # test pickling
428428

429+
@support.bigaddrspacetest
430+
def test_permutations_overflow(self):
431+
with self.assertRaises(OverflowError):
432+
permutations("A", 2**30)
433+
with self.assertRaises(OverflowError):
434+
permutations("A", 2, 2**30)
435+
429436
@support.impl_detail("tuple reuse is specific to CPython")
430437
def test_permutations_tuple_reuse(self):
431438
self.assertEqual(len(set(map(id, permutations('abcde', 3)))), 1)
@@ -955,6 +962,11 @@ def product2(*args, **kwds):
955962
args = map(iter, args)
956963
self.assertEqual(len(list(product(*args))), expected_len)
957964

965+
@support.bigaddrspacetest
966+
def test_product_overflow(self):
967+
with self.assertRaises(OverflowError):
968+
product(["a"]*(2**16), repeat=2**16)
969+
958970
@support.impl_detail("tuple reuse is specific to CPython")
959971
def test_product_tuple_reuse(self):
960972
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
@@ -50,6 +50,10 @@ Core and Builtins
5050
Library
5151
-------
5252

53+
- Issue #23363: Fix possible overflow in itertools.permutations.
54+
55+
- Issue #23364: Fix possible overflow in itertools.product.
56+
5357
- Issue #23366: Fixed possible integer overflow in itertools.combinations.
5458

5559
- Issue #23366: Fixed possible integer overflow in itertools.combinations.

Modules/itertoolsmodule.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,8 +2017,17 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
20172017
}
20182018
}
20192019

2020-
assert(PyTuple_Check(args));
2021-
nargs = (repeat == 0) ? 0 : PyTuple_GET_SIZE(args);
2020+
assert(PyTuple_CheckExact(args));
2021+
if (repeat == 0) {
2022+
nargs = 0;
2023+
} else {
2024+
nargs = PyTuple_GET_SIZE(args);
2025+
if (repeat > PY_SSIZE_T_MAX/sizeof(Py_ssize_t) ||
2026+
nargs > PY_SSIZE_T_MAX/(repeat * sizeof(Py_ssize_t))) {
2027+
PyErr_SetString(PyExc_OverflowError, "repeat argument too large");
2028+
return NULL;
2029+
}
2030+
}
20222031
npools = nargs * repeat;
20232032

20242033
indices = PyMem_Malloc(npools * sizeof(Py_ssize_t));
@@ -3049,6 +3058,11 @@ permutations_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
30493058
goto error;
30503059
}
30513060

3061+
if (n > PY_SSIZE_T_MAX/sizeof(Py_ssize_t) ||
3062+
r > PY_SSIZE_T_MAX/sizeof(Py_ssize_t)) {
3063+
PyErr_SetString(PyExc_OverflowError, "parameters too large");
3064+
goto error;
3065+
}
30523066
indices = PyMem_Malloc(n * sizeof(Py_ssize_t));
30533067
cycles = PyMem_Malloc(r * sizeof(Py_ssize_t));
30543068
if (indices == NULL || cycles == NULL) {

0 commit comments

Comments
 (0)