@@ -4071,9 +4071,15 @@ def test_sneaky_hardlink_fallback(self):
40714071 for filter in 'tar' , 'fully_trusted' :
40724072 with self .subTest (filter ), self .check_context (arc .open (), filter ):
40734073 if not os_helper .can_symlink ():
4074- self .expect_file ("a/t/dummy" )
4075- self .expect_file ("b/" )
4076- self .expect_file ("c/" )
4074+ if filter == 'tar' :
4075+ self .expect_exception (
4076+ tarfile .LinkFallbackError ,
4077+ "link 'boom' would be extracted as a copy of "
4078+ + "'c/escape', which was rejected" )
4079+ else :
4080+ self .expect_file ("a/t/dummy" )
4081+ self .expect_file ("b/" )
4082+ self .expect_file ("c/" )
40774083 else :
40784084 self .expect_file ("a/t/dummy" )
40794085 self .expect_file ("b/" )
@@ -4252,6 +4258,25 @@ def testing_filter(member, path):
42524258 if os_helper .can_chmod ():
42534259 self .assertFalse (path .stat ().st_mode & stat .S_IWUSR )
42544260
4261+ @symlink_test
4262+ def test_extract_filters_target_none (self ):
4263+ # Test that when extract() falls back to extracting (rather than
4264+ # linking) a hardlink target, the member is skipped if the filter
4265+ # returns None.
4266+ with ArchiveMaker () as arc :
4267+ arc .add ('a/b/s' , symlink_to = '../escape' )
4268+ arc .add ('q' , hardlink_to = 'a/b/s' )
4269+ def filter_unsafe_members (member , path ):
4270+ try :
4271+ return tarfile .data_filter (member , path )
4272+ except tarfile .FilterError as error :
4273+ return None
4274+ with self .check_context (arc .open (), filter_unsafe_members ):
4275+ if os_helper .can_symlink ():
4276+ self .expect_file ('a/b/s' , symlink_to = '../escape' )
4277+ else :
4278+ self .expect_file ('a/b/' ) # symlink is not extracted
4279+
42554280 def test_link_fallback_normalizes (self ):
42564281 # Make sure hardlink fallbacks work for non-normalized paths for all
42574282 # filters
0 commit comments