File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -387,17 +387,24 @@ def check_zip_members(zf: zipfile.ZipFile) -> list[zipfile.ZipInfo]:
387387
388388 @staticmethod
389389 def _is_unsafe_symlink_target (target : str ) -> bool :
390- r"""Return *True* when *target* is an absolute symlink destination.
390+ r"""Return *True* when *target* is an unsafe symlink destination.
391391
392392 Absolute targets (POSIX ``/`` or Windows drive/UNC anchors) are
393- always unsafe regardless of context. Relative targets that contain
394- ``..`` components are NOT rejected here; they are validated after
395- extraction by :meth:`_check_symlinks_in_dest` using the manifest
396- root as the safety boundary.
393+ always unsafe. Relative targets containing ``..`` components are
394+ also rejected: during :meth:`tarfile.TarFile.extractall` an
395+ already-extracted symlink can be followed when writing a later
396+ member, so a ``..``-based target can escape *dest_dir* before
397+ :meth:`_check_symlinks_in_dest` runs. That method remains as a
398+ secondary check for any case not caught here.
397399 """
398400 posix = pathlib .PurePosixPath (target )
399401 win = pathlib .PureWindowsPath (target )
400- return posix .is_absolute () or bool (win .anchor )
402+ return (
403+ posix .is_absolute ()
404+ or bool (win .anchor )
405+ or ".." in posix .parts
406+ or ".." in win .parts
407+ )
401408
402409 @staticmethod
403410 def _check_symlinks_in_dest (dest_dir : str ) -> None :
Original file line number Diff line number Diff line change @@ -254,3 +254,4 @@ Feature: Fetching dependencies from an archive (tar/zip)
254254 link.mk
255255 dfetch.yaml
256256 """
257+ And 'MyProject/SomeProject/sub/dir/link.mk' is a symlink pointing to '../../other/target.mk'
Original file line number Diff line number Diff line change @@ -363,6 +363,15 @@ def step_impl(_, name):
363363 assert os .path .exists (name ), f"Expected { name } to exist, but it didn't!"
364364
365365
366+ @then ("'{path}' is a symlink pointing to '{target}'" )
367+ def step_impl (_ , path , target ):
368+ assert os .path .islink (
369+ path
370+ ), f"Expected { path !r} to be a symbolic link, but it is not"
371+ actual = os .readlink (path )
372+ assert actual == target , f"Expected { path !r} to point to { target !r} , got { actual !r} "
373+
374+
366375def multisub (patterns : List [Tuple [Pattern [str ], str ]], text : str ) -> str :
367376 """Apply a list of tuples that each contain a regex + replace string."""
368377 for pattern , replace in patterns :
You can’t perform that action at this time.
0 commit comments