@@ -1297,6 +1297,35 @@ def find_class(module_name, global_name):
1297
1297
self .assertEqual (loads (b'cmath\n log\n .' ), ('math' , 'log' ))
1298
1298
self .assertEqual (loads (b'\x8c \x04 math\x8c \x03 log\x93 .' ), ('math' , 'log' ))
1299
1299
1300
+ def test_bad_ext_code (self ):
1301
+ # unregistered extension code
1302
+ self .check_unpickling_error (ValueError , b'\x82 \x01 .' )
1303
+ self .check_unpickling_error (ValueError , b'\x82 \xff .' )
1304
+ self .check_unpickling_error (ValueError , b'\x83 \x01 \x00 .' )
1305
+ self .check_unpickling_error (ValueError , b'\x83 \xff \xff .' )
1306
+ self .check_unpickling_error (ValueError , b'\x84 \x01 \x00 \x00 \x00 .' )
1307
+ self .check_unpickling_error (ValueError , b'\x84 \xff \xff \xff \x7f .' )
1308
+ # EXT specifies code <= 0
1309
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x82 \x00 .' )
1310
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x83 \x00 \x00 .' )
1311
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x84 \x00 \x00 \x00 \x00 .' )
1312
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x84 \x00 \x00 \x00 \x80 .' )
1313
+ self .check_unpickling_error (pickle .UnpicklingError , b'\x84 \xff \xff \xff \xff .' )
1314
+
1315
+ @support .cpython_only
1316
+ def test_bad_ext_inverted_registry (self ):
1317
+ code = 1
1318
+ def check (key , exc ):
1319
+ with support .swap_item (copyreg ._inverted_registry , code , key ):
1320
+ with self .assertRaises (exc ):
1321
+ self .loads (b'\x82 \x01 .' )
1322
+ check (None , ValueError )
1323
+ check ((), ValueError )
1324
+ check ((__name__ ,), (TypeError , ValueError ))
1325
+ check ((__name__ , "MyList" , "x" ), (TypeError , ValueError ))
1326
+ check ((__name__ , None ), (TypeError , ValueError ))
1327
+ check ((None , "MyList" ), (TypeError , ValueError ))
1328
+
1300
1329
def test_bad_reduce (self ):
1301
1330
self .assertEqual (self .loads (b'cbuiltins\n int\n )R.' ), 0 )
1302
1331
self .check_unpickling_error (TypeError , b'N)R.' )
@@ -2033,6 +2062,28 @@ def persistent_id(self, obj):
2033
2062
check ({Clearer (): 1 , Clearer (): 2 })
2034
2063
check ({1 : Clearer (), 2 : Clearer ()})
2035
2064
2065
+ @support .cpython_only
2066
+ def test_bad_ext_code (self ):
2067
+ # This should never happen in normal circumstances, because the type
2068
+ # and the value of the extesion code is checked in copyreg.add_extension().
2069
+ key = (__name__ , 'MyList' )
2070
+ def check (code , exc ):
2071
+ assert key not in copyreg ._extension_registry
2072
+ assert code not in copyreg ._inverted_registry
2073
+ with (support .swap_item (copyreg ._extension_registry , key , code ),
2074
+ support .swap_item (copyreg ._inverted_registry , code , key )):
2075
+ for proto in protocols [2 :]:
2076
+ with self .assertRaises (exc ):
2077
+ self .dumps (MyList , proto )
2078
+
2079
+ check (object (), TypeError )
2080
+ check (None , TypeError )
2081
+ check (- 1 , (RuntimeError , struct .error ))
2082
+ check (0 , RuntimeError )
2083
+ check (2 ** 31 , (RuntimeError , OverflowError , struct .error ))
2084
+ check (2 ** 1000 , (OverflowError , struct .error ))
2085
+ check (- 2 ** 1000 , (OverflowError , struct .error ))
2086
+
2036
2087
2037
2088
class AbstractPickleTests :
2038
2089
# Subclass must define self.dumps, self.loads.
0 commit comments