Commit 34a9a439043 for php.net

commit 34a9a4390435c6bb27094419cd68bbcda605a7cd
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sat Jun 20 20:58:24 2026 -0400

    ext/ftp: fix off-by-one terminator write in ftp_readline()

    The bug80901 fix (09696eee9d43) terminates an over-long response with
    *data = 0, but when the line fills the whole FTP_BUFSIZE inbuf without a
    CR/LF, data points at inbuf[FTP_BUFSIZE] and the terminator is written one
    byte past the buffer, into the adjacent ftpbuf_t::extra field. Reserve the
    final byte for the terminator so it always lands inside inbuf. A
    buffer-filling response loses its last character (bug80901's SYST reply is
    now 4095 visible chars, with the terminator taking the 4096th slot).

    Closes GH-22377

diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index ca5e05ead81..17a3e10e0d6 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -1359,7 +1359,7 @@ ftp_readline(ftpbuf_t *ftp)
 		}

 		data = eol;
-		if ((rcvd = my_recv(ftp, ftp->fd, data, size)) < 1) {
+		if (size < 2 || (rcvd = my_recv(ftp, ftp->fd, data, size - 1)) < 1) {
 			*data = 0;
 			return 0;
 		}
diff --git a/ext/ftp/tests/bug80901.phpt b/ext/ftp/tests/bug80901.phpt
index e2a58fa0668..a1c0e479c6a 100644
--- a/ext/ftp/tests/bug80901.phpt
+++ b/ext/ftp/tests/bug80901.phpt
@@ -16,4 +16,4 @@
 --EXPECTF--
 bool(true)

-Warning: ftp_systype(): **************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** in %s on line %d
+Warning: ftp_systype(): *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** in %s on line %d