From 4977747f0da325f5ba4e7f346ce1db8eb6899885 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Fri, 30 May 2025 12:05:14 +0200 Subject: [PATCH] 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 --- lib/cfilters.c | 5 +++++ lib/cfilters.h | 5 +++++ lib/ftp.c | 5 ++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/cfilters.c b/lib/cfilters.c index a9de86a462..00090f0c71 100644 --- a/lib/cfilters.c +++ b/lib/cfilters.c @@ -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; diff --git a/lib/cfilters.h b/lib/cfilters.h index 646aabf37d..4c604db38f 100644 --- a/lib/cfilters.h +++ b/lib/cfilters.h @@ -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. diff --git a/lib/ftp.c b/lib/ftp.c index 0aa19262f7..2c6138e980 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -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");