+2005-03-17 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * ftp-basic.c (ftp_login): Don't free the string if ftp_response
+ returned an error status because the line didn't get allocated in
+ the first place.
+
+2005-03-15 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * http.c (read_http_response_head): Limit the response size to 64k
+ bytes.
+
+ * retr.c (fd_read_hunk): Accept a MAXSIZE argument that limits the
+ number of bytes the function is allowed to allocate.
+ (fd_read_line): Limit the line to 4096 bytes.
+
2005-03-12 Hrvoje Niksic <hniksic@xemacs.org>
* wget.h: Include options.h after wgint has been defined.
return NULL;
}
+/* The maximum size of a single HTTP response we care to read. This
+ is not meant to impose an arbitrary limit, but to protect the user
+ from Wget slurping up available memory upon encountering malicious
+ or buggy server output. Define it to 0 to remove the limit. */
+
+#define HTTP_RESPONSE_MAX_SIZE 65536
+
/* Read the HTTP request head from FD and return it. The error
conditions are the same as with fd_read_hunk.
static char *
read_http_response_head (int fd)
{
- return fd_read_hunk (fd, response_head_terminator, 512);
+ return fd_read_hunk (fd, response_head_terminator, 512,
+ HTTP_RESPONSE_MAX_SIZE);
}
struct response {
a read. If the read returns a different amount of data, the
process is retried until all data arrives safely.
- BUFSIZE is the size of the initial buffer expected to read all the
- data in the typical case.
+ SIZEHINT is the buffer size sufficient to hold all the data in the
+ typical case (it is used as the initial buffer size). MAXSIZE is
+ the maximum amount of memory this function is allowed to allocate,
+ or 0 if no upper limit is to be enforced.
This function should be used as a building block for other
functions -- see fd_read_line as a simple example. */
char *
-fd_read_hunk (int fd, hunk_terminator_t hunk_terminator, int bufsize)
+fd_read_hunk (int fd, hunk_terminator_t terminator, long sizehint, long maxsize)
{
+ long bufsize = sizehint;
char *hunk = xmalloc (bufsize);
int tail = 0; /* tail position in HUNK */
+ assert (maxsize >= bufsize);
+
while (1)
{
const char *end;
xfree (hunk);
return NULL;
}
- end = hunk_terminator (hunk, tail, pklen);
+ end = terminator (hunk, tail, pklen);
if (end)
{
/* The data contains the terminator: we'll drain the data up
if (tail == bufsize - 1)
{
+ /* Double the buffer size, but refuse to allocate more than
+ MAXSIZE bytes. */
+ if (maxsize && bufsize >= maxsize)
+ {
+ xfree (hunk);
+ errno = ENOMEM;
+ return NULL;
+ }
bufsize <<= 1;
+ if (maxsize && bufsize > maxsize)
+ bufsize = maxsize;
hunk = xrealloc (hunk, bufsize);
}
}
return NULL;
}
+/* The maximum size of the single line we agree to accept. This is
+ not meant to impose an arbitrary limit, but to protect the user
+ from Wget slurping up available memory upon encountering malicious
+ or buggy server output. Define it to 0 to remove the limit. */
+#define FD_READ_LINE_MAX 4096
+
/* Read one line from FD and return it. The line is allocated using
- malloc.
+ malloc, but is never larger than FD_READ_LINE_MAX.
If an error occurs, or if no data can be read, NULL is returned.
In the former case errno indicates the error condition, and in the
char *
fd_read_line (int fd)
{
- return fd_read_hunk (fd, line_terminator, 128);
+ return fd_read_hunk (fd, line_terminator, 128, FD_READ_LINE_MAX);
}
\f
/* Return a printed representation of the download rate, as
typedef const char *(*hunk_terminator_t) PARAMS ((const char *, int, int));
-char *fd_read_hunk PARAMS ((int, hunk_terminator_t, int));
+char *fd_read_hunk PARAMS ((int, hunk_terminator_t, long, long));
char *fd_read_line PARAMS ((int));
uerr_t retrieve_url PARAMS ((const char *, char **, char **,