Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 87eee63

Browse files
committed
#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.
1 parent 869bad9 commit 87eee63

3 files changed

Lines changed: 33 additions & 1 deletion

File tree

Lib/test/pickletester.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,20 @@ def test_callapi(self):
996996
pickle.Pickler(f, -1)
997997
pickle.Pickler(f, protocol=-1)
998998

999+
def test_bad_init(self):
1000+
# Test issue3664 (pickle can segfault from a badly initialized Pickler).
1001+
from io import BytesIO
1002+
# Override initialization without calling __init__() of the superclass.
1003+
class BadPickler(pickle.Pickler):
1004+
def __init__(self): pass
1005+
1006+
class BadUnpickler(pickle.Unpickler):
1007+
def __init__(self): pass
1008+
1009+
self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
1010+
self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
1011+
1012+
9991013
class AbstractPersistentPicklerTests(unittest.TestCase):
10001014

10011015
# This class defines persistent_id() and persistent_load()

Misc/NEWS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ Core and Builtins
3333
Library
3434
-------
3535

36-
- telnetlib now works completely in bytes.
36+
- Issue #3664: The pickle module could segfault if a subclass of Pickler fails
37+
to call the base __init__ method.
38+
39+
- Issue #3725: telnetlib now works completely in bytes.
3740

3841
- Issue #4072: Restore build_py_2to3.
3942

Modules/_pickle.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,11 @@ pickler_write(PicklerObject *self, const char *s, Py_ssize_t n)
421421
{
422422
PyObject *data, *result;
423423

424+
if (self->write_buf == NULL) {
425+
PyErr_SetString(PyExc_SystemError, "invalid write buffer");
426+
return -1;
427+
}
428+
424429
if (s == NULL) {
425430
if (!(self->buf_size))
426431
return 0;
@@ -2378,6 +2383,16 @@ Pickler_dump(PicklerObject *self, PyObject *args)
23782383
{
23792384
PyObject *obj;
23802385

2386+
/* Check whether the Pickler was initialized correctly (issue3664).
2387+
Developers often forget to call __init__() in their subclasses, which
2388+
would trigger a segfault without this check. */
2389+
if (self->write == NULL) {
2390+
PyErr_Format(PicklingError,
2391+
"Pickler.__init__() was not called by %s.__init__()",
2392+
Py_TYPE(self)->tp_name);
2393+
return NULL;
2394+
}
2395+
23812396
if (!PyArg_ParseTuple(args, "O:dump", &obj))
23822397
return NULL;
23832398

0 commit comments

Comments
 (0)