|
2 | 2 | import unittest |
3 | 3 | import pickle |
4 | 4 | import pickletools |
| 5 | +import sys |
5 | 6 | import copyreg |
6 | 7 | from http.cookies import SimpleCookie |
7 | 8 |
|
8 | | -from test.support import TestFailed, TESTFN, run_with_locale |
| 9 | +from test.support import ( |
| 10 | + TestFailed, TESTFN, run_with_locale, |
| 11 | + _2G, _4G, precisionbigmemtest, |
| 12 | + ) |
9 | 13 |
|
10 | 14 | from pickle import bytes_types |
11 | 15 |
|
|
14 | 18 | # kind of outer loop. |
15 | 19 | protocols = range(pickle.HIGHEST_PROTOCOL + 1) |
16 | 20 |
|
| 21 | +character_size = 4 if sys.maxunicode > 0xFFFF else 2 |
| 22 | + |
17 | 23 |
|
18 | 24 | # Return True if opcode code appears in the pickle, else False. |
19 | 25 | def opcode_in_pickle(code, pickle): |
@@ -1098,6 +1104,100 @@ def test_empty_bytestring(self): |
1098 | 1104 | empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r') |
1099 | 1105 | self.assertEqual(empty, '') |
1100 | 1106 |
|
| 1107 | + def check_negative_32b_binXXX(self, dumped): |
| 1108 | + if sys.maxsize > 2**32: |
| 1109 | + self.skipTest("test is only meaningful on 32-bit builds") |
| 1110 | + # XXX Pure Python pickle reads lengths as signed and passes |
| 1111 | + # them directly to read() (hence the EOFError) |
| 1112 | + with self.assertRaises((pickle.UnpicklingError, EOFError, |
| 1113 | + ValueError, OverflowError)): |
| 1114 | + self.loads(dumped) |
| 1115 | + |
| 1116 | + def test_negative_32b_binbytes(self): |
| 1117 | + # On 32-bit builds, a BINBYTES of 2**31 or more is refused |
| 1118 | + self.check_negative_32b_binXXX(b'\x80\x03B\xff\xff\xff\xffxyzq\x00.') |
| 1119 | + |
| 1120 | + def test_negative_32b_binunicode(self): |
| 1121 | + # On 32-bit builds, a BINUNICODE of 2**31 or more is refused |
| 1122 | + self.check_negative_32b_binXXX(b'\x80\x03X\xff\xff\xff\xffxyzq\x00.') |
| 1123 | + |
| 1124 | + |
| 1125 | +class BigmemPickleTests(unittest.TestCase): |
| 1126 | + |
| 1127 | + # Binary protocols can serialize longs of up to 2GB-1 |
| 1128 | + |
| 1129 | + @precisionbigmemtest(size=_2G, memuse=1 + 1, dry_run=False) |
| 1130 | + def test_huge_long_32b(self, size): |
| 1131 | + data = 1 << (8 * size) |
| 1132 | + try: |
| 1133 | + for proto in protocols: |
| 1134 | + if proto < 2: |
| 1135 | + continue |
| 1136 | + with self.assertRaises((ValueError, OverflowError)): |
| 1137 | + self.dumps(data, protocol=proto) |
| 1138 | + finally: |
| 1139 | + data = None |
| 1140 | + |
| 1141 | + # Protocol 3 can serialize up to 4GB-1 as a bytes object |
| 1142 | + # (older protocols don't have a dedicated opcode for bytes and are |
| 1143 | + # too inefficient) |
| 1144 | + |
| 1145 | + @precisionbigmemtest(size=_2G, memuse=1 + 1, dry_run=False) |
| 1146 | + def test_huge_bytes_32b(self, size): |
| 1147 | + data = b"abcd" * (size // 4) |
| 1148 | + try: |
| 1149 | + for proto in protocols: |
| 1150 | + if proto < 3: |
| 1151 | + continue |
| 1152 | + try: |
| 1153 | + pickled = self.dumps(data, protocol=proto) |
| 1154 | + self.assertTrue(b"abcd" in pickled[:15]) |
| 1155 | + self.assertTrue(b"abcd" in pickled[-15:]) |
| 1156 | + finally: |
| 1157 | + pickled = None |
| 1158 | + finally: |
| 1159 | + data = None |
| 1160 | + |
| 1161 | + @precisionbigmemtest(size=_4G, memuse=1 + 1, dry_run=False) |
| 1162 | + def test_huge_bytes_64b(self, size): |
| 1163 | + data = b"a" * size |
| 1164 | + try: |
| 1165 | + for proto in protocols: |
| 1166 | + if proto < 3: |
| 1167 | + continue |
| 1168 | + with self.assertRaises((ValueError, OverflowError)): |
| 1169 | + self.dumps(data, protocol=proto) |
| 1170 | + finally: |
| 1171 | + data = None |
| 1172 | + |
| 1173 | + # All protocols use 1-byte per printable ASCII character; we add another |
| 1174 | + # byte because the encoded form has to be copied into the internal buffer. |
| 1175 | + |
| 1176 | + @precisionbigmemtest(size=_2G, memuse=2 + character_size, dry_run=False) |
| 1177 | + def test_huge_str_32b(self, size): |
| 1178 | + data = "abcd" * (size // 4) |
| 1179 | + try: |
| 1180 | + for proto in protocols: |
| 1181 | + try: |
| 1182 | + pickled = self.dumps(data, protocol=proto) |
| 1183 | + self.assertTrue(b"abcd" in pickled[:15]) |
| 1184 | + self.assertTrue(b"abcd" in pickled[-15:]) |
| 1185 | + finally: |
| 1186 | + pickled = None |
| 1187 | + finally: |
| 1188 | + data = None |
| 1189 | + |
| 1190 | + @precisionbigmemtest(size=_4G, memuse=1 + character_size, dry_run=False) |
| 1191 | + def test_huge_str_64b(self, size): |
| 1192 | + data = "a" * size |
| 1193 | + try: |
| 1194 | + for proto in protocols: |
| 1195 | + with self.assertRaises((ValueError, OverflowError)): |
| 1196 | + self.dumps(data, protocol=proto) |
| 1197 | + finally: |
| 1198 | + data = None |
| 1199 | + |
| 1200 | + |
1101 | 1201 | # Test classes for reduce_ex |
1102 | 1202 |
|
1103 | 1203 | class REX_one(object): |
|
0 commit comments