1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00
out that libcurl didn't deal with large responses from server commands, when
the single response was consisting of multiple lines but of a total size of
16KB or more. Dan Fandrich improved the ftp test script and provided test
case 1006 to repeat the problem, and I fixed the code to make sure this new
test case runs fine.
This commit is contained in:
Daniel Stenberg 2007-08-24 14:00:42 +00:00
parent d994fcf2b1
commit 7cba40b218
5 changed files with 116 additions and 39 deletions

View File

@ -6,6 +6,14 @@
Changelog Changelog
Daniel S (24 August 2007)
- Bug report #1779054 (http://curl.haxx.se/bug/view.cgi?id=1779054) pointed
out that libcurl didn't deal with large responses from server commands, when
the single response was consisting of multiple lines but of a total size of
16KB or more. Dan Fandrich improved the ftp test script and provided test
case 1006 to repeat the problem, and I fixed the code to make sure this new
test case runs fine.
Patrick M (23 August 2007) Patrick M (23 August 2007)
- OS/400 port: new files lib/config-os400.h lib/setup-os400.h packages/OS400/*. - OS/400 port: new files lib/config-os400.h lib/setup-os400.h packages/OS400/*.
See packages/OS400/README.OS400. See packages/OS400/README.OS400.

View File

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

View File

@ -343,7 +343,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
conn->data_prot = 0; conn->data_prot = 0;
#endif #endif
res = Curl_read(conn, sockfd, ptr, BUFSIZE-ftpc->nread_resp, res = Curl_read(conn, sockfd, ptr, BUFSIZE-ftpc->nread_resp,
&gotbytes); &gotbytes);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = prot; conn->data_prot = prot;
#endif #endif
@ -387,7 +387,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
/* output debug output if that is requested */ /* output debug output if that is requested */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
if(!conn->sec_complete) if(!conn->sec_complete)
#endif #endif
if(data->set.verbose) if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN, Curl_debug(data, CURLINFO_HEADER_IN,
@ -424,6 +424,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
ftpc->linestart_resp = ptr+1; ftpc->linestart_resp = ptr+1;
} }
} }
if(!keepon && (i != gotbytes)) { if(!keepon && (i != gotbytes)) {
/* We found the end of the response lines, but we didn't parse the /* We found the end of the response lines, but we didn't parse the
full chunk of data we have read from the server. We therefore need full chunk of data we have read from the server. We therefore need
@ -436,26 +437,45 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
else else
return CURLE_OUT_OF_MEMORY; /**BANG**/ return CURLE_OUT_OF_MEMORY; /**BANG**/
} }
else if(keepon && (i == gotbytes) && (gotbytes > BUFSIZE/2)) { else if(keepon) {
/* We got an excessive line without newlines and we need to deal int clipamount = 0;
with it. First, check if it seems to start with a valid status bool restart = FALSE;
code and then we keep just that in the line cache. Then throw
away the rest. */ if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
infof(data, "Excessive FTP response line length received, %zd bytes." /* We got an excessive line without newlines and we need to deal
" Stripping\n", gotbytes); with it. First, check if it seems to start with a valid status
if(STATUSCODE(ftpc->linestart_resp)) { code and then we keep just that in the line cache. Then throw
ftpc->cache_size = 4; /* we copy 4 bytes since after the three-digit away the rest. */
number there is a dash or a space and it infof(data, "Excessive FTP response line length received, %zd bytes."
is significant */ " Stripping\n", gotbytes);
ftpc->cache = (char *)malloc((int)ftpc->cache_size); restart = TRUE;
if(ftpc->cache) if(STATUSCODE(ftpc->linestart_resp))
memcpy(ftpc->cache, ftpc->linestart_resp, (int)ftpc->cache_size); /* we copy 4 bytes since after the three-digit number there is a
else dash or a space and it is significant */
return CURLE_OUT_OF_MEMORY; clipamount = 4;
}
else if(perline && (ftpc->nread_resp > BUFSIZE/2)) {
/* We got a large chunk of data and there's still trailing data to
take care of, so we put that part in the "cache" and restart */
clipamount = perline;
restart = TRUE;
}
if(restart) {
if(clipamount) {
ftpc->cache_size = clipamount;
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 reset a few variables to start over nicely from the start of
the big buffer */
ftpc->nread_resp = 0; /* start over from scratch in the buffer */
ptr = ftpc->linestart_resp = buf;
perline = 0;
} }
/* 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 */ } /* there was data */
@ -603,16 +623,16 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
ftpc->cache_size = 0; /* zero the size just in case */ ftpc->cache_size = 0; /* zero the size just in case */
} }
else { else {
int res; int res;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
enum protection_level prot = conn->data_prot; enum protection_level prot = conn->data_prot;
conn->data_prot = 0; conn->data_prot = 0;
#endif #endif
res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp, res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp,
&gotbytes); &gotbytes);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = prot; conn->data_prot = prot;
#endif #endif
if(res < 0) if(res < 0)
/* EWOULDBLOCK */ /* EWOULDBLOCK */
@ -654,7 +674,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
/* output debug output if that is requested */ /* output debug output if that is requested */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
if(!conn->sec_complete) if(!conn->sec_complete)
#endif #endif
if(data->set.verbose) if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN, Curl_debug(data, CURLINFO_HEADER_IN,
@ -2538,7 +2558,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
Curl_sec_request_prot(conn, "private"); Curl_sec_request_prot(conn, "private");
/* We set private first as default, in case the line below fails to /* We set private first as default, in case the line below fails to
set a valid level */ set a valid level */
Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
if(Curl_sec_login(conn) != 0) if(Curl_sec_login(conn) != 0)
infof(data, "Logging in with password in cleartext!\n"); infof(data, "Logging in with password in cleartext!\n");
@ -2673,13 +2693,13 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_CCC: case FTP_CCC:
if (ftpcode < 500) { if (ftpcode < 500) {
/* First shut down the SSL layer (note: this call will block) */ /* First shut down the SSL layer (note: this call will block) */
result = Curl_ssl_shutdown(conn, FIRSTSOCKET); result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
if(result) { if(result) {
failf(conn->data, "Failed to clear the command channel (CCC)"); failf(conn->data, "Failed to clear the command channel (CCC)");
return result; return result;
} }
} }
/* Then continue as normal */ /* Then continue as normal */
@ -3143,8 +3163,8 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, bool premature
if(dlen && !ftpc->cwdfail) { if(dlen && !ftpc->cwdfail) {
ftpc->prevpath = path; ftpc->prevpath = path;
if(flen) if(flen)
/* if 'path' is not the whole string */ /* if 'path' is not the whole string */
ftpc->prevpath[dlen]=0; /* terminate */ ftpc->prevpath[dlen]=0; /* terminate */
infof(data, "Remembering we are in dir %s\n", ftpc->prevpath); infof(data, "Remembering we are in dir %s\n", ftpc->prevpath);
} }
else { else {

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 \ test296 test297 test298 test610 test611 test612 test406 test407 test408 \
test409 test613 test614 test700 test701 test702 test704 test705 test703 \ test409 test613 test614 test700 test701 test702 test704 test705 test703 \
test706 test707 test350 test351 test352 test353 test289 test540 test354 \ test706 test707 test350 test351 test352 test353 test289 test540 test354 \
test231 test1000 test1001 test1002 test1003 test1004 test1005 test231 test1000 test1001 test1002 test1003 test1004 test1005 test1006

49
tests/data/test1006 Normal file

File diff suppressed because one or more lines are too long