@@ -1297,6 +1297,35 @@ def find_class(module_name, global_name):
12971297 self .assertEqual (loads (b'cmath\n log\n .' ), ('math' , 'log' ))
12981298 self .assertEqual (loads (b'\x8c \x04 math\x8c \x03 log\x93 .' ), ('math' , 'log' ))
12991299
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+
13001329 def test_bad_reduce (self ):
13011330 self .assertEqual (self .loads (b'cbuiltins\n int\n )R.' ), 0 )
13021331 self .check_unpickling_error (TypeError , b'N)R.' )
@@ -2033,6 +2062,28 @@ def persistent_id(self, obj):
20332062 check ({Clearer (): 1 , Clearer (): 2 })
20342063 check ({1 : Clearer (), 2 : Clearer ()})
20352064
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+
20362087
20372088class AbstractPickleTests :
20382089 # Subclass must define self.dumps, self.loads.
0 commit comments