@@ -4418,9 +4418,15 @@ def test_sneaky_hardlink_fallback(self):
44184418 for filter in 'tar' , 'fully_trusted' :
44194419 with self .subTest (filter ), self .check_context (arc .open (), filter ):
44204420 if not os_helper .can_symlink ():
4421- self .expect_file ("a/t/dummy" )
4422- self .expect_file ("b/" )
4423- self .expect_file ("c/" )
4421+ if filter == 'tar' :
4422+ self .expect_exception (
4423+ tarfile .LinkFallbackError ,
4424+ "link 'boom' would be extracted as a copy of "
4425+ + "'c/escape', which was rejected" )
4426+ else :
4427+ self .expect_file ("a/t/dummy" )
4428+ self .expect_file ("b/" )
4429+ self .expect_file ("c/" )
44244430 else :
44254431 self .expect_file ("a/t/dummy" )
44264432 self .expect_file ("b/" )
@@ -4617,6 +4623,25 @@ def testing_filter(member, path):
46174623 if os_helper .can_chmod ():
46184624 self .assertFalse (path .stat ().st_mode & stat .S_IWUSR )
46194625
4626+ @symlink_test
4627+ def test_extract_filters_target_none (self ):
4628+ # Test that when extract() falls back to extracting (rather than
4629+ # linking) a hardlink target, the member is skipped if the filter
4630+ # returns None.
4631+ with ArchiveMaker () as arc :
4632+ arc .add ('a/b/s' , symlink_to = '../escape' )
4633+ arc .add ('q' , hardlink_to = 'a/b/s' )
4634+ def filter_unsafe_members (member , path ):
4635+ try :
4636+ return tarfile .data_filter (member , path )
4637+ except tarfile .FilterError as error :
4638+ return None
4639+ with self .check_context (arc .open (), filter_unsafe_members ):
4640+ if os_helper .can_symlink ():
4641+ self .expect_file ('a/b/s' , symlink_to = '../escape' )
4642+ else :
4643+ self .expect_file ('a/b/' ) # symlink is not extracted
4644+
46204645 def test_link_fallback_normalizes (self ):
46214646 # Make sure hardlink fallbacks work for non-normalized paths for all
46224647 # filters
0 commit comments