[php-src] master: Merge branch '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:27:14+01:00
Commit: https://github.com/php/php-src/commit/c09c2e98b374a78a126d1dc39057ab2ab3538e9b
Raw diff: https://github.com/php/php-src/commit/c09c2e98b374a78a126d1dc39057ab2ab3538e9b.diff
Merge branch 'PHP-8.5'
* PHP-8.5:
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 a7a3e340ecf1..15994b60cc70 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -2197,7 +2197,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 a6665630e350..429342b36e3d 100644
--- a/ext/zip/zip_stream.c
+++ b/ext/zip/zip_stream.c
@@ -192,6 +192,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, false);
return 0;