mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
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.
This commit is contained in:
parent
d994fcf2b1
commit
7cba40b218
8
CHANGES
8
CHANGES
@ -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.
|
||||||
|
@ -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:
|
||||||
|
94
lib/ftp.c
94
lib/ftp.c
@ -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 {
|
||||||
|
@ -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
49
tests/data/test1006
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user