cURL / Mailing Lists / curl-library / Single Mail

curl-library

Bugfix for issue 1330310 (SIGSEGV in Curl_removeHandleFromPipeline)

From: Lénaïc Lefever <lenaic.lefever_at_gmail.com>
Date: Thu, 16 Apr 2009 06:17:37 +0200

Hi,

Issue 1330310 somehow got unfixed and made libcurl (7.19.4) crash by
doing a double Curl_done on the same connection
(Curl_getoff_all_pipelines gets called from Curl_done with conn being
NULL).

Here's a detailed scenario that leads to the crash:

[TEXT] Re-using existing connection! (#0) with host qmstaging.com
[TEXT] Connected to ********** (***.***.***.***) port 21 (#0)
[TEXT] Request has same path as previous transfer
[HEADER OUT] EPSV
[TEXT] Connect data stream passively
[TEXT] disabling EPSV usage
[TEXT] Send failure: Broken pipe

A send failure occurs in Curl_do (url.c), the result is equal to
CURLE_SEND_ERROR

[TEXT] Re-used connection seems dead, get a new one

libcurl entered the following piece of code here:

     if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
       /* This was a re-use of a connection and we got a write error
in the
        * DO-phase. Then we DISCONNECT this connection and have
another attempt
        * to CONNECT and then DO again! The retry cannot possibly find
another
        * connection to re-use, since we only keep one possible
connection for
        * each. */

       infof(data, "Re-used connection seems dead, get a new one\n");
       conn->bits.close = TRUE; /* enforce close of this connection */
       result = Curl_done(&conn, result, FALSE); /* we are so done
with this */

       /* conn may no longer be a good pointer */

       /*
        * According to bug report #1330310. We need to check for
        * CURLE_SEND_ERROR here as well. I figure this could happen
when the
        * request failed on a FTP connection and thus Curl_done()
itself tried
        * to use the connection (again). Slight Lack of feedback in
the report,
        * but I don't think this extra check can do much harm.
        */
       if((CURLE_OK == result) || (CURLE_SEND_ERROR == result)) {

Normally a reconnection should follow here. The problem is that
Curl_done returns an error code different from CURLE_SEND_ERROR (in
this case while using the FTP connection).

This makes the condition check for the reconnection fail, since result
has changed (in my case, to CURLE_PARTIAL_FILE).

When Curl_do returns, the resulting error code (CURLE_PARTIAL_FILE)
leads to the second Curl_done, but at that time the connection was
already deallocated.

I've fixed the bug by keeping the original result in an extra CURLCode
variable and check if this variable is equal to CURLE_SEND_ERROR. I'm
sure there is a cleaner way to fix this problem than my fast hack.

I love libcurl, it's a great lib!

Regards,
Lenaic
Received on 2009-04-16