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

@ -41,6 +41,9 @@ CURLcode test(char *URL)
{
CURLcode res;
CURL *curl;
#ifdef LIB696
int transfers = 0;
#endif
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
@ -58,6 +61,10 @@ CURLcode test(char *URL)
test_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
#ifdef LIB696
again:
#endif
res = curl_easy_perform(curl);
if(!res) {
@ -87,8 +94,12 @@ CURLcode test(char *URL)
if(nread) {
/* send received stuff to stdout */
if(!write(STDOUT_FILENO, buf, nread))
if((size_t)write(STDOUT_FILENO, buf, nread) != nread) {
fprintf(stderr, "write() failed: errno %d (%s)\n",
errno, strerror(errno));
res = TEST_ERR_FAILURE;
break;
}
}
} while((res == CURLE_OK && nread) || (res == CURLE_AGAIN));
@ -98,12 +109,10 @@ CURLcode test(char *URL)
}
#ifdef LIB696
/* attempt to use the handle again */
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
test_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
++transfers;
/* perform the transfer a second time */
if(!res && transfers == 1)
goto again;
#endif
test_cleanup: