mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
[3.11] gh-50644: Forbid pickling of codecs streams (GH-109180) (GH-109232)
Attempts to pickle or create a shallow or deep copy of codecs streams
now raise a TypeError.
Previously, copying failed with a RecursionError, while pickling
produced wrong results that eventually caused unpickling to fail with
a RecursionError.
(cherry picked from commit d6892c2b92
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
c20658249d
commit
b070d73ff2
3 changed files with 95 additions and 0 deletions
|
@ -1,7 +1,9 @@
|
|||
import codecs
|
||||
import contextlib
|
||||
import copy
|
||||
import io
|
||||
import locale
|
||||
import pickle
|
||||
import sys
|
||||
import unittest
|
||||
import encodings
|
||||
|
@ -1772,6 +1774,61 @@ class StreamReaderTest(unittest.TestCase):
|
|||
f = self.reader(self.stream)
|
||||
self.assertEqual(f.readlines(), ['\ud55c\n', '\uae00'])
|
||||
|
||||
def test_copy(self):
|
||||
f = self.reader(Queue(b'\xed\x95\x9c\n\xea\xb8\x80'))
|
||||
with self.assertRaisesRegex(TypeError, 'StreamReader'):
|
||||
copy.copy(f)
|
||||
with self.assertRaisesRegex(TypeError, 'StreamReader'):
|
||||
copy.deepcopy(f)
|
||||
|
||||
def test_pickle(self):
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(protocol=proto):
|
||||
f = self.reader(Queue(b'\xed\x95\x9c\n\xea\xb8\x80'))
|
||||
with self.assertRaisesRegex(TypeError, 'StreamReader'):
|
||||
pickle.dumps(f, proto)
|
||||
|
||||
|
||||
class StreamWriterTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.writer = codecs.getwriter('utf-8')
|
||||
|
||||
def test_copy(self):
|
||||
f = self.writer(Queue(b''))
|
||||
with self.assertRaisesRegex(TypeError, 'StreamWriter'):
|
||||
copy.copy(f)
|
||||
with self.assertRaisesRegex(TypeError, 'StreamWriter'):
|
||||
copy.deepcopy(f)
|
||||
|
||||
def test_pickle(self):
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(protocol=proto):
|
||||
f = self.writer(Queue(b''))
|
||||
with self.assertRaisesRegex(TypeError, 'StreamWriter'):
|
||||
pickle.dumps(f, proto)
|
||||
|
||||
|
||||
class StreamReaderWriterTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.reader = codecs.getreader('latin1')
|
||||
self.writer = codecs.getwriter('utf-8')
|
||||
|
||||
def test_copy(self):
|
||||
f = codecs.StreamReaderWriter(Queue(b''), self.reader, self.writer)
|
||||
with self.assertRaisesRegex(TypeError, 'StreamReaderWriter'):
|
||||
copy.copy(f)
|
||||
with self.assertRaisesRegex(TypeError, 'StreamReaderWriter'):
|
||||
copy.deepcopy(f)
|
||||
|
||||
def test_pickle(self):
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(protocol=proto):
|
||||
f = codecs.StreamReaderWriter(Queue(b''), self.reader, self.writer)
|
||||
with self.assertRaisesRegex(TypeError, 'StreamReaderWriter'):
|
||||
pickle.dumps(f, proto)
|
||||
|
||||
|
||||
class EncodedFileTest(unittest.TestCase):
|
||||
|
||||
|
@ -3369,6 +3426,28 @@ class StreamRecoderTest(unittest.TestCase):
|
|||
self.assertEqual(sr.readline(), b'abc\n')
|
||||
self.assertEqual(sr.readline(), b'789\n')
|
||||
|
||||
def test_copy(self):
|
||||
bio = io.BytesIO()
|
||||
codec = codecs.lookup('ascii')
|
||||
sr = codecs.StreamRecoder(bio, codec.encode, codec.decode,
|
||||
encodings.ascii.StreamReader, encodings.ascii.StreamWriter)
|
||||
|
||||
with self.assertRaisesRegex(TypeError, 'StreamRecoder'):
|
||||
copy.copy(sr)
|
||||
with self.assertRaisesRegex(TypeError, 'StreamRecoder'):
|
||||
copy.deepcopy(sr)
|
||||
|
||||
def test_pickle(self):
|
||||
q = Queue(b'')
|
||||
codec = codecs.lookup('ascii')
|
||||
sr = codecs.StreamRecoder(q, codec.encode, codec.decode,
|
||||
encodings.ascii.StreamReader, encodings.ascii.StreamWriter)
|
||||
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
with self.subTest(protocol=proto):
|
||||
with self.assertRaisesRegex(TypeError, 'StreamRecoder'):
|
||||
pickle.dumps(sr, proto)
|
||||
|
||||
|
||||
@unittest.skipIf(_testinternalcapi is None, 'need _testinternalcapi module')
|
||||
class LocaleCodecTest(unittest.TestCase):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue