#3664: The pickle module could segfault if a Pickler instance is not correctly initialized:
when a subclass forgets to call the base __init__ method, or when __init__ is called a second time with invalid parameters Patch by Alexandre Vassalotti.
This commit is contained in:
parent
869bad9b5a
commit
87eee631fb
|
@ -996,6 +996,20 @@ class AbstractPickleModuleTests(unittest.TestCase):
|
|||
pickle.Pickler(f, -1)
|
||||
pickle.Pickler(f, protocol=-1)
|
||||
|
||||
def test_bad_init(self):
|
||||
# Test issue3664 (pickle can segfault from a badly initialized Pickler).
|
||||
from io import BytesIO
|
||||
# Override initialization without calling __init__() of the superclass.
|
||||
class BadPickler(pickle.Pickler):
|
||||
def __init__(self): pass
|
||||
|
||||
class BadUnpickler(pickle.Unpickler):
|
||||
def __init__(self): pass
|
||||
|
||||
self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
|
||||
self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
|
||||
|
||||
|
||||
class AbstractPersistentPicklerTests(unittest.TestCase):
|
||||
|
||||
# This class defines persistent_id() and persistent_load()
|
||||
|
|
|
@ -33,7 +33,10 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- telnetlib now works completely in bytes.
|
||||
- Issue #3664: The pickle module could segfault if a subclass of Pickler fails
|
||||
to call the base __init__ method.
|
||||
|
||||
- Issue #3725: telnetlib now works completely in bytes.
|
||||
|
||||
- Issue #4072: Restore build_py_2to3.
|
||||
|
||||
|
|
|
@ -421,6 +421,11 @@ pickler_write(PicklerObject *self, const char *s, Py_ssize_t n)
|
|||
{
|
||||
PyObject *data, *result;
|
||||
|
||||
if (self->write_buf == NULL) {
|
||||
PyErr_SetString(PyExc_SystemError, "invalid write buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s == NULL) {
|
||||
if (!(self->buf_size))
|
||||
return 0;
|
||||
|
@ -2378,6 +2383,16 @@ Pickler_dump(PicklerObject *self, PyObject *args)
|
|||
{
|
||||
PyObject *obj;
|
||||
|
||||
/* Check whether the Pickler was initialized correctly (issue3664).
|
||||
Developers often forget to call __init__() in their subclasses, which
|
||||
would trigger a segfault without this check. */
|
||||
if (self->write == NULL) {
|
||||
PyErr_Format(PicklingError,
|
||||
"Pickler.__init__() was not called by %s.__init__()",
|
||||
Py_TYPE(self)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:dump", &obj))
|
||||
return NULL;
|
||||
|
||||
|
|
Loading…
Reference in New Issue