@@ -4621,9 +4621,15 @@ def test_sneaky_hardlink_fallback(self):
46214621 for filter in 'tar' , 'fully_trusted' :
46224622 with self .subTest (filter ), self .check_context (arc .open (), filter ):
46234623 if not os_helper .can_symlink ():
4624- self .expect_file ("a/t/dummy" )
4625- self .expect_file ("b/" )
4626- self .expect_file ("c/" )
4624+ if filter == 'tar' :
4625+ self .expect_exception (
4626+ tarfile .LinkFallbackError ,
4627+ "link 'boom' would be extracted as a copy of "
4628+ + "'c/escape', which was rejected" )
4629+ else :
4630+ self .expect_file ("a/t/dummy" )
4631+ self .expect_file ("b/" )
4632+ self .expect_file ("c/" )
46274633 else :
46284634 self .expect_file ("a/t/dummy" )
46294635 self .expect_file ("b/" )
@@ -4820,6 +4826,25 @@ def testing_filter(member, path):
48204826 if os_helper .can_chmod ():
48214827 self .assertFalse (path .stat ().st_mode & stat .S_IWUSR )
48224828
4829+ @symlink_test
4830+ def test_extract_filters_target_none (self ):
4831+ # Test that when extract() falls back to extracting (rather than
4832+ # linking) a hardlink target, the member is skipped if the filter
4833+ # returns None.
4834+ with ArchiveMaker () as arc :
4835+ arc .add ('a/b/s' , symlink_to = '../escape' )
4836+ arc .add ('q' , hardlink_to = 'a/b/s' )
4837+ def filter_unsafe_members (member , path ):
4838+ try :
4839+ return tarfile .data_filter (member , path )
4840+ except tarfile .FilterError as error :
4841+ return None
4842+ with self .check_context (arc .open (), filter_unsafe_members ):
4843+ if os_helper .can_symlink ():
4844+ self .expect_file ('a/b/s' , symlink_to = '../escape' )
4845+ else :
4846+ self .expect_file ('a/b/' ) # symlink is not extracted
4847+
48234848 def test_link_fallback_normalizes (self ):
48244849 # Make sure hardlink fallbacks work for non-normalized paths for all
48254850 # filters
0 commit comments