Skip to content

Commit e660734

Browse files
committed
Improve tests & an error message
1 parent f2c619a commit e660734

File tree

2 files changed

+62
-13
lines changed

2 files changed

+62
-13
lines changed

Lib/tarfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ def __init__(self, tarinfo):
742742
class AbsoluteLinkError(FilterError):
743743
def __init__(self, tarinfo):
744744
self.tarinfo = tarinfo
745-
super().__init__(f'{tarinfo.name!r} is a symlink to an absolute path')
745+
super().__init__(f'{tarinfo.name!r} is a link to an absolute path')
746746

747747
class LinkOutsideDestinationError(FilterError):
748748
def __init__(self, tarinfo, path):

Lib/test/test_tarfile.py

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3496,8 +3496,15 @@ def test_parent_symlink(self):
34963496
# Test interplaying symlinks
34973497
# Inspired by 'dirsymlink2a' in jwilk/traversal-archives
34983498
with ArchiveMaker() as arc:
3499+
3500+
# links to `.` which is both:
3501+
# - the destination directory
3502+
# - `current` itself
34993503
arc.add('current', symlink_to='.')
3504+
3505+
# effectively points to ./../
35003506
arc.add('parent', symlink_to='current/..')
3507+
35013508
arc.add('parent/evil')
35023509

35033510
if os_helper.can_symlink():
@@ -3540,8 +3547,15 @@ def test_parent_symlink2(self):
35403547
# Test interplaying symlinks
35413548
# Inspired by 'dirsymlink2b' in jwilk/traversal-archives
35423549
with ArchiveMaker() as arc:
3550+
3551+
# links to `.` which is both:
3552+
# - the destination directory
3553+
# - `current` itself
35433554
arc.add('current', symlink_to='.')
3555+
3556+
# available as `./parent`, effectively points to `./../`
35443557
arc.add('current/parent', symlink_to='..')
3558+
35453559
arc.add('parent/evil')
35463560

35473561
with self.check_context(arc.open(), 'fully_trusted'):
@@ -3553,17 +3567,29 @@ def test_parent_symlink2(self):
35533567
self.expect_file('current/')
35543568
self.expect_file('parent/evil')
35553569

3556-
for filter in 'tar', 'data':
3557-
with self.check_context(arc.open(), filter):
3558-
if os_helper.can_symlink():
3559-
self.expect_exception(
3560-
tarfile.OutsideDestinationError,
3561-
"'parent/evil' would be extracted to "
3562-
+ """['"].*evil['"], which is outside """
3563-
+ "the destination")
3564-
else:
3565-
self.expect_file('current/')
3566-
self.expect_file('parent/evil')
3570+
with self.check_context(arc.open(), 'tar'):
3571+
if os_helper.can_symlink():
3572+
# Fail when extracting a file outside destination
3573+
self.expect_exception(
3574+
tarfile.OutsideDestinationError,
3575+
"'parent/evil' would be extracted to "
3576+
+ """['"].*evil['"], which is outside """
3577+
+ "the destination")
3578+
else:
3579+
self.expect_file('current/')
3580+
self.expect_file('parent/evil')
3581+
3582+
with self.check_context(arc.open(), 'data'):
3583+
if os_helper.can_symlink():
3584+
# Fail as soon as we have a symlink outside the destination
3585+
self.expect_exception(
3586+
tarfile.LinkOutsideDestinationError,
3587+
"'current/parent' would link to "
3588+
+ """['"].*outerdir['"], which is outside """
3589+
+ "the destination")
3590+
else:
3591+
self.expect_file('current/')
3592+
self.expect_file('parent/evil')
35673593

35683594
@symlink_test
35693595
def test_absolute_symlink(self):
@@ -3593,12 +3619,30 @@ def test_absolute_symlink(self):
35933619
with self.check_context(arc.open(), 'data'):
35943620
self.expect_exception(
35953621
tarfile.AbsoluteLinkError,
3596-
"'parent' is a symlink to an absolute path")
3622+
"'parent' is a link to an absolute path")
3623+
3624+
def test_absolute_hardlink(self):
3625+
# Test hardlink to an absolute path
3626+
# Inspired by 'dirsymlink' in jwilk/traversal-archives
3627+
with ArchiveMaker() as arc:
3628+
arc.add('parent', hardlink_to=self.outerdir / 'foo')
3629+
3630+
with self.check_context(arc.open(), 'fully_trusted'):
3631+
self.expect_exception(KeyError, ".*foo. not found")
3632+
3633+
with self.check_context(arc.open(), 'tar'):
3634+
self.expect_exception(KeyError, ".*foo. not found")
3635+
3636+
with self.check_context(arc.open(), 'data'):
3637+
self.expect_exception(
3638+
tarfile.AbsoluteLinkError,
3639+
"'parent' is a link to an absolute path")
35973640

35983641
@symlink_test
35993642
def test_sly_relative0(self):
36003643
# Inspired by 'relative0' in jwilk/traversal-archives
36013644
with ArchiveMaker() as arc:
3645+
# points to `../../tmp/moo`
36023646
arc.add('../moo', symlink_to='..//tmp/moo')
36033647

36043648
try:
@@ -3651,10 +3695,15 @@ def test_sly_relative2(self):
36513695

36523696
@symlink_test
36533697
def test_deep_symlink(self):
3698+
# Test that symlinks and hardlinks inside a directory
3699+
# point to the correct file (`target` of size 3).
3700+
# If links aren't supported we get a copy of the file.
36543701
with ArchiveMaker() as arc:
36553702
arc.add('targetdir/target', size=3)
3703+
# a hardlink's linkname is relative to the archive
36563704
arc.add('linkdir/hardlink', hardlink_to=os.path.join(
36573705
'targetdir', 'target'))
3706+
# a symlink's linkname is relative to the link's directory
36583707
arc.add('linkdir/symlink', symlink_to=os.path.join(
36593708
'..', 'targetdir', 'target'))
36603709

0 commit comments

Comments
 (0)