diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-05-31 08:29:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-31 08:29:39 (GMT) |
commit | 38ab7d4721b422547f7b46b9d68968863fa70573 (patch) | |
tree | aac2c1543f721338b6cf665e9d289ccad43a8af6 | |
parent | ba0430211f5101c9d748d72b03926ca79c5252a8 (diff) | |
download | cpython-38ab7d4721b422547f7b46b9d68968863fa70573.zip cpython-38ab7d4721b422547f7b46b9d68968863fa70573.tar.gz cpython-38ab7d4721b422547f7b46b9d68968863fa70573.tar.bz2 |
bpo-31829: Make protocol 0 pickles be loadable in text mode in Python 2. (GH-11859)
Escape ``\r``, ``\0`` and ``\x1a`` (end-of-file on Windows) in Unicode strings.
-rw-r--r-- | Lib/pickle.py | 3 | ||||
-rw-r--r-- | Lib/test/pickletester.py | 19 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2017-10-21-12-07-56.bpo-31829.6IhP-O.rst | 3 | ||||
-rw-r--r-- | Modules/_pickle.c | 5 |
4 files changed, 25 insertions, 5 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py index cb768b2..a67ac7d 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -852,7 +852,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) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index f6fda9e..f8f3bc9 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -3067,22 +3067,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() @@ -3106,6 +3104,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 index 0000000..aefb8ae --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-21-12-07-56.bpo-31829.6IhP-O.rst @@ -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. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 57145be..34e11bd 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -2588,7 +2588,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) |