Package: curl
Version: 7.19.7-1
Tags: patch

If a server returns a Content-Length header and then it uses chunked transfer,
curl often fails with with the following error:

  curl: (18) transfer closed with outstanding read data remaining

I think the cause is that when it finds a Content-Length header while parsing
the response, it makes k->maxdownload = contentlength; (transfer.c:1216).
Although it sets k->size = -1; (transfer.c:1014), k->maxdownload is still the
contentlength:

          /* According to RFC2616 section 4.4, we MUST ignore
             Content-Length: headers if we are now receiving data
             using chunked Transfer-Encoding.
          */
          if(k->chunk)
            k->size=-1;

Later, when the reading from the server (readwrite_data), the following can
happen: if the server wants to send the final "0\r\n\r\n" chunk in a separate
packet, libcurl will hit the condition in transfer.c:635:

    if((-1 != k->maxdownload) &&
       (k->bytecount + nread >= k->maxdownload)) { ... }

where it sets

    k->keepon &= ~KEEP_RECV; /* we're done reading */

and considers reading finished.  So it will never read the final chunk, hence
the error.

On the other hand, if the server sends the final chunk in a previous packet
with other data, Curl_httpchunk_read() will happily loop through all of it and
correctly register the final state (CHUNK_STOP).

Setting k->maxdownload to -1 when the transfer encoding is chunked seems to
solve the problem (for me at least):

--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1010,8 +1010,10 @@ static CURLcode readwrite_http_headers(struct
SessionHandle *data,
              Content-Length: headers if we are now receiving data
              using chunked Transfer-Encoding.
           */
-          if(k->chunk)
+          if(k->chunk) {
             k->size=-1;
+           k->maxdownload=-1;
+         }

         }
         if(-1 != k->size) {


The curl upstream diverged somewhat already from the version used in Debian,
but the problem persists there also (I checked today's cvs snapshot).
diff --git a/lib/transfer.c b/lib/transfer.c
index 1f69706..b1595b5 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1010,8 +1010,10 @@ static CURLcode readwrite_http_headers(struct SessionHandle *data,
              Content-Length: headers if we are now receiving data
              using chunked Transfer-Encoding.
           */
-          if(k->chunk)
+          if(k->chunk) {
             k->size=-1;
+	    k->maxdownload=-1;
+	  }
 
         }
         if(-1 != k->size) {

Reply via email to