@@ -1311,6 +1311,35 @@ def find_class(module_name, global_name):
1311
1311
self .assertEqual (loads (b'cmath\n log\n .' ), ('math' , 'log' ))
1312
1312
self .assertEqual (loads (b'\x8c \x04 math\x8c \x03 log\x93 .' ), ('math' , 'log' ))
1313
1313
1314
+ def test_bad_ext_code (self ):
1315
+ # unregistered extension code
1316
+ self .check_unpickling_error (ValueError , b'\x82 \x01 .' )
1317
+ self .check_unpickling_error (ValueError , b'\x82 \xff .' )
1318
+ self .check_unpickling_error (ValueError , b'\x83 \x01 \x00 .' )
1319
+ self .check_unpickling_error (ValueError , b'\x83 \xff \xff .' )
1320
+ self .check_unpickling_error (ValueError , b'\x84 \x01 \x00 \x00 \x00 .' )
1321
+ self .check_unpickling_error (ValueError , b'\x84 \xff \xff \xff \x7f .' )
1322
+ # EXT specifies code <= 0
1323
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x82 \x00 .' )
1324
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x83 \x00 \x00 .' )
1325
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x84 \x00 \x00 \x00 \x00 .' )
1326
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x84 \x00 \x00 \x00 \x80 .' )
1327
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x84 \xff \xff \xff \xff .' )
1328
+
1329
+ @support .cpython_only
1330
+ def test_bad_ext_inverted_registry (self ):
1331
+ code = 1
1332
+ def check (key , exc ):
1333
+ with support .swap_item (copyreg ._inverted_registry , code , key ):
1334
+ with self .assertRaises (exc ):
1335
+ self .loads (b'\x82 \x01 .' )
1336
+ check (None , ValueError )
1337
+ check ((), ValueError )
1338
+ check ((__name__ ,), (TypeError , ValueError ))
1339
+ check ((__name__ , "MyList" , "x" ), (TypeError , ValueError ))
1340
+ check ((__name__ , None ), (TypeError , ValueError ))
1341
+ check ((None , "MyList" ), (TypeError , ValueError ))
1342
+
1314
1343
def test_bad_reduce (self ):
1315
1344
self .assertEqual (self .loads (b'cbuiltins\n int\n )R.' ), 0 )
1316
1345
self .check_unpickling_error (TypeError , b'N)R.' )
@@ -2163,6 +2192,28 @@ def persistent_id(self, obj):
2163
2192
check ({Clearer (): 1 , Clearer (): 2 })
2164
2193
check ({1 : Clearer (), 2 : Clearer ()})
2165
2194
2195
+ @support .cpython_only
2196
+ def test_bad_ext_code (self ):
2197
+ # This should never happen in normal circumstances, because the type
2198
+ # and the value of the extesion code is checked in copyreg.add_extension().
2199
+ key = (__name__ , 'MyList' )
2200
+ def check (code , exc ):
2201
+ assert key not in copyreg ._extension_registry
2202
+ assert code not in copyreg ._inverted_registry
2203
+ with (support .swap_item (copyreg ._extension_registry , key , code ),
2204
+ support .swap_item (copyreg ._inverted_registry , code , key )):
2205
+ for proto in protocols [2 :]:
2206
+ with self .assertRaises (exc ):
2207
+ self .dumps (MyList , proto )
2208
+
2209
+ check (object (), TypeError )
2210
+ check (None , TypeError )
2211
+ check (- 1 , (RuntimeError , struct .error ))
2212
+ check (0 , RuntimeError )
2213
+ check (2 ** 31 , (RuntimeError , OverflowError , struct .error ))
2214
+ check (2 ** 1000 , (OverflowError , struct .error ))
2215
+ check (- 2 ** 1000 , (OverflowError , struct .error ))
2216
+
2166
2217
2167
2218
class AbstractPickleTests :
2168
2219
# Subclass must define self.dumps, self.loads.
0 commit comments