Commit cafbcde1620 for php.net

commit cafbcde1620550be24034c24f50539230366bf37
Author: Georgij Tsarin <nullderef@duck.com>
Date:   Mon Sep 7 16:13:40 2026 +0300

    ftp: use SSL_write_ex() in single_send() to fix signed/unsigned handling (#22967)

    * ftp: use SSL_write_ex() in single_send()

    Replace SSL_write() with SSL_write_ex() and pass its return value
    to SSL_get_error(). This preserves the original API contract and
    avoids signed/unsigned conversion issues when handling errors.

    Signed-off-by: Denis Sergeev <zeff@altlinux.org>

    * ftp: widen single_send() return type to ssize_t

    * ftp: initialize sent before SSL_write_ex()

    ---------

    Signed-off-by: Denis Sergeev <zeff@altlinux.org>
    Co-authored-by: Denis Sergeev <zeff@altlinux.org>

diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index 20a67950627..eaa1768156e 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -1349,13 +1349,14 @@ static ssize_t my_recv_wrapper_with_restart(php_socket_t fd, void *buf, size_t s
 	return n;
 }

-static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) {
+static ssize_t single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) {
 #ifdef HAVE_FTP_SSL
 	int err;
 	bool retry = false;
 	SSL *handle = NULL;
 	php_socket_t fd;
 	size_t sent;
+	int ret;

 	if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
 		handle = ftp->ssl_handle;
@@ -1368,8 +1369,9 @@ static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) {
 	}

 	do {
-		sent = SSL_write(handle, buf, size);
-		err = SSL_get_error(handle, sent);
+		sent = 0;
+		ret = SSL_write_ex(handle, buf, size, &sent);
+		err = SSL_get_error(handle, ret);

 		switch (err) {
 			case SSL_ERROR_NONE: