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:
Родитель
d994fcf2b1
Коммит
7cba40b218
8
CHANGES
8
CHANGES
|
@ -6,6 +6,14 @@
|
|||
|
||||
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)
|
||||
- OS/400 port: new files lib/config-os400.h lib/setup-os400.h packages/OS400/*.
|
||||
See packages/OS400/README.OS400.
|
||||
|
|
|
@ -45,7 +45,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
|
||||
o excessively long FTP server responses and response lines
|
||||
o file:// upload then FTP:// upload crash
|
||||
|
||||
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;
|
||||
#endif
|
||||
res = Curl_read(conn, sockfd, ptr, BUFSIZE-ftpc->nread_resp,
|
||||
&gotbytes);
|
||||
&gotbytes);
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
conn->data_prot = prot;
|
||||
#endif
|
||||
|
@ -387,7 +387,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
|||
|
||||
/* output debug output if that is requested */
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
if(!conn->sec_complete)
|
||||
if(!conn->sec_complete)
|
||||
#endif
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
|
@ -424,6 +424,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
|||
ftpc->linestart_resp = ptr+1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!keepon && (i != gotbytes)) {
|
||||
/* 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
|
||||
|
@ -436,26 +437,45 @@ 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;
|
||||
else if(keepon) {
|
||||
int clipamount = 0;
|
||||
bool restart = FALSE;
|
||||
|
||||
if((perline == 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);
|
||||
restart = TRUE;
|
||||
if(STATUSCODE(ftpc->linestart_resp))
|
||||
/* we copy 4 bytes since after the three-digit number there is a
|
||||
dash or a space and it is significant */
|
||||
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 */
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
else {
|
||||
int res;
|
||||
int res;
|
||||
#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
|
||||
res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp,
|
||||
&gotbytes);
|
||||
res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp,
|
||||
&gotbytes);
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
conn->data_prot = prot;
|
||||
conn->data_prot = prot;
|
||||
#endif
|
||||
if(res < 0)
|
||||
/* EWOULDBLOCK */
|
||||
|
@ -654,7 +674,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
|||
|
||||
/* output debug output if that is requested */
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
if(!conn->sec_complete)
|
||||
if(!conn->sec_complete)
|
||||
#endif
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
|
@ -2538,7 +2558,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
|||
Curl_sec_request_prot(conn, "private");
|
||||
/* We set private first as default, in case the line below fails to
|
||||
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)
|
||||
infof(data, "Logging in with password in cleartext!\n");
|
||||
|
@ -2673,13 +2693,13 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
|||
|
||||
case FTP_CCC:
|
||||
if (ftpcode < 500) {
|
||||
/* First shut down the SSL layer (note: this call will block) */
|
||||
result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
|
||||
/* First shut down the SSL layer (note: this call will block) */
|
||||
result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
|
||||
|
||||
if(result) {
|
||||
failf(conn->data, "Failed to clear the command channel (CCC)");
|
||||
return result;
|
||||
}
|
||||
if(result) {
|
||||
failf(conn->data, "Failed to clear the command channel (CCC)");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then continue as normal */
|
||||
|
@ -3143,8 +3163,8 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, bool premature
|
|||
if(dlen && !ftpc->cwdfail) {
|
||||
ftpc->prevpath = path;
|
||||
if(flen)
|
||||
/* if 'path' is not the whole string */
|
||||
ftpc->prevpath[dlen]=0; /* terminate */
|
||||
/* if 'path' is not the whole string */
|
||||
ftpc->prevpath[dlen]=0; /* terminate */
|
||||
infof(data, "Remembering we are in dir %s\n", ftpc->prevpath);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -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 test1003 test1004 test1005
|
||||
test231 test1000 test1001 test1002 test1003 test1004 test1005 test1006
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Загрузка…
Ссылка в новой задаче