]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-31829: Make protocol 0 pickles be loadable in text mode in Python 2. (GH-11859)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 12 Jun 2019 11:50:11 +0000 (04:50 -0700)
committerGitHub <noreply@github.com>
Wed, 12 Jun 2019 11:50:11 +0000 (04:50 -0700)
Escape ``\r``, ``\0`` and ``\x1a`` (end-of-file on Windows) in Unicode strings.
(cherry picked from commit 38ab7d4721b422547f7b46b9d68968863fa70573)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/pickle.py
Lib/test/pickletester.py
Misc/NEWS.d/next/Library/2017-10-21-12-07-56.bpo-31829.6IhP-O.rst [new file with mode: 0644]
Modules/_pickle.c

index e6d003787bad89c99a25636d31a114598e235722..bfa3c0361b73c6ba406beff72276e2433c78dfc2 100644 (file)
@@ -749,7 +749,10 @@ class _Pickler:
                 self.write(BINUNICODE + pack("<I", n) + encoded)
         else:
             obj = obj.replace("\\", "\\u005c")
+            obj = obj.replace("\0", "\\u0000")
             obj = obj.replace("\n", "\\u000a")
+            obj = obj.replace("\r", "\\u000d")
+            obj = obj.replace("\x1a", "\\u001a")  # EOF on DOS
             self.write(UNICODE + obj.encode('raw-unicode-escape') +
                        b'\n')
         self.memoize(obj)
index 5540d0015ed9b3b8e1f71d119eedb6d607a19f9f..1d88fcb859af89f7d5dcda2b7c02c7a8bb646adf 100644 (file)
@@ -2709,22 +2709,20 @@ class BadGetattr:
 class AbstractPickleModuleTests(unittest.TestCase):
 
     def test_dump_closed_file(self):
-        import os
         f = open(TESTFN, "wb")
         try:
             f.close()
             self.assertRaises(ValueError, self.dump, 123, f)
         finally:
-            os.remove(TESTFN)
+            support.unlink(TESTFN)
 
     def test_load_closed_file(self):
-        import os
         f = open(TESTFN, "wb")
         try:
             f.close()
             self.assertRaises(ValueError, self.dump, 123, f)
         finally:
-            os.remove(TESTFN)
+            support.unlink(TESTFN)
 
     def test_load_from_and_dump_to_file(self):
         stream = io.BytesIO()
@@ -2748,6 +2746,19 @@ class AbstractPickleModuleTests(unittest.TestCase):
         self.Pickler(f, -1)
         self.Pickler(f, protocol=-1)
 
+    def test_dump_text_file(self):
+        f = open(TESTFN, "w")
+        try:
+            for proto in protocols:
+                self.assertRaises(TypeError, self.dump, 123, f, proto)
+        finally:
+            f.close()
+            support.unlink(TESTFN)
+
+    def test_incomplete_input(self):
+        s = io.BytesIO(b"X''.")
+        self.assertRaises((EOFError, struct.error, pickle.UnpicklingError), self.load, s)
+
     def test_bad_init(self):
         # Test issue3664 (pickle can segfault from a badly initialized Pickler).
         # Override initialization without calling __init__() of the superclass.
diff --git a/Misc/NEWS.d/next/Library/2017-10-21-12-07-56.bpo-31829.6IhP-O.rst b/Misc/NEWS.d/next/Library/2017-10-21-12-07-56.bpo-31829.6IhP-O.rst
new file mode 100644 (file)
index 0000000..aefb8ae
--- /dev/null
@@ -0,0 +1,3 @@
+``\r``, ``\0`` and ``\x1a`` (end-of-file on Windows) are now escaped in
+protocol 0 pickles of Unicode strings. This allows to load them without loss
+from files open in text mode in Python 2.
index c8b3ef70f52150006fdc91c4e3378d7f43911d65..9a6207b519fafc514e42bd462b534c5ed4bc9129 100644 (file)
@@ -2337,7 +2337,10 @@ raw_unicode_escape(PyObject *obj)
             *p++ = Py_hexdigits[ch & 15];
         }
         /* Map 16-bit characters, '\\' and '\n' to '\uxxxx' */
-        else if (ch >= 256 || ch == '\\' || ch == '\n') {
+        else if (ch >= 256 ||
+                 ch == '\\' || ch == 0 || ch == '\n' || ch == '\r' ||
+                 ch == 0x1a)
+        {
             /* -1: subtract 1 preallocated byte */
             p = _PyBytesWriter_Prepare(&writer, p, 6-1);
             if (p == NULL)