@@ -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.' )
@@ -2031,6 +2060,28 @@ def persistent_id(self, obj):
2031
2060
check ({Clearer (): 1 , Clearer (): 2 })
2032
2061
check ({1 : Clearer (), 2 : Clearer ()})
2033
2062
2063
+ @support .cpython_only
2064
+ def test_bad_ext_code (self ):
2065
+ # This should never happen in normal circumstances, because the type
2066
+ # and the value of the extesion code is checked in copyreg.add_extension().
2067
+ key = (__name__ , 'MyList' )
2068
+ def check (code , exc ):
2069
+ assert key not in copyreg ._extension_registry
2070
+ assert code not in copyreg ._inverted_registry
2071
+ with (support .swap_item (copyreg ._extension_registry , key , code ),
2072
+ support .swap_item (copyreg ._inverted_registry , code , key )):
2073
+ for proto in protocols [2 :]:
2074
+ with self .assertRaises (exc ):
2075
+ self .dumps (MyList , proto )
2076
+
2077
+ check (object (), TypeError )
2078
+ check (None , TypeError )
2079
+ check (- 1 , (RuntimeError , struct .error ))
2080
+ check (0 , RuntimeError )
2081
+ check (2 ** 31 , (RuntimeError , OverflowError , struct .error ))
2082
+ check (2 ** 1000 , (OverflowError , struct .error ))
2083
+ check (- 2 ** 1000 , (OverflowError , struct .error ))
2084
+
2034
2085
2035
2086
class AbstractPickleTests :
2036
2087
# Subclass must define self.dumps, self.loads.
0 commit comments