diff options
author | Daniel Stenberg <daniel@haxx.se> | 2007-08-22 14:18:06 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2007-08-22 14:18:06 +0000 |
commit | 381e372939d72bb572c545b18bf050fd4fbca5b5 (patch) | |
tree | 41da29f015fb11840096b839d32a873fefbfd53e /lib | |
parent | c347db2e0ade83a9b2d3cc44f51bbb541b5ca6f4 (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')
-rw-r--r-- | lib/ftp.c | 33 |
1 files changed, 29 insertions, 4 deletions
@@ -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)! */ |