Commit 61edcf9be7d for php

commit 61edcf9be7d16a325ff94d714f1208bcb00e90a4
Author: lazerg <lazerg2@gmail.com>
Date:   Sun Nov 1 14:21:30 2026 +0800

    Fix GH-25089: Heap buffer over-read via crafted alias size in zip-based phar (#25099)

    phar_parse_zipfile() set the alias length from the size claimed in the ZIP
    headers before reading the alias, but the buffer only holds what was
    actually decompressed. A smaller payload made phar_validate_alias() and
    Phar::getAlias() read past the buffer.

    Set the alias length after reading the alias, using the actual number of
    bytes read.

    Fixes #25089.

    Closes #25099

diff --git a/NEWS b/NEWS
index 14ce817e8ca..e3b60ecc14a 100644
--- a/NEWS
+++ b/NEWS
@@ -234,6 +234,8 @@ PHP                                                                        NEWS
     (mvorisek)

 - Phar:
+  . Fixed bug GH-25089 (Heap buffer over-read via crafted alias size in
+    zip-based phar). (Lazizbek Ergashev)
   . Fixed bug GH-8469 (Phar::decompressFiles() and Phar::compressFiles() retain
     compressed contents after changing compression). (Raphael Paez)
   . Fixed bug GH-24740 (Oversized tar metadata exhausts the memory limit).
diff --git a/ext/phar/tests/zip/gh25089.phpt b/ext/phar/tests/zip/gh25089.phpt
new file mode 100644
index 00000000000..ec68c035f0c
--- /dev/null
+++ b/ext/phar/tests/zip/gh25089.phpt
@@ -0,0 +1,35 @@
+--TEST--
+GH-25089 (Heap buffer over-read via crafted alias size in zip-based phar)
+--EXTENSIONS--
+phar
+zlib
+--FILE--
+<?php
+$name = '.phar/alias.txt';
+$alias = 'ABCD';
+$data = gzdeflate($alias);
+$crc = crc32($alias);
+$claimed = 0x1000;
+
+$local = "PK\x03\x04"
+    . pack('vvvvvVVVvv', 20, 0, 8, 0, 0,
+        $crc, strlen($data), $claimed, strlen($name), 0)
+    . $name . $data;
+$central = "PK\x01\x02"
+    . pack('vvvvvvVVVvvvvvVV', 20, 20, 0, 8, 0, 0,
+        $crc, strlen($data), $claimed, strlen($name), 0, 0, 0, 0, 0, 0)
+    . $name;
+$end = "PK\x05\x06"
+    . pack('vvvvVVv', 0, 0, 1, 1, strlen($central), strlen($local), 0);
+
+file_put_contents(__DIR__ . '/gh25089.zip', $local . $central . $end);
+
+$phar = new PharData(__DIR__ . '/gh25089.zip');
+var_dump($phar->getAlias());
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/gh25089.zip');
+?>
+--EXPECT--
+string(4) "ABCD"
diff --git a/ext/phar/zip.c b/ext/phar/zip.c
index f051c35a09a..c1230cb7807 100644
--- a/ext/phar/zip.c
+++ b/ext/phar/zip.c
@@ -648,7 +648,6 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia
 			fp->readpos = 0;
 			/* the above lines should be for php < 5.2.6 after 5.3 filters are fixed */

-			mydata->alias_len = entry.uncompressed_filesize;
 			if (entry.flags & PHAR_ENT_COMPRESSED_GZ) {
 				filter = php_stream_filter_create("zlib.inflate", NULL, php_stream_is_persistent(fp));

@@ -735,6 +734,8 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia
 				}
 			}

+			mydata->alias_len = entry.uncompressed_filesize;
+
 			/* return to central directory parsing */
 			php_stream_seek(fp, restore_pos, SEEK_SET);
 		}