[php-src] master: Merge branch 'PHP-8.4' into PHP-8.5

David Carlier <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: David Carlier (devnexen)
Date: 2026-08-30T15:26:35+01:00

Commit: https://github.com/php/php-src/commit/a1851722b86fe21a785e56dd925747c2c229bc67
Raw diff: https://github.com/php/php-src/commit/a1851722b86fe21a785e56dd925747c2c229bc67.diff

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  ext/zip: php_zip_ops_stat() succeeds when the archive cannot be opened.
  ext/zip: ZipArchive::getNameIndex() index truncated to int.

Changed paths:
  A  ext/zip/tests/oo_getnameindex_large_index.phpt
  A  ext/zip/tests/stream_fstat_unreadable_archive.phpt
  M  ext/zip/php_zip.c
  M  ext/zip/zip_stream.c


Diff:

diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 74c8db3fefde..369ec5f46ea5 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -2136,7 +2136,7 @@ PHP_METHOD(ZipArchive, getNameIndex)
 
 	ZIP_FROM_OBJECT(intern, self);
 
-	name = zip_get_name(intern, (int) index, flags);
+	name = zip_get_name(intern, (zip_uint64_t) index, flags);
 
 	if (name) {
 		RETVAL_STRING((char *)name);
diff --git a/ext/zip/tests/oo_getnameindex_large_index.phpt b/ext/zip/tests/oo_getnameindex_large_index.phpt
new file mode 100644
index 000000000000..471dffc38d91
--- /dev/null
+++ b/ext/zip/tests/oo_getnameindex_large_index.phpt
@@ -0,0 +1,44 @@
+--TEST--
+ZipArchive::getNameIndex() with an index that does not fit in an int
+--EXTENSIONS--
+zip
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE != 8) die('skip 64-bit only');
+?>
+--FILE--
+<?php
+$file = __DIR__ . '/oo_getnameindex_large_index.zip';
+
+@unlink($file);
+
+$zip = new ZipArchive;
+if (!$zip->open($file, ZipArchive::CREATE)) {
+    exit('failed');
+}
+
+$zip->addFromString('entry1.txt', 'entry #1');
+$zip->close();
+
+if (!$zip->open($file)) {
+    exit('failed');
+}
+
+var_dump($zip->getNameIndex(0));
+var_dump($zip->getNameIndex(1 << 32));
+var_dump($zip->getNameIndex((1 << 32) + 1));
+var_dump($zip->getNameIndex(PHP_INT_MAX));
+var_dump($zip->getNameIndex(-1));
+
+$zip->close();
+?>
+--EXPECT--
+string(10) "entry1.txt"
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+--CLEAN--
+<?php
+unlink(__DIR__ . '/oo_getnameindex_large_index.zip');
+?>
diff --git a/ext/zip/tests/stream_fstat_unreadable_archive.phpt b/ext/zip/tests/stream_fstat_unreadable_archive.phpt
new file mode 100644
index 000000000000..a81fc8fc3cfc
--- /dev/null
+++ b/ext/zip/tests/stream_fstat_unreadable_archive.phpt
@@ -0,0 +1,38 @@
+--TEST--
+fstat() on a zip:// stream whose archive can no longer be opened
+--EXTENSIONS--
+zip
+--SKIPIF--
+<?php
+if (PHP_OS_FAMILY === 'Windows') die('skip the archive cannot be rewritten while it is open');
+?>
+--FILE--
+<?php
+$file = __DIR__ . '/stream_fstat_unreadable_archive.zip';
+
+@unlink($file);
+
+$zip = new ZipArchive;
+if (!$zip->open($file, ZipArchive::CREATE)) {
+    exit('failed');
+}
+
+$zip->addFromString('entry.txt', 'entry');
+$zip->close();
+
+$fp = fopen('zip://' . $file . '#entry.txt', 'rb');
+var_dump($fp !== false);
+
+file_put_contents($file, 'this is not a zip archive');
+
+var_dump(fstat($fp));
+
+fclose($fp);
+?>
+--EXPECT--
+bool(true)
+bool(false)
+--CLEAN--
+<?php
+unlink(__DIR__ . '/stream_fstat_unreadable_archive.zip');
+?>
diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c
index 0356863ef7ce..b70b82a415ec 100644
--- a/ext/zip/zip_stream.c
+++ b/ext/zip/zip_stream.c
@@ -195,6 +195,9 @@ static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{
 		ssb->sb.st_blocks = -1;
 #endif
 		ssb->sb.st_ino = -1;
+	} else {
+		zend_string_release_ex(file_basename, 0);
+		return -1;
 	}
 	zend_string_release_ex(file_basename, 0);
 	return 0;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.