Symlink archive entries had their stored target passed directly to
mz_os_make_symlink without checking containment, so a malicious
archive could create a link pointing outside the extraction root.
Add mz_path_is_symlink_target_safe to verify a link target resolves
within the destination directory, and apply it to both the UNIX1
extrafield and entry-content link targets. Reject symlink entries
outright when no destination base is set, since the target cannot be
validated without one.
Assisted-By: Claude Opus 4.8
mz_os_get_file_attribs used lstat on POSIX and GetFileAttributesW
on Win32, both of which return the link's own attributes rather
than the target's. Callers that wanted to follow a symlink had no
way to ask for that, so mz_zip_writer_add_file produced followed
entries tagged ISLNK and readers that tried to recreate them as
symlinks.
Flip mz_os_get_file_attribs to stat on POSIX and to a CreateFile +
GetFileInformationByHandle path on Win32 when the entry is a
reparse point. Add mz_os_get_link_attribs preserving the original
lstat / GetFileAttributesW semantics. Update mz_zip_writer_add_file
to pick the right getter for each branch and to skip symlinks
cleanly when neither store_links nor follow_links is set.
Refs #797.
The paper is not freely redistributable: "To copy otherwise, to republish,
to post on servers or to redistribute to lists, requires prior specific
permission and/or a fee."
It is assumed that minizip-ng has not gained permission to redistribute
it. Therefore, drop it.
The Copyright of the WinZip document is by Corel Corporation.
All rights are reserved, which includes the right to distribute copies
of the document. Therefore, drop it and reference it via URL.
There is a small race where a file can be replaced with a link between the
call to mz_os_is_symlink and the call to mz_stream_os_open. Add
MZ_OPEN_MODE_NOFOLLOW to make sure that (on POSIX) a link cannot be
followed.