@@ -3490,11 +3490,12 @@ class ArchiveMaker:
34903490        with t.open() as tar: 
34913491            ... # `tar` is now a TarFile with 'filename' in it! 
34923492    """ 
3493-     def  __init__ (self ):
3493+     def  __init__ (self ,  ** kwargs ):
34943494        self .bio  =  io .BytesIO ()
3495+         self .tar_kwargs  =  dict (kwargs )
34953496
34963497    def  __enter__ (self ):
3497-         self .tar_w  =  tarfile .TarFile (mode = 'w' , fileobj = self .bio )
3498+         self .tar_w  =  tarfile .TarFile (mode = 'w' , fileobj = self .bio ,  ** self . tar_kwargs )
34983499        return  self 
34993500
35003501    def  __exit__ (self , * exc ):
@@ -4073,7 +4074,10 @@ def test_tar_filter(self):
40734074        # that in the test archive.) 
40744075        with  tarfile .TarFile .open (tarname ) as  tar :
40754076            for  tarinfo  in  tar .getmembers ():
4076-                 filtered  =  tarfile .tar_filter (tarinfo , '' )
4077+                 try :
4078+                     filtered  =  tarfile .tar_filter (tarinfo , '' )
4079+                 except  UnicodeEncodeError :
4080+                     continue 
40774081                self .assertIs (filtered .name , tarinfo .name )
40784082                self .assertIs (filtered .type , tarinfo .type )
40794083
@@ -4084,11 +4088,44 @@ def test_data_filter(self):
40844088            for  tarinfo  in  tar .getmembers ():
40854089                try :
40864090                    filtered  =  tarfile .data_filter (tarinfo , '' )
4087-                 except  tarfile .FilterError :
4091+                 except  ( tarfile .FilterError ,  UnicodeEncodeError ) :
40884092                    continue 
40894093                self .assertIs (filtered .name , tarinfo .name )
40904094                self .assertIs (filtered .type , tarinfo .type )
40914095
4096+     def  test_filter_unencodable (self ):
4097+         # Sanity check using a valid path. 
4098+         tarinfo  =  tarfile .TarInfo (os_helper .TESTFN )
4099+         filtered  =  tarfile .tar_filter (tarinfo , '' )
4100+         self .assertIs (filtered .name , tarinfo .name )
4101+         filtered  =  tarfile .data_filter (tarinfo , '' )
4102+         self .assertIs (filtered .name , tarinfo .name )
4103+ 
4104+         tarinfo  =  tarfile .TarInfo ('test\0 ' )
4105+         self .assertRaises (ValueError , tarfile .tar_filter , tarinfo , '' )
4106+         self .assertRaises (ValueError , tarfile .data_filter , tarinfo , '' )
4107+         tarinfo  =  tarfile .TarInfo ('\ud800 ' )
4108+         self .assertRaises (UnicodeEncodeError , tarfile .tar_filter , tarinfo , '' )
4109+         self .assertRaises (UnicodeEncodeError , tarfile .data_filter , tarinfo , '' )
4110+ 
4111+     def  test_extract_encode_error (self ):
4112+         with  ArchiveMaker (encoding = 'ascii' , errors = 'surrogateescape' ) as  arc :
4113+             arc .add ('\udced \udca0 \udc80 ' )
4114+         with  os_helper .temp_cwd () as  tmp :
4115+             tar  =  arc .open (encoding = 'utf-8' , errors = 'surrogatepass' ,
4116+                            errorlevel = 1 )
4117+             self .assertEqual (tar .getnames (), ['\ud800 ' ])
4118+             with  self .assertRaises (UnicodeEncodeError ):
4119+                 tar .extractall ()
4120+             self .assertEqual (os .listdir (), [])
4121+ 
4122+             tar  =  arc .open (encoding = 'utf-8' , errors = 'surrogatepass' ,
4123+                            errorlevel = 0 , debug = 1 )
4124+             with  support .captured_stderr () as  stderr :
4125+                 tar .extractall ()
4126+             self .assertEqual (os .listdir (), [])
4127+             self .assertIn ('tarfile: UnicodeEncodeError ' , stderr .getvalue ())
4128+ 
40924129    def  test_change_default_filter_on_instance (self ):
40934130        tar  =  tarfile .TarFile (tarname , 'r' )
40944131        def  strict_filter (tarinfo , path ):
0 commit comments