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.
This commit is contained in:
Daniel Stenberg 2007-08-22 14:18:06 +00:00
parent c347db2e0a
commit 381e372939
5 changed files with 86 additions and 5 deletions

View File

@ -6,6 +6,13 @@
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

View File

@ -44,6 +44,7 @@ This release includes the following bugfixes:
o resume HTTP PUT using Digest authentication
o FTP NOBODY requests on directories sent "SIZE (null)"
o FTP NOBODY request on file crash
o excessively long FTP server response lines
This release includes the following known bugs:

View File

@ -287,9 +287,13 @@ static void ftp_respinit(struct connectdata *conn)
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,
@ -399,7 +403,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
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)! */
@ -432,6 +436,27 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
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 */
@ -645,7 +670,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
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)! */

View File

@ -43,4 +43,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test296 test297 test298 test610 test611 test612 test406 test407 test408 \
test409 test613 test614 test700 test701 test702 test704 test705 test703 \
test706 test707 test350 test351 test352 test353 test289 test540 test354 \
test231 test1000 test1001 test1002
test231 test1000 test1001 test1002 test1003

48
tests/data/test1003 Normal file

File diff suppressed because one or more lines are too long