From: Stefan Eissing Date: Wed, 23 Apr 2025 09:24:45 +0000 (+0200) Subject: multi: init_do(): check result X-Git-Tag: curl-8_14_0~229 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e95556fc2b02a0ad38619aa94420d1dbeebfdd5;p=thirdparty%2Fcurl.git multi: init_do(): check result Calls to `Curl_init_do()` did not check on result and missed failures to properly and completely initialize a transfer request. The main cause of such an init failure is the need to rewind the READFUNCTION without a SEEKFUNCTION registered. Check the failure to "rewind" the upload data immediately make test cases 1576 and friends fail. Reported-by: Travis Lane Fixes #17139 Closes #17150 --- diff --git a/lib/multi.c b/lib/multi.c index d2615d3b4c..ddeab7e867 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -1560,10 +1560,15 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, rc = curl_multi_add_handle(multi, data); if(!rc) { struct SingleRequest *k = &data->req; + CURLcode result; /* pass in NULL for 'conn' here since we do not want to init the connection, only this transfer */ - Curl_init_do(data, NULL); + result = Curl_init_do(data, NULL); + if(result) { + curl_multi_remove_handle(multi, data); + return CURLM_INTERNAL_ERROR; + } /* take this handle to the perform state right away */ multistate(data, MSTATE_PERFORMING); diff --git a/lib/url.c b/lib/url.c index 9d17ce9779..e47ae60957 100644 --- a/lib/url.c +++ b/lib/url.c @@ -3533,28 +3533,26 @@ static CURLcode create_conn(struct Curl_easy *data, /* conn_protocol can only provide "old" protocols */ data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK; result = conn->handler->connect_it(data, &done); + if(result) + goto out; /* Setup a "faked" transfer that will do nothing */ + Curl_attach_connection(data, conn); + result = Curl_cpool_add(data, conn); if(!result) { - Curl_attach_connection(data, conn); - result = Curl_cpool_add(data, conn); + /* Setup whatever necessary for a resumed transfer */ + result = setup_range(data); if(!result) { - /* Setup whatever necessary for a resumed transfer */ - result = setup_range(data); - } - - if(result) { - DEBUGASSERT(conn->handler->done); - /* we ignore the return code for the protocol-specific DONE */ - (void)conn->handler->done(data, result, FALSE); - goto out; + Curl_xfer_setup_nop(data); + result = Curl_init_do(data, conn); } - Curl_xfer_setup_nop(data); } - /* since we skip do_init() */ - Curl_init_do(data, conn); - + if(result) { + DEBUGASSERT(conn->handler->done); + /* we ignore the return code for the protocol-specific DONE */ + (void)conn->handler->done(data, result, FALSE); + } goto out; } #endif @@ -3704,7 +3702,9 @@ static CURLcode create_conn(struct Curl_easy *data, } /* Setup and init stuff before DO starts, in preparing for the transfer. */ - Curl_init_do(data, conn); + result = Curl_init_do(data, conn); + if(result) + goto out; /* * Setup whatever necessary for a resumed transfer diff --git a/tests/libtest/lib1576.c b/tests/libtest/lib1576.c index 46952e3eea..a25798824d 100644 --- a/tests/libtest/lib1576.c +++ b/tests/libtest/lib1576.c @@ -38,6 +38,15 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) return strlen(testdata); } +static int seek_callback(void *ptr, curl_off_t offset, int origin) +{ + (void)ptr; + (void)offset; + if(origin != SEEK_SET) + return CURL_SEEKFUNC_FAIL; + return CURL_SEEKFUNC_OK; +} + CURLcode test(char *URL) { CURLcode res; @@ -62,6 +71,7 @@ CURLcode test(char *URL) test_setopt(curl, CURLOPT_URL, URL); test_setopt(curl, CURLOPT_UPLOAD, 1L); test_setopt(curl, CURLOPT_READFUNCTION, read_callback); + test_setopt(curl, CURLOPT_SEEKFUNCTION, seek_callback); test_setopt(curl, CURLOPT_INFILESIZE, (long)strlen(testdata)); test_setopt(curl, CURLOPT_CUSTOMREQUEST, "CURL"); diff --git a/tests/mk-bundle.pl b/tests/mk-bundle.pl index 5ed28a0807..6ca51392c7 100755 --- a/tests/mk-bundle.pl +++ b/tests/mk-bundle.pl @@ -78,6 +78,7 @@ my @reused_symbols = ( "removeFd", "rlim2str", "run_thread", + "seek_callback", "send_ping", "showem", "store_errmsg",