]> granicus.if.org Git - python/commitdiff
Issue #10180: Pickling file objects is now explicitly forbidden, since
authorAntoine Pitrou <solipsis@pitrou.net>
Fri, 5 Nov 2010 21:15:39 +0000 (21:15 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Fri, 5 Nov 2010 21:15:39 +0000 (21:15 +0000)
unpickling them produced nonsensical results.

Lib/_pyio.py
Lib/test/test_io.py
Misc/NEWS
Modules/_io/bufferedio.c
Modules/_io/fileio.c
Modules/_io/textio.c

index 83bce709b56ae9262d1099c2f4b4172959f9ecd4..87c833c9645668582344badc4d28b5ae81e865a6 100644 (file)
@@ -747,6 +747,10 @@ class _BufferedIOMixin(BufferedIOBase):
     def mode(self):
         return self.raw.mode
 
+    def __getstate__(self):
+        raise TypeError("can not serialize a '{0}' object"
+                        .format(self.__class__.__name__))
+
     def __repr__(self):
         clsname = self.__class__.__name__
         try:
index 680e36dc8dd3d2a66df7a149daf33218f28b7658..91dd8037b6c6d533d28d4cd5d03429d1556f3b81 100644 (file)
@@ -30,6 +30,7 @@ import abc
 import signal
 import errno
 import warnings
+import pickle
 from itertools import cycle, count
 from collections import deque
 from test import support
@@ -2566,6 +2567,23 @@ class MiscIOTest(unittest.TestCase):
         self._check_warn_on_dealloc_fd("r")
 
 
+    def test_pickling(self):
+        # Pickling file objects is forbidden
+        for kwargs in [
+                {"mode": "w"},
+                {"mode": "wb"},
+                {"mode": "wb", "buffering": 0},
+                {"mode": "r"},
+                {"mode": "rb"},
+                {"mode": "rb", "buffering": 0},
+                {"mode": "w+"},
+                {"mode": "w+b"},
+                {"mode": "w+b", "buffering": 0},
+            ]:
+            for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
+                with self.open(support.TESTFN, **kwargs) as f:
+                    self.assertRaises(TypeError, pickle.dumps, f, protocol)
+
 class CMiscIOTest(MiscIOTest):
     io = io
 
index af33d2838f22c9cd628cd9029cd779afbb89973d..18c1cde75434e7feb52a305a84fc7245b887f2e4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -65,6 +65,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #10180: Pickling file objects is now explicitly forbidden, since
+  unpickling them produced nonsensical results.
+
 - Issue #10311: The signal module now restores errno before returning from
   its low-level signal handler.  Patch by Hallvard B Furuseth.
 
index 30451692b3967f87585f9053213d0c6db9fd6926..504e2cbd14091cc6c59b16150c74bd15d4c5d84a 100644 (file)
@@ -549,6 +549,15 @@ buffered_isatty(buffered *self, PyObject *args)
     return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
 }
 
+/* Serialization */
+
+static PyObject *
+buffered_getstate(buffered *self, PyObject *args)
+{
+    PyErr_Format(PyExc_TypeError,
+                 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
+    return NULL;
+}
 
 /* Forward decls */
 static PyObject *
@@ -1489,6 +1498,7 @@ static PyMethodDef bufferedreader_methods[] = {
     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
+    {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
 
     {"read", (PyCFunction)buffered_read, METH_VARARGS},
     {"peek", (PyCFunction)buffered_peek, METH_VARARGS},
@@ -1872,6 +1882,7 @@ static PyMethodDef bufferedwriter_methods[] = {
     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
+    {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
 
     {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS},
     {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS},
@@ -2137,6 +2148,8 @@ static PyMethodDef bufferedrwpair_methods[] = {
     {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
     {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
 
+    {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
+
     {NULL, NULL}
 };
 
@@ -2257,6 +2270,7 @@ static PyMethodDef bufferedrandom_methods[] = {
     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
+    {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS},
 
     {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
 
index 09ea80f179df1a14f3ce5a0dd9473af970bec134..96fce15fef12302f24bd91a8d85fc8e67c31189a 100644 (file)
@@ -952,6 +952,14 @@ fileio_isatty(fileio *self)
     return PyBool_FromLong(res);
 }
 
+static PyObject *
+fileio_getstate(fileio *self)
+{
+    PyErr_Format(PyExc_TypeError,
+                 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
+    return NULL;
+}
+
 
 PyDoc_STRVAR(fileio_doc,
 "file(name: str[, mode: str]) -> file IO object\n"
@@ -1046,6 +1054,7 @@ static PyMethodDef fileio_methods[] = {
     {"fileno",   (PyCFunction)fileio_fileno,   METH_NOARGS,      fileno_doc},
     {"isatty",   (PyCFunction)fileio_isatty,   METH_NOARGS,      isatty_doc},
     {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
+    {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL},
     {NULL,           NULL}             /* sentinel */
 };
 
index e222067a3ad508d22d6ddb0542df8e34b62a71ae..2559714aaf9fd5d47e05b11410287da512fb385f 100644 (file)
@@ -2382,6 +2382,14 @@ textiowrapper_isatty(textio *self, PyObject *args)
     return PyObject_CallMethod(self->buffer, "isatty", NULL);
 }
 
+static PyObject *
+textiowrapper_getstate(textio *self, PyObject *args)
+{
+    PyErr_Format(PyExc_TypeError,
+                 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
+    return NULL;
+}
+
 static PyObject *
 textiowrapper_flush(textio *self, PyObject *args)
 {
@@ -2546,6 +2554,7 @@ static PyMethodDef textiowrapper_methods[] = {
     {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS},
     {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS},
     {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS},
+    {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS},
 
     {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS},
     {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS},