From bc3a7c7b175eccba23d215054ad871c0a8208c26 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Fri, 3 Jul 2026 14:14:25 +0800 Subject: [PATCH] Fix GH-21705: ZipArchive::getFromIndex() ignores FL_UNCHANGED (#21706) ZipArchive::getFromIndex() already passed flags to zip_fopen_index(), but it used an unflagged stat call to determine the entry size. Use the same flags for the stat lookup so deleted entries can still be read with ZipArchive::FL_UNCHANGED, matching ZipArchive::getFromName(). Closes #21706 --- NEWS | 4 ++++ ext/zip/php_zip.c | 2 +- ext/zip/tests/bug_gh21705.phpt | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 ext/zip/tests/bug_gh21705.phpt diff --git a/NEWS b/NEWS index 1edc25b4899d..6d4d1865d790 100644 --- a/NEWS +++ b/NEWS @@ -65,6 +65,10 @@ PHP NEWS . Fixed bug GH-22395 (base_convert() outputs at most 64 characters). (Weilin Du) +- Zip: + . Fixed bug GH-21705 (ZipArchive::getFromIndex() ignores + ZipArchive::FL_UNCHANGED for deleted entries). (Weilin Du) + 02 Jul 2026, PHP 8.4.23 - Core: diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index b29ba2c370b8..16df403dcda5 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -2939,7 +2939,7 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ ZIP_FROM_OBJECT(intern, self); - PHP_ZIP_STAT_INDEX(intern, index, 0, sb); + PHP_ZIP_STAT_INDEX(intern, index, flags, sb); } if (sb.size < 1) { diff --git a/ext/zip/tests/bug_gh21705.phpt b/ext/zip/tests/bug_gh21705.phpt new file mode 100644 index 000000000000..41dabb224510 --- /dev/null +++ b/ext/zip/tests/bug_gh21705.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZipArchive::getFromIndex() honors FL_UNCHANGED for deleted entries +--EXTENSIONS-- +zip +--FILE-- +open($name, ZipArchive::CREATE); +$zip->addFromString('foo.txt', 'foo'); +$zip->addFromString('bar.txt', 'bar'); +$zip->close(); + +$zip = new ZipArchive; +$zip->open($name); + +$index = $zip->locateName('bar.txt'); +$zip->deleteName('bar.txt'); + +var_dump($zip->getFromName('bar.txt', 0, ZipArchive::FL_UNCHANGED)); +var_dump($zip->getFromIndex($index, 0, ZipArchive::FL_UNCHANGED)); + +$zip->close(); +?> +--CLEAN-- + +--EXPECT-- +string(3) "bar" +string(3) "bar"