mirror of
https://github.com/python/cpython.git
synced 2025-07-23 11:15:24 +00:00
[3.13] gh-135034: Normalize link targets in tarfile, add os.path.realpath(strict='allow_missing')
(GH-135037) (GH-135064)
Addresses CVEs 2024-12718, 2025-4138, 2025-4330, and 2025-4517.
(cherry picked from commit 3612d8f517
)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
Signed-off-by: Łukasz Langa <lukasz@langa.pl>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Seth Michael Larson <seth@python.org>
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
9f3d99967c
commit
aa9eb5f757
11 changed files with 968 additions and 167 deletions
|
@ -36,7 +36,7 @@ __all__ = ["normcase","isabs","join","splitdrive","splitroot","split","splitext"
|
|||
"samefile","sameopenfile","samestat",
|
||||
"curdir","pardir","sep","pathsep","defpath","altsep","extsep",
|
||||
"devnull","realpath","supports_unicode_filenames","relpath",
|
||||
"commonpath", "isjunction","isdevdrive"]
|
||||
"commonpath", "isjunction","isdevdrive","ALLOW_MISSING"]
|
||||
|
||||
|
||||
def _get_sep(path):
|
||||
|
@ -402,6 +402,15 @@ symbolic links encountered in the path."""
|
|||
curdir = '.'
|
||||
pardir = '..'
|
||||
getcwd = os.getcwd
|
||||
if strict is ALLOW_MISSING:
|
||||
ignored_error = FileNotFoundError
|
||||
strict = True
|
||||
elif strict:
|
||||
ignored_error = ()
|
||||
else:
|
||||
ignored_error = OSError
|
||||
|
||||
maxlinks = None
|
||||
|
||||
# The stack of unresolved path parts. When popped, a special value of None
|
||||
# indicates that a symlink target has been resolved, and that the original
|
||||
|
@ -462,25 +471,28 @@ symbolic links encountered in the path."""
|
|||
path = newpath
|
||||
continue
|
||||
target = os.readlink(newpath)
|
||||
except OSError:
|
||||
if strict:
|
||||
raise
|
||||
path = newpath
|
||||
except ignored_error:
|
||||
pass
|
||||
else:
|
||||
# Resolve the symbolic link
|
||||
if target.startswith(sep):
|
||||
# Symlink target is absolute; reset resolved path.
|
||||
path = sep
|
||||
if maxlinks is None:
|
||||
# Mark this symlink as seen but not fully resolved.
|
||||
seen[newpath] = None
|
||||
# Push the symlink path onto the stack, and signal its specialness
|
||||
# by also pushing None. When these entries are popped, we'll
|
||||
# record the fully-resolved symlink target in the 'seen' mapping.
|
||||
rest.append(newpath)
|
||||
rest.append(None)
|
||||
# Push the unresolved symlink target parts onto the stack.
|
||||
target_parts = target.split(sep)[::-1]
|
||||
rest.extend(target_parts)
|
||||
part_count += len(target_parts)
|
||||
continue
|
||||
# Resolve the symbolic link
|
||||
seen[newpath] = None # not resolved symlink
|
||||
if target.startswith(sep):
|
||||
# Symlink target is absolute; reset resolved path.
|
||||
path = sep
|
||||
# Push the symlink path onto the stack, and signal its specialness by
|
||||
# also pushing None. When these entries are popped, we'll record the
|
||||
# fully-resolved symlink target in the 'seen' mapping.
|
||||
rest.append(newpath)
|
||||
rest.append(None)
|
||||
# Push the unresolved symlink target parts onto the stack.
|
||||
target_parts = target.split(sep)[::-1]
|
||||
rest.extend(target_parts)
|
||||
part_count += len(target_parts)
|
||||
# An error occurred and was ignored.
|
||||
path = newpath
|
||||
|
||||
return path
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue