@@ -4186,9 +4186,15 @@ def test_sneaky_hardlink_fallback(self):
41864186 for filter in 'tar' , 'fully_trusted' :
41874187 with self .subTest (filter ), self .check_context (arc .open (), filter ):
41884188 if not os_helper .can_symlink ():
4189- self .expect_file ("a/t/dummy" )
4190- self .expect_file ("b/" )
4191- self .expect_file ("c/" )
4189+ if filter == 'tar' :
4190+ self .expect_exception (
4191+ tarfile .LinkFallbackError ,
4192+ "link 'boom' would be extracted as a copy of "
4193+ + "'c/escape', which was rejected" )
4194+ else :
4195+ self .expect_file ("a/t/dummy" )
4196+ self .expect_file ("b/" )
4197+ self .expect_file ("c/" )
41924198 else :
41934199 self .expect_file ("a/t/dummy" )
41944200 self .expect_file ("b/" )
@@ -4367,6 +4373,25 @@ def testing_filter(member, path):
43674373 if os_helper .can_chmod ():
43684374 self .assertFalse (path .stat ().st_mode & stat .S_IWUSR )
43694375
4376+ @symlink_test
4377+ def test_extract_filters_target_none (self ):
4378+ # Test that when extract() falls back to extracting (rather than
4379+ # linking) a hardlink target, the member is skipped if the filter
4380+ # returns None.
4381+ with ArchiveMaker () as arc :
4382+ arc .add ('a/b/s' , symlink_to = '../escape' )
4383+ arc .add ('q' , hardlink_to = 'a/b/s' )
4384+ def filter_unsafe_members (member , path ):
4385+ try :
4386+ return tarfile .data_filter (member , path )
4387+ except tarfile .FilterError as error :
4388+ return None
4389+ with self .check_context (arc .open (), filter_unsafe_members ):
4390+ if os_helper .can_symlink ():
4391+ self .expect_file ('a/b/s' , symlink_to = '../escape' )
4392+ else :
4393+ self .expect_file ('a/b/' ) # symlink is not extracted
4394+
43704395 def test_link_fallback_normalizes (self ):
43714396 # Make sure hardlink fallbacks work for non-normalized paths for all
43724397 # filters
0 commit comments