Commit 765fe90b594 for php.net
commit 765fe90b594b2b9fcbf55957b81a6565480c2e25
Merge: 6493ea617aa 1feb20156bb
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date: Sun Jul 12 21:07:01 2026 -0400
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4:
Fix use-after-free on re-entrant ftp_close() during a transfer
diff --cc ext/ftp/ftp.c
index 5fcd41536ec,1345e378d8e..88f7431cc32
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@@ -817,8 -890,13 +817,13 @@@ bool ftp_get(ftpbuf_t *ftp, php_stream
char arg[MAX_LENGTH_OF_LONG];
if (ftp == NULL) {
- return 0;
+ return false;
}
+ if (ftp->in_use) {
+ php_error_docref(NULL, E_WARNING, "FTP\\Connection is already in use");
- return 0;
++ return false;
+ }
+ ftp->in_use = true;
if (!ftp_type(ftp, type)) {
goto bail;
}
@@@ -894,11 -972,14 +899,13 @@@
goto bail;
}
+ ftp->in_use = false;
- return 1;
+ return true;
bail:
data_close(ftp);
+ ftp->in_use = false;
- return 0;
+ return false;
}
-/* }}} */
static zend_result ftp_send_stream_to_data_socket(ftpbuf_t *ftp, databuf_t *data, php_stream *instream, ftptype_t type, bool send_once_and_return)
{
@@@ -979,8 -1062,13 +986,13 @@@ bool ftp_put(ftpbuf_t *ftp, const char
char arg[MAX_LENGTH_OF_LONG];
if (ftp == NULL) {
- return 0;
+ return false;
}
+ if (ftp->in_use) {
+ php_error_docref(NULL, E_WARNING, "FTP\\Connection is already in use");
- return 0;
++ return false;
+ }
+ ftp->in_use = true;
if (!ftp_type(ftp, type)) {
goto bail;
}
@@@ -1021,19 -1109,30 +1033,26 @@@
if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250 && ftp->resp != 200)) {
goto bail;
}
+ ftp->in_use = false;
- return 1;
+ return true;
bail:
data_close(ftp);
+ ftp->in_use = false;
- return 0;
+ return false;
}
-/* }}} */
-
-/* {{{ ftp_append */
-int
-ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type)
+bool ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type)
{
- databuf_t *data = NULL;
+ databuf_t *data = NULL;
if (ftp == NULL) {
- return 0;
+ return false;
}
+ if (ftp->in_use) {
+ php_error_docref(NULL, E_WARNING, "FTP\\Connection is already in use");
- return 0;
++ return false;
+ }
+ ftp->in_use = true;
if (!ftp_type(ftp, type)) {
goto bail;
}
@@@ -1061,13 -1160,18 +1080,15 @@@
if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250 && ftp->resp != 200)) {
goto bail;
}
+ ftp->in_use = false;
- return 1;
+ return true;
bail:
data_close(ftp);
+ ftp->in_use = false;
- return 0;
+ return false;
}
-/* }}} */
-/* {{{ ftp_size */
-zend_long
-ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len)
+zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len)
{
if (ftp == NULL) {
return -1;
@@@ -2179,9 -2366,18 +2222,14 @@@ bail
data_close(ftp);
return PHP_FTP_FAILED;
}
-/* }}} */
-
-/* {{{ ftp_nb_continue_write */
-int
-ftp_nb_continue_write(ftpbuf_t *ftp)
+int ftp_nb_continue_write(ftpbuf_t *ftp)
{
+ if (ftp->in_use) {
+ php_error_docref(NULL, E_WARNING, "FTP\\Connection is already in use");
+ return PHP_FTP_FAILED;
+ }
+
/* check if we can write more data */
if (!data_writeable(ftp, ftp->data->fd)) {
return PHP_FTP_MOREDATA;
@@@ -2205,5 -2405,7 +2257,6 @@@
bail:
data_close(ftp);
ftp->nb = 0;
+ ftp->in_use = false;
return PHP_FTP_FAILED;
}
-/* }}} */
diff --cc ext/ftp/php_ftp.c
index f19cc4b4b6b,432270cff19..c89c1f07f7c
--- a/ext/ftp/php_ftp.c
+++ b/ext/ftp/php_ftp.c
@@@ -800,12 -803,12 +809,12 @@@ PHP_FUNCTION(ftp_nb_get
}
/* configuration */
- ftp->direction = 0; /* recv */
- ftp->closestream = 1; /* do close */
+ ftp->direction = false; /* recv */
+ ftp->closestream = true; /* do close */
if ((ret = ftp_nb_get(ftp, outstream, remote, remote_len, xtype, resumepos)) == PHP_FTP_FAILED) {
- php_stream_close(outstream);
ftp->stream = NULL;
+ php_stream_close(outstream);
VCWD_UNLINK(local);
if (*ftp->inbuf) {
php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
@@@ -953,8 -946,13 +962,13 @@@ PHP_FUNCTION(ftp_nb_fput
}
/* configuration */
+ if (ftp->in_use) {
+ php_error_docref(NULL, E_WARNING, "FTP\\Connection is already in use");
+ RETURN_FALSE;
+ }
+
- ftp->direction = 1; /* send */
- ftp->closestream = 0; /* do not close */
+ ftp->direction = true; /* send */
+ ftp->closestream = false; /* do not close */
if (((ret = ftp_nb_put(ftp, remote, remote_len, stream, xtype, startpos)) == PHP_FTP_FAILED)) {
if (*ftp->inbuf) {
@@@ -1093,9 -1091,15 +1107,15 @@@ PHP_FUNCTION(ftp_nb_put
}
}
+ if (ftp->in_use) {
+ php_stream_close(instream);
+ php_error_docref(NULL, E_WARNING, "FTP\\Connection is already in use");
+ RETURN_FALSE;
+ }
+
/* configuration */
- ftp->direction = 1; /* send */
- ftp->closestream = 1; /* do close */
+ ftp->direction = true; /* send */
+ ftp->closestream = true; /* do close */
ret = ftp_nb_put(ftp, remote, remote_len, instream, xtype, startpos);