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

Skip to content

Commit 243757e

Browse files
committed
Issue #10180: Pickling file objects is now explicitly forbidden, since
unpickling them produced nonsensical results.
1 parent 4a5f967 commit 243757e

6 files changed

Lines changed: 57 additions & 0 deletions

File tree

Lib/_pyio.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,10 @@ def name(self):
747747
def mode(self):
748748
return self.raw.mode
749749

750+
def __getstate__(self):
751+
raise TypeError("can not serialize a '{0}' object"
752+
.format(self.__class__.__name__))
753+
750754
def __repr__(self):
751755
clsname = self.__class__.__name__
752756
try:

Lib/test/test_io.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import signal
3131
import errno
3232
import warnings
33+
import pickle
3334
from itertools import cycle, count
3435
from collections import deque
3536
from test import support
@@ -2566,6 +2567,23 @@ def test_warn_on_dealloc_fd(self):
25662567
self._check_warn_on_dealloc_fd("r")
25672568

25682569

2570+
def test_pickling(self):
2571+
# Pickling file objects is forbidden
2572+
for kwargs in [
2573+
{"mode": "w"},
2574+
{"mode": "wb"},
2575+
{"mode": "wb", "buffering": 0},
2576+
{"mode": "r"},
2577+
{"mode": "rb"},
2578+
{"mode": "rb", "buffering": 0},
2579+
{"mode": "w+"},
2580+
{"mode": "w+b"},
2581+
{"mode": "w+b", "buffering": 0},
2582+
]:
2583+
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
2584+
with self.open(support.TESTFN, **kwargs) as f:
2585+
self.assertRaises(TypeError, pickle.dumps, f, protocol)
2586+
25692587
class CMiscIOTest(MiscIOTest):
25702588
io = io
25712589

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ Core and Builtins
6565
Library
6666
-------
6767

68+
- Issue #10180: Pickling file objects is now explicitly forbidden, since
69+
unpickling them produced nonsensical results.
70+
6871
- Issue #10311: The signal module now restores errno before returning from
6972
its low-level signal handler. Patch by Hallvard B Furuseth.
7073

Modules/_io/bufferedio.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,15 @@ buffered_isatty(buffered *self, PyObject *args)
549549
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
550550
}
551551

552+
/* Serialization */
553+
554+
static PyObject *
555+
buffered_getstate(buffered *self, PyObject *args)
556+
{
557+
PyErr_Format(PyExc_TypeError,
558+
"cannot serialize '%s' object", Py_TYPE(self)->tp_name);
559+
return NULL;
560+
}
552561

553562
/* Forward decls */
554563
static PyObject *
@@ -1489,6 +1498,7 @@ static PyMethodDef bufferedreader_methods[] = {
14891498
{"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
14901499
{"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
14911500
{"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
1501+
{"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
14921502

14931503
{"read", (PyCFunction)buffered_read, METH_VARARGS},
14941504
{"peek", (PyCFunction)buffered_peek, METH_VARARGS},
@@ -1872,6 +1882,7 @@ static PyMethodDef bufferedwriter_methods[] = {
18721882
{"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
18731883
{"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
18741884
{"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
1885+
{"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
18751886

18761887
{"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
18771888
{"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
@@ -2137,6 +2148,8 @@ static PyMethodDef bufferedrwpair_methods[] = {
21372148
{"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
21382149
{"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
21392150

2151+
{"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
2152+
21402153
{NULL, NULL}
21412154
};
21422155

@@ -2257,6 +2270,7 @@ static PyMethodDef bufferedrandom_methods[] = {
22572270
{"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
22582271
{"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
22592272
{"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2273+
{"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
22602274

22612275
{"flush", (PyCFunction)buffered_flush, METH_NOARGS},
22622276

Modules/_io/fileio.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,14 @@ fileio_isatty(fileio *self)
952952
return PyBool_FromLong(res);
953953
}
954954

955+
static PyObject *
956+
fileio_getstate(fileio *self)
957+
{
958+
PyErr_Format(PyExc_TypeError,
959+
"cannot serialize '%s' object", Py_TYPE(self)->tp_name);
960+
return NULL;
961+
}
962+
955963

956964
PyDoc_STRVAR(fileio_doc,
957965
"file(name: str[, mode: str]) -> file IO object\n"
@@ -1046,6 +1054,7 @@ static PyMethodDef fileio_methods[] = {
10461054
{"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc},
10471055
{"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc},
10481056
{"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
1057+
{"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL},
10491058
{NULL, NULL} /* sentinel */
10501059
};
10511060

Modules/_io/textio.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2382,6 +2382,14 @@ textiowrapper_isatty(textio *self, PyObject *args)
23822382
return PyObject_CallMethod(self->buffer, "isatty", NULL);
23832383
}
23842384

2385+
static PyObject *
2386+
textiowrapper_getstate(textio *self, PyObject *args)
2387+
{
2388+
PyErr_Format(PyExc_TypeError,
2389+
"cannot serialize '%s' object", Py_TYPE(self)->tp_name);
2390+
return NULL;
2391+
}
2392+
23852393
static PyObject *
23862394
textiowrapper_flush(textio *self, PyObject *args)
23872395
{
@@ -2546,6 +2554,7 @@ static PyMethodDef textiowrapper_methods[] = {
25462554
{"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS},
25472555
{"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS},
25482556
{"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS},
2557+
{"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS},
25492558

25502559
{"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS},
25512560
{"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS},

0 commit comments

Comments
 (0)