bpo-41288: Fix a crash in unpickling invalid NEWOBJ_EX. (GH-21458)
Automerge-Triggered-By: @tiran
(cherry picked from commit 4f309abf55
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
c77f71f981
commit
f56c75ed53
|
@ -1170,6 +1170,24 @@ class AbstractUnpickleTests(unittest.TestCase):
|
||||||
self.assertIs(type(unpickled), collections.UserDict)
|
self.assertIs(type(unpickled), collections.UserDict)
|
||||||
self.assertEqual(unpickled, collections.UserDict({1: 2}))
|
self.assertEqual(unpickled, collections.UserDict({1: 2}))
|
||||||
|
|
||||||
|
def test_bad_reduce(self):
|
||||||
|
self.assertEqual(self.loads(b'cbuiltins\nint\n)R.'), 0)
|
||||||
|
self.check_unpickling_error(TypeError, b'N)R.')
|
||||||
|
self.check_unpickling_error(TypeError, b'cbuiltins\nint\nNR.')
|
||||||
|
|
||||||
|
def test_bad_newobj(self):
|
||||||
|
error = (pickle.UnpicklingError, TypeError)
|
||||||
|
self.assertEqual(self.loads(b'cbuiltins\nint\n)\x81.'), 0)
|
||||||
|
self.check_unpickling_error(error, b'cbuiltins\nlen\n)\x81.')
|
||||||
|
self.check_unpickling_error(error, b'cbuiltins\nint\nN\x81.')
|
||||||
|
|
||||||
|
def test_bad_newobj_ex(self):
|
||||||
|
error = (pickle.UnpicklingError, TypeError)
|
||||||
|
self.assertEqual(self.loads(b'cbuiltins\nint\n)}\x92.'), 0)
|
||||||
|
self.check_unpickling_error(error, b'cbuiltins\nlen\n)}\x92.')
|
||||||
|
self.check_unpickling_error(error, b'cbuiltins\nint\nN}\x92.')
|
||||||
|
self.check_unpickling_error(error, b'cbuiltins\nint\n)N\x92.')
|
||||||
|
|
||||||
def test_bad_stack(self):
|
def test_bad_stack(self):
|
||||||
badpickles = [
|
badpickles = [
|
||||||
b'.', # STOP
|
b'.', # STOP
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Unpickling invalid NEWOBJ_EX opcode with the C implementation raises now
|
||||||
|
UnpicklingError instead of crashing.
|
|
@ -5988,23 +5988,30 @@ load_newobj_ex(UnpicklerObject *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyType_Check(cls)) {
|
if (!PyType_Check(cls)) {
|
||||||
Py_DECREF(kwargs);
|
|
||||||
Py_DECREF(args);
|
|
||||||
PyErr_Format(st->UnpicklingError,
|
PyErr_Format(st->UnpicklingError,
|
||||||
"NEWOBJ_EX class argument must be a type, not %.200s",
|
"NEWOBJ_EX class argument must be a type, not %.200s",
|
||||||
Py_TYPE(cls)->tp_name);
|
Py_TYPE(cls)->tp_name);
|
||||||
Py_DECREF(cls);
|
goto error;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((PyTypeObject *)cls)->tp_new == NULL) {
|
if (((PyTypeObject *)cls)->tp_new == NULL) {
|
||||||
Py_DECREF(kwargs);
|
|
||||||
Py_DECREF(args);
|
|
||||||
Py_DECREF(cls);
|
|
||||||
PyErr_SetString(st->UnpicklingError,
|
PyErr_SetString(st->UnpicklingError,
|
||||||
"NEWOBJ_EX class argument doesn't have __new__");
|
"NEWOBJ_EX class argument doesn't have __new__");
|
||||||
return -1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (!PyTuple_Check(args)) {
|
||||||
|
PyErr_Format(st->UnpicklingError,
|
||||||
|
"NEWOBJ_EX args argument must be a tuple, not %.200s",
|
||||||
|
Py_TYPE(args)->tp_name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (!PyDict_Check(kwargs)) {
|
||||||
|
PyErr_Format(st->UnpicklingError,
|
||||||
|
"NEWOBJ_EX kwargs argument must be a dict, not %.200s",
|
||||||
|
Py_TYPE(kwargs)->tp_name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
|
obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
|
||||||
Py_DECREF(kwargs);
|
Py_DECREF(kwargs);
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
|
@ -6014,6 +6021,12 @@ load_newobj_ex(UnpicklerObject *self)
|
||||||
}
|
}
|
||||||
PDATA_PUSH(self->stack, obj, -1);
|
PDATA_PUSH(self->stack, obj, -1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
Py_DECREF(kwargs);
|
||||||
|
Py_DECREF(args);
|
||||||
|
Py_DECREF(cls);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue