Skip to content

Commit aef2658

Browse files
committed
Account for differences in symlink resolution
1 parent e660734 commit aef2658

File tree

1 file changed

+48
-10
lines changed

1 file changed

+48
-10
lines changed

Lib/test/test_tarfile.py

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3546,14 +3546,44 @@ def test_parent_symlink(self):
35463546
def test_parent_symlink2(self):
35473547
# Test interplaying symlinks
35483548
# Inspired by 'dirsymlink2b' in jwilk/traversal-archives
3549+
3550+
# Posix and Windows have different pathname resolution:
3551+
# either symlink or a '..' component resolve first.
3552+
# Let's see which we are on.
3553+
if os_helper.can_symlink():
3554+
testpath = os.path.join(TEMPDIR, 'resolution_test')
3555+
os.mkdir(testpath)
3556+
3557+
# testpath/current links to `.` which is all of:
3558+
# - `testpath`
3559+
# - `testpath/current`
3560+
# - `testpath/current/current`
3561+
# - etc.
3562+
os.symlink('.', os.path.join(testpath, 'current'))
3563+
3564+
# we'll test where `testpath/current/../file` ends up
3565+
with open(os.path.join(testpath, 'current', '..', 'file'), 'w'):
3566+
pass
3567+
3568+
if os.path.exists(os.path.join(testpath, 'file')):
3569+
# Windows collapses 'current\..' to '.' first, leaving
3570+
# 'testpath\file'
3571+
dotdot_resolves_early = True
3572+
elif os.path.exists(os.path.join(testpath, '..', 'file')):
3573+
# Posix resolves 'current' to '.' first, leaving
3574+
# 'testpath/../file'
3575+
dotdot_resolves_early = False
3576+
else:
3577+
raise AssertionError('Could not determine link resolution')
3578+
35493579
with ArchiveMaker() as arc:
35503580

3551-
# links to `.` which is both:
3552-
# - the destination directory
3553-
# - `current` itself
3581+
# `current` links to `.` which is both the destination directory
3582+
# and `current` itself
35543583
arc.add('current', symlink_to='.')
35553584

3556-
# available as `./parent`, effectively points to `./../`
3585+
# `current/parent` is also available as `./parent`,
3586+
# and effectively points to `./../`
35573587
arc.add('current/parent', symlink_to='..')
35583588

35593589
arc.add('parent/evil')
@@ -3581,12 +3611,20 @@ def test_parent_symlink2(self):
35813611

35823612
with self.check_context(arc.open(), 'data'):
35833613
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")
3614+
if dotdot_resolves_early:
3615+
# Fail when extracting a file outside destination
3616+
self.expect_exception(
3617+
tarfile.OutsideDestinationError,
3618+
"'parent/evil' would be extracted to "
3619+
+ """['"].*evil['"], which is outside """
3620+
+ "the destination")
3621+
else:
3622+
# Fail as soon as we have a symlink outside the destination
3623+
self.expect_exception(
3624+
tarfile.LinkOutsideDestinationError,
3625+
"'current/parent' would link to "
3626+
+ """['"].*outerdir['"], which is outside """
3627+
+ "the destination")
35903628
else:
35913629
self.expect_file('current/')
35923630
self.expect_file('parent/evil')

0 commit comments

Comments
 (0)