Changelog
+Daniel S (22 August 2007)
+- Bug report #1779054 (http://curl.haxx.se/bug/view.cgi?id=1779054) pointed
+ out that libcurl didn't deal with very long (>16K) FTP server response lines
+ properly. Starting now, libcurl will chop them off (thus the client app will
+ not get the full line) but survive and deal with them fine otherwise. Test
+ case 1003 was added to verify this.
+
Daniel S (20 August 2007)
- Based on a patch by Christian Vogt, the FTP code now sets the upcoming
download transfer size much earlier to be possible to get read with
ftpc->linestart_resp = conn->data->state.buffer;
}
+/* macro to check for a three-digit ftp status code at the start of the
+ given string */
+#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \
+ ISDIGIT(line[2]))
+
/* macro to check for the last line in an FTP server response */
-#define lastline(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \
- ISDIGIT(line[2]) && (' ' == line[3]))
+#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
static CURLcode ftp_readresp(curl_socket_t sockfd,
struct connectdata *conn,
if(result)
return result;
- if(perline>3 && lastline(ftpc->linestart_resp)) {
+ if(perline>3 && LASTLINE(ftpc->linestart_resp)) {
/* This is the end of the last line, copy the last line to the
start of the buffer and zero terminate, for old times sake (and
krb4)! */
else
return CURLE_OUT_OF_MEMORY; /**BANG**/
}
+ else if(keepon && (i == gotbytes) && (gotbytes > BUFSIZE/2)) {
+ /* We got an excessive line without newlines and we need to deal
+ with it. First, check if it seems to start with a valid status
+ code and then we keep just that in the line cache. Then throw
+ away the rest. */
+ infof(data, "Excessive FTP response line length received, %zd bytes."
+ " Stripping\n", gotbytes);
+ if(STATUSCODE(ftpc->linestart_resp)) {
+ ftpc->cache_size = 4; /* we copy 4 bytes since after the three-digit
+ number there is a dash or a space and it
+ is significant */
+ ftpc->cache = (char *)malloc((int)ftpc->cache_size);
+ if(ftpc->cache)
+ memcpy(ftpc->cache, ftpc->linestart_resp, (int)ftpc->cache_size);
+ else
+ return CURLE_OUT_OF_MEMORY;
+ }
+ /* now we forget what we read and get a new chunk in the next loop
+ and append to the small piece we might have put in the cache */
+ ftpc->nread_resp = 0;
+ }
} /* there was data */
} /* while there's buffer left and loop is requested */
if(result)
return result;
- if(perline>3 && lastline(line_start)) {
+ if(perline>3 && LASTLINE(line_start)) {
/* This is the end of the last line, copy the last
* line to the start of the buffer and zero terminate,
* for old times sake (and krb4)! */