ftp: fix teardown of DATA connection in done

When ftp_done() is called to terminate the transfer, it needs to tear
down any open SECONDARY filter chain. The condition on when to do that
was relying on there to be a valid socket. This is not sufficient as the
socket is only set *after* happy eyeballing has decided on one.

Instead of checking for a valid conn->sock, check if any connection
filter is installed.

Fixes #17482
Reported-by: Rasmus Melchior Jacobsen
Closes #17491
This commit is contained in:
Stefan Eissing 2025-05-30 12:05:14 +02:00 committed by Daniel Stenberg
parent 4b76a821f8
commit 4977747f0d
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 12 additions and 3 deletions

View file

@ -497,6 +497,11 @@ out:
return result;
}
bool Curl_conn_is_setup(struct connectdata *conn, int sockindex)
{
return (conn->cfilter[sockindex] != NULL);
}
bool Curl_conn_is_connected(struct connectdata *conn, int sockindex)
{
struct Curl_cfilter *cf;

View file

@ -370,6 +370,11 @@ bool Curl_conn_cf_needs_flush(struct Curl_cfilter *cf,
CURLcode Curl_conn_connect(struct Curl_easy *data, int sockindex,
bool blocking, bool *done);
/**
* Check if a filter chain at `sockindex` for connection `conn` exists.
*/
bool Curl_conn_is_setup(struct connectdata *conn, int sockindex);
/**
* Check if the filter chain at `sockindex` for connection `conn` is
* completely connected.

View file

@ -1752,8 +1752,7 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data,
infof(data, "Failed EPSV attempt. Disabling EPSV");
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
Curl_conn_close(data, SECONDARYSOCKET);
Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
close_secondarysocket(data, ftpc);
data->state.errorbuf = FALSE; /* allow error message to get
rewritten */
result = Curl_pp_sendf(data, &ftpc->pp, "%s", "PASV");
@ -3322,7 +3321,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */
#endif
if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
if(Curl_conn_is_setup(conn, SECONDARYSOCKET)) {
if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
/* partial download completed */
result = Curl_pp_sendf(data, pp, "%s", "ABOR");