Issue #28322: Fixed possible crashes when unpickle itertools objects from
incorrect pickle data. Based on patch by John Leitch.
This commit is contained in:
commit
18c5e8e86f
|
@ -183,6 +183,19 @@ class TestBasicOps(unittest.TestCase):
|
||||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||||
self.pickletest(proto, chain('abc', 'def'), compare=list('abcdef'))
|
self.pickletest(proto, chain('abc', 'def'), compare=list('abcdef'))
|
||||||
|
|
||||||
|
def test_chain_setstate(self):
|
||||||
|
self.assertRaises(TypeError, chain().__setstate__, ())
|
||||||
|
self.assertRaises(TypeError, chain().__setstate__, [])
|
||||||
|
self.assertRaises(TypeError, chain().__setstate__, 0)
|
||||||
|
self.assertRaises(TypeError, chain().__setstate__, ([],))
|
||||||
|
self.assertRaises(TypeError, chain().__setstate__, (iter([]), []))
|
||||||
|
it = chain()
|
||||||
|
it.__setstate__((iter(['abc', 'def']),))
|
||||||
|
self.assertEqual(list(it), ['a', 'b', 'c', 'd', 'e', 'f'])
|
||||||
|
it = chain()
|
||||||
|
it.__setstate__((iter(['abc', 'def']), iter(['ghi'])))
|
||||||
|
self.assertEqual(list(it), ['ghi', 'a', 'b', 'c', 'd', 'e', 'f'])
|
||||||
|
|
||||||
def test_combinations(self):
|
def test_combinations(self):
|
||||||
self.assertRaises(TypeError, combinations, 'abc') # missing r argument
|
self.assertRaises(TypeError, combinations, 'abc') # missing r argument
|
||||||
self.assertRaises(TypeError, combinations, 'abc', 2, 1) # too many arguments
|
self.assertRaises(TypeError, combinations, 'abc', 2, 1) # too many arguments
|
||||||
|
@ -667,19 +680,22 @@ class TestBasicOps(unittest.TestCase):
|
||||||
self.assertEqual(take(20, c), list('defgabcdefgabcdefgab'))
|
self.assertEqual(take(20, c), list('defgabcdefgabcdefgab'))
|
||||||
|
|
||||||
# The first argument to setstate needs to be a tuple
|
# The first argument to setstate needs to be a tuple
|
||||||
with self.assertRaises(SystemError):
|
with self.assertRaises(TypeError):
|
||||||
cycle('defg').__setstate__([list('abcdefg'), 0])
|
cycle('defg').__setstate__([list('abcdefg'), 0])
|
||||||
|
|
||||||
# The first argument in the setstate tuple must be a list
|
# The first argument in the setstate tuple must be a list
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
c = cycle('defg')
|
c = cycle('defg')
|
||||||
c.__setstate__((dict.fromkeys('defg'), 0))
|
c.__setstate__((tuple('defg'), 0))
|
||||||
take(20, c)
|
take(20, c)
|
||||||
|
|
||||||
# The first argument in the setstate tuple must be a list
|
# The second argument in the setstate tuple must be an int
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
cycle('defg').__setstate__((list('abcdefg'), 'x'))
|
cycle('defg').__setstate__((list('abcdefg'), 'x'))
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, cycle('').__setstate__, ())
|
||||||
|
self.assertRaises(TypeError, cycle('').__setstate__, ([],))
|
||||||
|
|
||||||
def test_groupby(self):
|
def test_groupby(self):
|
||||||
# Check whether it accepts arguments correctly
|
# Check whether it accepts arguments correctly
|
||||||
self.assertEqual([], list(groupby([])))
|
self.assertEqual([], list(groupby([])))
|
||||||
|
|
|
@ -54,6 +54,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #28322: Fixed possible crashes when unpickle itertools objects from
|
||||||
|
incorrect pickle data. Based on patch by John Leitch.
|
||||||
|
|
||||||
- Issue #28228: imghdr now supports pathlib.
|
- Issue #28228: imghdr now supports pathlib.
|
||||||
|
|
||||||
- Issue #28226: compileall now supports pathlib.
|
- Issue #28226: compileall now supports pathlib.
|
||||||
|
|
|
@ -147,8 +147,13 @@ static PyObject *
|
||||||
groupby_setstate(groupbyobject *lz, PyObject *state)
|
groupby_setstate(groupbyobject *lz, PyObject *state)
|
||||||
{
|
{
|
||||||
PyObject *currkey, *currvalue, *tgtkey;
|
PyObject *currkey, *currvalue, *tgtkey;
|
||||||
if (!PyArg_ParseTuple(state, "OOO", &currkey, &currvalue, &tgtkey))
|
if (!PyTuple_Check(state)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "state is not a tuple");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!PyArg_ParseTuple(state, "OOO", &currkey, &currvalue, &tgtkey)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
Py_INCREF(currkey);
|
Py_INCREF(currkey);
|
||||||
Py_XSETREF(lz->currkey, currkey);
|
Py_XSETREF(lz->currkey, currkey);
|
||||||
Py_INCREF(currvalue);
|
Py_INCREF(currvalue);
|
||||||
|
@ -727,8 +732,13 @@ tee_setstate(teeobject *to, PyObject *state)
|
||||||
{
|
{
|
||||||
teedataobject *tdo;
|
teedataobject *tdo;
|
||||||
int index;
|
int index;
|
||||||
if (!PyArg_ParseTuple(state, "O!i", &teedataobject_type, &tdo, &index))
|
if (!PyTuple_Check(state)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "state is not a tuple");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!PyArg_ParseTuple(state, "O!i", &teedataobject_type, &tdo, &index)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (index < 0 || index > LINKCELLS) {
|
if (index < 0 || index > LINKCELLS) {
|
||||||
PyErr_SetString(PyExc_ValueError, "Index out of range");
|
PyErr_SetString(PyExc_ValueError, "Index out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -971,9 +981,13 @@ cycle_setstate(cycleobject *lz, PyObject *state)
|
||||||
{
|
{
|
||||||
PyObject *saved=NULL;
|
PyObject *saved=NULL;
|
||||||
int firstpass;
|
int firstpass;
|
||||||
|
if (!PyTuple_Check(state)) {
|
||||||
if (!PyArg_ParseTuple(state, "O!i", &PyList_Type, &saved, &firstpass))
|
PyErr_SetString(PyExc_TypeError, "state is not a tuple");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!PyArg_ParseTuple(state, "O!i", &PyList_Type, &saved, &firstpass)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
Py_INCREF(saved);
|
Py_INCREF(saved);
|
||||||
Py_XSETREF(lz->saved, saved);
|
Py_XSETREF(lz->saved, saved);
|
||||||
lz->firstpass = firstpass != 0;
|
lz->firstpass = firstpass != 0;
|
||||||
|
@ -1903,8 +1917,17 @@ chain_setstate(chainobject *lz, PyObject *state)
|
||||||
{
|
{
|
||||||
PyObject *source, *active=NULL;
|
PyObject *source, *active=NULL;
|
||||||
|
|
||||||
if (! PyArg_ParseTuple(state, "O|O", &source, &active))
|
if (!PyTuple_Check(state)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "state is not a tuple");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!PyArg_ParseTuple(state, "O|O", &source, &active)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!PyIter_Check(source) || (active != NULL && !PyIter_Check(active))) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "Arguments must be iterators.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Py_INCREF(source);
|
Py_INCREF(source);
|
||||||
Py_XSETREF(lz->source, source);
|
Py_XSETREF(lz->source, source);
|
||||||
|
@ -3262,10 +3285,15 @@ permutations_setstate(permutationsobject *po, PyObject *state)
|
||||||
PyObject *indices, *cycles, *result;
|
PyObject *indices, *cycles, *result;
|
||||||
Py_ssize_t n, i;
|
Py_ssize_t n, i;
|
||||||
|
|
||||||
|
if (!PyTuple_Check(state)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "state is not a tuple");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (!PyArg_ParseTuple(state, "O!O!",
|
if (!PyArg_ParseTuple(state, "O!O!",
|
||||||
&PyTuple_Type, &indices,
|
&PyTuple_Type, &indices,
|
||||||
&PyTuple_Type, &cycles))
|
&PyTuple_Type, &cycles)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
n = PyTuple_GET_SIZE(po->pool);
|
n = PyTuple_GET_SIZE(po->pool);
|
||||||
if (PyTuple_GET_SIZE(indices) != n || PyTuple_GET_SIZE(cycles) != po->r) {
|
if (PyTuple_GET_SIZE(indices) != n || PyTuple_GET_SIZE(cycles) != po->r) {
|
||||||
|
|
Loading…
Reference in New Issue