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) {