]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ftp: restore protocol state after http proxy CONNECT
authorTom Eccles <tom.eccles@codethink.co.uk>
Thu, 23 Jun 2022 09:09:25 +0000 (10:09 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 23 Jun 2022 14:07:20 +0000 (16:07 +0200)
connect_init() (lib/http_proxy.c) swaps out the protocol state while
working on the proxy connection, this is then restored by
Curl_connect_done() after the connection completes.

ftp_do_more() extracted the protocol state pointer to a local variable
at the start of the function then calls Curl_proxy_connect(). If the proxy
connection completes, Curl_proxy_connect() will call Curl_connect_done()
(via Curl_proxyCONNECT()), which restores data->req.p to point to the ftp
protocol state instead of the http proxy protocol state, but the local
variable in ftp_do_more still pointed to the old value.

Ultimately this meant that the state worked on by ftp_do_more() was the
http proxy state not the ftp state initialised by ftp_connect(), but
subsequent calls to any ftp_ function would use the original state.

For my use-case, the visible consequence was that ftp->downloadsize was
never set and so downloaded data was never returned to the application.

This commit updates the ftp protocol state pointer in ftp_do_more() after
Curl_proxy_connect() returns, ensuring that the correct state pointer is
used.

Fixes #8737
Closes #9043

lib/ftp.c

index ae2c90965d1672bb3dbc3d4826bba2840fb97777..e6e9821c9cad4268fc6094332b7a5c49fbe7c287 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -3565,8 +3565,10 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
   bool connected = FALSE;
   bool complete = FALSE;
 
-  /* the ftp struct is inited in ftp_connect() */
-  struct FTP *ftp = data->req.p.ftp;
+  /* the ftp struct is inited in ftp_connect(). If we are connecting to an HTTP
+   * proxy then the state will not be valid until after that connection is
+   * complete */
+  struct FTP *ftp = NULL;
 
   /* if the second connection isn't done yet, wait for it */
   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
@@ -3607,6 +3609,9 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
     return result;
 #endif
 
+  /* Curl_proxy_connect might have moved the protocol state */
+  ftp = data->req.p.ftp;
+
   if(ftpc->state) {
     /* already in a state so skip the initial commands.
        They are only done to kickstart the do_more state */