From e0c0de003b0812943922dfb51511f3e5c1248f11 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 29 Sep 2021 12:09:13 +0200 Subject: [PATCH] Fix #77978: Dirname ending in colon unzips to wrong dir When making the relative path, we must not stop on a `:\` sequence in the middle of the filename. This is only significant on Windows as it may indicate an absolute filename, but this is already checked at the beginning of the function. Note that the bug and this patch affects all systems. However, on Windows the file is no longer extracted at all, since Windows NTSF does not allow filenames containing colons. Closes GH-7528. --- NEWS | 1 + ext/zip/php_zip.c | 4 ++-- ext/zip/tests/bug77978.phpt | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 ext/zip/tests/bug77978.phpt diff --git a/NEWS b/NEWS index 90862421236..df97cf53097 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,7 @@ PHP NEWS - Zip: . Fixed bug #81490 (ZipArchive::extractTo() may leak memory). (cmb, Remi) + . Fixed bug #77978 (Dirname ending in colon unzips to wrong dir). (cmb) 23 Sep 2021, PHP 7.4.24 diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 08f49a3a560..de749a52a0f 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -117,8 +117,8 @@ static char * php_zip_make_relative_path(char *path, size_t path_len) /* {{{ */ return path; } - if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) { - /* i is the position of . or :, add 1 for / */ + if (i >= 2 && path[i -1] == '.') { + /* i is the position of ., add 1 for / */ path_begin = path + i + 1; break; } diff --git a/ext/zip/tests/bug77978.phpt b/ext/zip/tests/bug77978.phpt new file mode 100644 index 00000000000..2f3c22f4213 --- /dev/null +++ b/ext/zip/tests/bug77978.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug #77978 (Dirname ending in colon unzips to wrong dir) +--SKIPIF-- + +--FILE-- +open($file, ZipArchive::CREATE|ZipArchive::OVERWRITE); +$zip->addFromString("dir/test:/filename.txt", "contents"); +$zip->close(); + +$zip->open($file); +// Windows won't extract filenames with colons; we suppress the warning +@$zip->extractTo($target, "dir/test:/filename.txt"); +$zip->close(); + +var_dump(!file_exists("$target/filename.txt")); +var_dump(PHP_OS_FAMILY === "Windows" || file_exists("$target/dir/test:/filename.txt")); +?> +--EXPECT-- +bool(true) +bool(true) +--CLEAN-- +