@@ -3483,6 +3483,84 @@ def __init__(self): pass
34833483 self .assertRaises (pickle .PicklingError , BadPickler ().dump , 0 )
34843484 self .assertRaises (pickle .UnpicklingError , BadUnpickler ().load )
34853485
3486+ def test_unpickler_bad_file (self ):
3487+ # bpo-38384: Crash in _pickle if the read attribute raises an error.
3488+ def raises_oserror (self , * args , ** kwargs ):
3489+ raise OSError
3490+ @property
3491+ def bad_property (self ):
3492+ 1 / 0
3493+
3494+ # File without read and readline
3495+ class F :
3496+ pass
3497+ self .assertRaises ((AttributeError , TypeError ), self .Unpickler , F ())
3498+
3499+ # File without read
3500+ class F :
3501+ readline = raises_oserror
3502+ self .assertRaises ((AttributeError , TypeError ), self .Unpickler , F ())
3503+
3504+ # File without readline
3505+ class F :
3506+ read = raises_oserror
3507+ self .assertRaises ((AttributeError , TypeError ), self .Unpickler , F ())
3508+
3509+ # File with bad read
3510+ class F :
3511+ read = bad_property
3512+ readline = raises_oserror
3513+ self .assertRaises (ZeroDivisionError , self .Unpickler , F ())
3514+
3515+ # File with bad readline
3516+ class F :
3517+ readline = bad_property
3518+ read = raises_oserror
3519+ self .assertRaises (ZeroDivisionError , self .Unpickler , F ())
3520+
3521+ # File with bad readline, no read
3522+ class F :
3523+ readline = bad_property
3524+ self .assertRaises (ZeroDivisionError , self .Unpickler , F ())
3525+
3526+ # File with bad read, no readline
3527+ class F :
3528+ read = bad_property
3529+ self .assertRaises ((AttributeError , ZeroDivisionError ), self .Unpickler , F ())
3530+
3531+ # File with bad peek
3532+ class F :
3533+ peek = bad_property
3534+ read = raises_oserror
3535+ readline = raises_oserror
3536+ try :
3537+ self .Unpickler (F ())
3538+ except ZeroDivisionError :
3539+ pass
3540+
3541+ # File with bad readinto
3542+ class F :
3543+ readinto = bad_property
3544+ read = raises_oserror
3545+ readline = raises_oserror
3546+ try :
3547+ self .Unpickler (F ())
3548+ except ZeroDivisionError :
3549+ pass
3550+
3551+ def test_pickler_bad_file (self ):
3552+ # File without write
3553+ class F :
3554+ pass
3555+ self .assertRaises (TypeError , self .Pickler , F ())
3556+
3557+ # File with bad write
3558+ class F :
3559+ @property
3560+ def write (self ):
3561+ 1 / 0
3562+ self .assertRaises (ZeroDivisionError , self .Pickler , F ())
3563+
34863564 def check_dumps_loads_oob_buffers (self , dumps , loads ):
34873565 # No need to do the full gamut of tests here, just enough to
34883566 # check that dumps() and loads() redirect their arguments
0 commit comments