diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 3870b153688b25..fbcecba1fbec77 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -470,6 +470,25 @@ def test_iterator_setstate(self): it.__setstate__(2**64 - 7) self.assertEqual(list(it), [12, 10]) + def test_iterator_invalid_setstate(self): + + class I: + def __int__(self): return 1 + def __index__(self): return 1 + def __repr__(self): return "I()" + + invalid_values = (1.0, I(), "") + + for invalid_value in invalid_values: + invalid_msg = F"state must be an int, not " + ranges = (("range_iter", range(10, 100, 2)), + ("longrange_iter", range(10, 2**65, 2))) + for name, rng in ranges: + with self.subTest(invalid_value=invalid_value, range_name=name): + it = iter(rng) + with self.assertRaisesRegex(TypeError, invalid_msg): + it.__setstate__(invalid_value) + def test_odd_bug(self): # This used to raise a "SystemError: NULL result without error" # because the range validation step was eating the exception diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-10-23-07-06.gh-issue-141312.H-58GB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-10-23-07-06.gh-issue-141312.H-58GB.rst new file mode 100644 index 00000000000000..4fc9c452ecc5ac --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-10-23-07-06.gh-issue-141312.H-58GB.rst @@ -0,0 +1,2 @@ +Restict passing of non-integer object to the ``rangeiter.__setstate__`` +and ``longrangeiter.__setstate__``. Patch by Sergey Miryanov. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index f8cdfe68a6435e..fb6f8a6896d55a 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -884,6 +884,11 @@ rangeiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored)) static PyObject * rangeiter_setstate(PyObject *op, PyObject *state) { + if (!PyLong_CheckExact(state)) { + PyErr_Format(PyExc_TypeError, "state must be an int, not %T", state); + return NULL; + } + _PyRangeIterObject *r = (_PyRangeIterObject*)op; long index = PyLong_AsLong(state); if (index == -1 && PyErr_Occurred()) @@ -1042,6 +1047,11 @@ longrangeiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored)) static PyObject * longrangeiter_setstate(PyObject *op, PyObject *state) { + if (!PyLong_CheckExact(state)) { + PyErr_Format(PyExc_TypeError, "state must be an int, not %T", state); + return NULL; + } + longrangeiterobject *r = (longrangeiterobject*)op; PyObject *zero = _PyLong_GetZero(); // borrowed reference int cmp;