Commit bc3a7c7b175 for php.net

commit bc3a7c7b175eccba23d215054ad871c0a8208c26
Author: Weilin Du <weilindu@php.net>
Date:   Fri Jul 3 14:14:25 2026 +0800

    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

diff --git a/NEWS b/NEWS
index 1edc25b4899..6d4d1865d79 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 b29ba2c370b..16df403dcda 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 00000000000..41dabb22451
--- /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--
+<?php
+$name = __DIR__ . '/bug_gh21705.zip';
+@unlink($name);
+$zip = new ZipArchive;
+$zip->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--
+<?php
+$name = __DIR__ . '/bug_gh21705.zip';
+@unlink($name);
+?>
+--EXPECT--
+string(3) "bar"
+string(3) "bar"