easy: allow connect-only handle reuse with easy_perform

- Detach and disconnect an attached connection before performing.

Prior to this change it was not possible to safely reuse an easy handle
with an attached connection in a second call to curl_easy_perform. The
only known case of this is a connect-only type handle where the
connection was detached when curl_easy_perform returned, only to be
reattached by either curl_easy_send/recv.

This commit effectively reverts 2f8ecd5d and be82a360, the latter of
which treated the reuse as an error. Prior to that change undefined
behavior may occur in such a case.

Bug: https://curl.se/mail/lib-2025-01/0044.html
Reported-by: Aleksander Mazur

Closes https://github.com/curl/curl/pull/16008
This commit is contained in:
Jay Satiro 2025-01-15 03:56:11 -05:00
parent f25a807a7d
commit 4f99efb192
4 changed files with 55 additions and 23 deletions

View file

@ -751,11 +751,6 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
if(data->conn) {
failf(data, "cannot use again while associated with a connection");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
if(data->set.errorbuffer)
/* clear this as early as possible */
data->set.errorbuffer[0] = 0;
@ -767,6 +762,19 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
return CURLE_FAILED_INIT;
}
/* if the handle has a connection still attached (it is/was a connect-only
handle) then disconnect before performing */
if(data->conn) {
struct connectdata *c;
curl_socket_t s;
Curl_detach_connection(data);
s = Curl_getconnectinfo(data, &c);
if((s != CURL_SOCKET_BAD) && c) {
Curl_cpool_disconnect(data, c, TRUE);
}
DEBUGASSERT(!data->conn);
}
if(data->multi_easy)
multi = data->multi_easy;
else {