@@ -3977,9 +3977,15 @@ def test_sneaky_hardlink_fallback(self):
39773977 for filter in 'tar' , 'fully_trusted' :
39783978 with self .subTest (filter ), self .check_context (arc .open (), filter ):
39793979 if not os_helper .can_symlink ():
3980- self .expect_file ("a/t/dummy" )
3981- self .expect_file ("b/" )
3982- self .expect_file ("c/" )
3980+ if filter == 'tar' :
3981+ self .expect_exception (
3982+ tarfile .LinkFallbackError ,
3983+ "link 'boom' would be extracted as a copy of "
3984+ + "'c/escape', which was rejected" )
3985+ else :
3986+ self .expect_file ("a/t/dummy" )
3987+ self .expect_file ("b/" )
3988+ self .expect_file ("c/" )
39833989 else :
39843990 self .expect_file ("a/t/dummy" )
39853991 self .expect_file ("b/" )
@@ -4153,6 +4159,25 @@ def testing_filter(member, path):
41534159 if sys .platform != 'win32' :
41544160 self .assertFalse (path .stat ().st_mode & stat .S_IWUSR )
41554161
4162+ @symlink_test
4163+ def test_extract_filters_target_none (self ):
4164+ # Test that when extract() falls back to extracting (rather than
4165+ # linking) a hardlink target, the member is skipped if the filter
4166+ # returns None.
4167+ with ArchiveMaker () as arc :
4168+ arc .add ('a/b/s' , symlink_to = '../escape' )
4169+ arc .add ('q' , hardlink_to = 'a/b/s' )
4170+ def filter_unsafe_members (member , path ):
4171+ try :
4172+ return tarfile .data_filter (member , path )
4173+ except tarfile .FilterError as error :
4174+ return None
4175+ with self .check_context (arc .open (), filter_unsafe_members ):
4176+ if os_helper .can_symlink ():
4177+ self .expect_file ('a/b/s' , symlink_to = '../escape' )
4178+ else :
4179+ self .expect_file ('a/b/' ) # symlink is not extracted
4180+
41564181 def test_link_fallback_normalizes (self ):
41574182 # Make sure hardlink fallbacks work for non-normalized paths for all
41584183 # filters
0 commit comments