From 34a9a4390435c6bb27094419cd68bbcda605a7cd Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 20 Jun 2026 20:58:24 -0400 Subject: [PATCH 1/3] 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 --- ext/ftp/ftp.c | 2 +- ext/ftp/tests/bug80901.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index ca5e05ead81b..17a3e10e0d61 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 e2a58fa0668a..a1c0e479c6ae 100644 --- a/ext/ftp/tests/bug80901.phpt +++ b/ext/ftp/tests/bug80901.phpt @@ -16,4 +16,4 @@ ftp_systype($ftp); --EXPECTF-- bool(true) -Warning: ftp_systype(): **************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** in %s on line %d +Warning: ftp_systype(): *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** in %s on line %d From cb64c16917426a305d1d76a0dc36886b1201d536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 21 Jun 2026 23:51:32 +0200 Subject: [PATCH 2/3] zend_ast: Remove duplicated code when exporting arrays (#22392) Following php/php-src#22350. --- Zend/zend_ast.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 57faedc06f9b..cb27d9b7459c 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1940,11 +1940,10 @@ static ZEND_COLD void zend_ast_export_zval(smart_str *str, const zval *zv, int p } if (key) { zend_ast_export_quoted_str(str, key); - smart_str_appends(str, " => "); } else { smart_str_append_long(str, idx); - smart_str_appends(str, " => "); } + smart_str_appends(str, " => "); zend_ast_export_zval(str, val, 0, indent); } ZEND_HASH_FOREACH_END(); smart_str_appendc(str, ']'); From a7a3a5f1d2530191554ea249f5bdf1277501eb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 22 Jun 2026 00:30:58 +0200 Subject: [PATCH 3/3] zend_ast: Clean up `zend_ast_export_quoted_str()` (#22393) * zend_ast: Make `s` a `const zend_string*` in `zend_ast_export_quoted_str()` Following php/php-src#22350. * zend_ast: Reduce variable scope in `zend_ast_export_*str()` --- Zend/zend_ast.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index cb27d9b7459c..d3ce419c737e 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1578,9 +1578,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio static ZEND_COLD void zend_ast_export_str(smart_str *str, const zend_string *s) { - size_t i; - - for (i = 0; i < ZSTR_LEN(s); i++) { + for (size_t i = 0; i < ZSTR_LEN(s); i++) { unsigned char c = ZSTR_VAL(s)[i]; if (c == '\'' || c == '\\') { smart_str_appendc(str, '\\'); @@ -1593,9 +1591,7 @@ static ZEND_COLD void zend_ast_export_str(smart_str *str, const zend_string *s) static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, const zend_string *s) { - size_t i; - - for (i = 0; i < ZSTR_LEN(s); i++) { + for (size_t i = 0; i < ZSTR_LEN(s); i++) { unsigned char c = ZSTR_VAL(s)[i]; if (c < ' ') { switch (c) { @@ -1636,12 +1632,11 @@ static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, const zen } } -static ZEND_COLD void zend_ast_export_quoted_str(smart_str *str, zend_string *s) +static ZEND_COLD void zend_ast_export_quoted_str(smart_str *str, const zend_string *s) { - size_t i; - - for (i = 0; i < ZSTR_LEN(s); i++) { - if ((unsigned char) ZSTR_VAL(s)[i] < ' ') { + for (size_t i = 0; i < ZSTR_LEN(s); i++) { + unsigned char c = ZSTR_VAL(s)[i]; + if (c < ' ') { smart_str_appendc(str, '"'); zend_ast_export_qstr(str, '"', s); smart_str_appendc(str, '"');