aboutsummaryrefslogtreecommitdiff
path: root/lib/ftp.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-08-22 14:18:06 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-08-22 14:18:06 +0000
commit381e372939d72bb572c545b18bf050fd4fbca5b5 (patch)
tree41da29f015fb11840096b839d32a873fefbfd53e /lib/ftp.c
parentc347db2e0ade83a9b2d3cc44f51bbb541b5ca6f4 (diff)
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.
Diffstat (limited to 'lib/ftp.c')
-rw-r--r--lib/ftp.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 3ea07c0a2..8ecdca62e 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -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)! */