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

Ilia Alshanetsky <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-07-16T22:12:57-04:00

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

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  ext/standard: fix out-of-bounds access in the ftp:// directory stream

Changed paths:
  A  ext/standard/tests/streams/ftp_dirstream_oob.phpt
  M  ext/ftp/tests/server.inc
  M  ext/standard/ftp_fopen_wrapper.c
  M  ext/standard/tests/streams/opendir-002.phpt
  M  ext/standard/tests/streams/opendir-004.phpt


Diff:

diff --git a/ext/ftp/tests/server.inc b/ext/ftp/tests/server.inc
index 04e2ceefa278..65c1af1b7aab 100644
--- a/ext/ftp/tests/server.inc
+++ b/ext/ftp/tests/server.inc
@@ -290,7 +290,7 @@ if ($pid) {
             }
 
             if (empty($m[1]) || $m[1] !== 'emptydir') {
-                fputs($fs, "file1\r\nfile1\r\nfile\nb0rk\r\n");
+                fputs($fs, $nlst_data ?? "file1\r\nfile1\r\nfile\nb0rk\r\n");
             }
 
             fputs($s, "226 Closing data Connection.\r\n");
diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c
index 3330c5493dbf..c1f8fe7424b9 100644
--- a/ext/standard/ftp_fopen_wrapper.c
+++ b/ext/standard/ftp_fopen_wrapper.c
@@ -633,9 +633,9 @@ static ssize_t php_ftp_dirstream_read(php_stream *stream, char *buf, size_t coun
 
 	basename = php_basename(ent->d_name, tmp_len, NULL, 0);
 
-	tmp_len = MIN(sizeof(ent->d_name), ZSTR_LEN(basename) - 1);
+	tmp_len = MIN(sizeof(ent->d_name) - 1, ZSTR_LEN(basename));
 	memcpy(ent->d_name, ZSTR_VAL(basename), tmp_len);
-	ent->d_name[tmp_len - 1] = '\0';
+	ent->d_name[tmp_len] = '\0';
 	zend_string_release_ex(basename, 0);
 	ent->d_type = DT_UNKNOWN;
 
diff --git a/ext/standard/tests/streams/ftp_dirstream_oob.phpt b/ext/standard/tests/streams/ftp_dirstream_oob.phpt
new file mode 100644
index 000000000000..9e184f3c8ac6
--- /dev/null
+++ b/ext/standard/tests/streams/ftp_dirstream_oob.phpt
@@ -0,0 +1,33 @@
+--TEST--
+opendir() with 'ftp://' stream must not go out of bounds on an empty or slash-only listing line
+--SKIPIF--
+<?php
+if (array_search('ftp',stream_get_wrappers()) === FALSE) die("skip ftp wrapper not available.");
+if (!function_exists('pcntl_fork')) die("skip pcntl_fork() not available.");
+?>
+--FILE--
+<?php
+
+/* An empty line makes php_basename() return "\n" and a slash-only final line
+ * makes it return "", the two lengths the buffer math underflowed on. */
+$nlst_data = "file1\r\n\nb0rk\r\n/";
+
+require __DIR__ . "/../../../ftp/tests/server.inc";
+
+$path="ftp://localhost:" . $port."/";
+
+$ds=opendir($path);
+var_dump($ds);
+
+while (($fn=readdir($ds)) !== false) {
+      var_dump($fn);
+}
+
+closedir($ds);
+?>
+--EXPECTF--
+resource(%d) of type (stream)
+string(5) "file1"
+string(0) ""
+string(4) "b0rk"
+string(0) ""
diff --git a/ext/standard/tests/streams/opendir-002.phpt b/ext/standard/tests/streams/opendir-002.phpt
index 4978c8affa3d..0a5712564e2e 100644
--- a/ext/standard/tests/streams/opendir-002.phpt
+++ b/ext/standard/tests/streams/opendir-002.phpt
@@ -25,5 +25,5 @@ closedir($ds);
 resource(%d) of type (stream)
 string(5) "file1"
 string(5) "file1"
-string(3) "fil"
+string(4) "file"
 string(4) "b0rk"
diff --git a/ext/standard/tests/streams/opendir-004.phpt b/ext/standard/tests/streams/opendir-004.phpt
index 9ccb86b4f4b4..3f076e0d8386 100644
--- a/ext/standard/tests/streams/opendir-004.phpt
+++ b/ext/standard/tests/streams/opendir-004.phpt
@@ -27,5 +27,5 @@ while ($fn=readdir($ds)) {
 resource(%d) of type (stream)
 string(5) "file1"
 string(5) "file1"
-string(3) "fil"
+string(4) "file"
 string(4) "b0rk"
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.