ftp: restore protocol state after http proxy CONNECT

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
This commit is contained in:
Tom Eccles 2022-06-23 10:09:25 +01:00 committed by Daniel Stenberg
parent f3a7781594
commit 71bbabb167
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -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 */