FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

test(project): cover runtime_assets checksum and extraction helpers (… · pythonnative/pythonnative@fc61648 · GitHub

Commit fc61648

Browse files
test(project): cover runtime_assets checksum and extraction helpers (#75)
Refs: #57 Co-authored-by: Owen Carey <37121709+owenthcarey@users.noreply.github.com>
1 parent 052893e commit fc61648

2 files changed

Lines changed: 408 additions & 8 deletions

File tree

‎src/pythonnative/project/runtime_assets.py‎

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,37 @@ def _sha256(path: Path) -> str:
8080

8181

8282
def _safe_extract(tar_path: Path, dest: Path) -> None:
83-
"""Extract a tarball, refusing entries that escape ``dest``."""
83+
"""Extract a tarball, refusing entries that escape ``dest``.
84+
85+
Preflight checks reject unsafe paths, link targets, and special files.
86+
The data filter also checks each member during extraction, accounting
87+
for links created by earlier members and sanitizing file permissions.
88+
"""
8489
dest = dest.resolve()
8590
with tarfile.open(tar_path, "r:gz") as tar:
8691
members = tar.getmembers()
8792
for member in members:
8893
target = (dest / member.name).resolve()
89-
if not str(target).startswith(str(dest)):
94+
# ``is_relative_to`` compares path components. A string prefix
95+
# test would accept a sibling whose name merely starts with
96+
# ``dest``, such as ``../out-evil/x.txt`` beside ``out/``.
97+
if not target.is_relative_to(dest):
9098
raise RuntimeError(f"Refusing to extract unsafe path: {member.name}")
91-
# ``filter='data'`` (3.12+) blocks unsafe members; older Pythons
92-
# fall back to the manual check above.
93-
try:
94-
tar.extractall(dest, filter="data")
95-
except TypeError:
96-
tar.extractall(dest)
99+
if member.issym() or member.islnk():
100+
# A link's name can be innocuous while its target escapes.
101+
# Symlink targets resolve against the link's own directory;
102+
# hardlink targets are relative to the archive root.
103+
base = target.parent if member.issym() else dest
104+
link_target = (base / member.linkname).resolve()
105+
if not link_target.is_relative_to(dest):
106+
raise RuntimeError(f"Refusing to extract unsafe link: {member.name} -> {member.linkname}")
107+
if member.isdev():
108+
# The pinned archives only need files, directories, and
109+
# links, so refuse FIFOs and device nodes before extraction.
110+
raise RuntimeError(f"Refusing to extract special file: {member.name}")
111+
# Every supported interpreter provides the data filter. Keep it
112+
# explicit because Python 3.13 defaults to unfiltered extraction.
113+
tar.extractall(dest, filter="data")
97114

98115

99116
def _locate_runtime(extract_root: Path, python_version: str) -> IOSRuntime:

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL