1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-20240: FTP with SSL: ftp_fput(): Connection timed out on successful writes

Looking at the strace, the timeout is only 1s which may be too low
anyway for checking for a response, but some servers also don't end up
replying finally anyway and close the connection already.

`data_available` was originally used for non-blocking downloads/uploads
and then reused for the shutdown sequence, but its error handling was
never adjusted to be silent.

Closes GH-20294.
This commit is contained in:
Niels Dossche
2025-10-25 22:06:42 +02:00
parent 61b0d589d6
commit 8761c4e507
2 changed files with 12 additions and 3 deletions

4
NEWS
View File

@@ -21,6 +21,10 @@ PHP NEWS
. Fixed bug GH-19974 (fpm_status_export_to_zval segfault for parallel
execution). (Jakub Zelenka, txuna)
- FTP:
. Fixed bug GH-20240 (FTP with SSL: ftp_fput(): Connection timed out on
successful writes). (nielsdos)
- GD:
. Fixed bug GH-20070 (Return type violation in imagefilter when an invalid
filter is provided). (Girgias)

View File

@@ -1605,7 +1605,7 @@ my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
/* {{{ data_available */
int
data_available(ftpbuf_t *ftp, php_socket_t s)
data_available(ftpbuf_t *ftp, php_socket_t s, bool silent)
{
int n;
@@ -1613,6 +1613,9 @@ data_available(ftpbuf_t *ftp, php_socket_t s)
if (n < 1) {
char buf[256];
if (n == 0) {
if (silent) {
return 0;
}
#ifdef PHP_WIN32
_set_errno(ETIMEDOUT);
#else
@@ -1938,7 +1941,9 @@ static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle) {
done = 0;
}
while (!done && data_available(ftp, fd)) {
/* Don't report timeouts on the control channel if we're negotiating a shutdown already.
* Some servers don't put a final response. */
while (!done && data_available(ftp, fd, true)) {
ERR_clear_error();
nread = SSL_read(ssl_handle, buf, sizeof(buf));
if (nread <= 0) {
@@ -2198,7 +2203,7 @@ ftp_nb_continue_read(ftpbuf_t *ftp)
data = ftp->data;
/* check if there is already more data */
if (!data_available(ftp, data->fd)) {
if (!data_available(ftp, data->fd, false)) {
return PHP_FTP_MOREDATA;
}