summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_codecs.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-09-10 17:06:09 (GMT)
committerGitHub <noreply@github.com>2023-09-10 17:06:09 (GMT)
commitd6892c2b9263b39ea1c7905667942914b6a24b2c (patch)
tree26857f7693712248ae06996a024659a1c73bb51f /Lib/test/test_codecs.py
parent71b6e2602c0b5b06d51855f179cdb30094a67968 (diff)
downloadcpython-d6892c2b9263b39ea1c7905667942914b6a24b2c.zip
cpython-d6892c2b9263b39ea1c7905667942914b6a24b2c.tar.gz
cpython-d6892c2b9263b39ea1c7905667942914b6a24b2c.tar.bz2
gh-50644: Forbid pickling of codecs streams (GH-109180)
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.
Diffstat (limited to 'Lib/test/test_codecs.py')
-rw-r--r--Lib/test/test_codecs.py79
1 files changed, 79 insertions, 0 deletions
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
index 91d7eaf..b5e9271 100644
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -1,7 +1,9 @@
import codecs
import contextlib
+import copy
import io
import locale
+import pickle
import sys
import unittest
import encodings
@@ -1771,6 +1773,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):
@@ -3346,6 +3403,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):