callers. Don't allocate more than 64k bytes on headers; don't allocate
more than 4k bytes on a single line.
+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.
2005-03-12 Hrvoje Niksic <hniksic@xemacs.org>
* wget.h: Include options.h after wgint has been defined.
/* Get greeting. */
err = ftp_response (csock, &respline);
if (err != FTPOK)
/* Get greeting. */
err = ftp_response (csock, &respline);
if (err != FTPOK)
- {
- xfree (respline);
- return err;
- }
if (*respline != '2')
{
xfree (respline);
if (*respline != '2')
{
xfree (respline);
+/* 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.
/* 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)
{
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);
a read. If the read returns a different amount of data, the
process is retried until all data arrives safely.
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 *
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 */
char *hunk = xmalloc (bufsize);
int tail = 0; /* tail position in HUNK */
+ assert (maxsize >= bufsize);
+
while (1)
{
const char *end;
while (1)
{
const char *end;
xfree (hunk);
return NULL;
}
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 (end)
{
/* The data contains the terminator: we'll drain the data up
if (tail == bufsize - 1)
{
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;
+ }
+ if (maxsize && bufsize > maxsize)
+ bufsize = maxsize;
hunk = xrealloc (hunk, bufsize);
}
}
hunk = xrealloc (hunk, bufsize);
}
}
+/* 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
/* Read one line from FD and return it. The line is allocated using
+ 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
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)
{
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
}
\f
/* Return a printed representation of the download rate, as
typedef const char *(*hunk_terminator_t) PARAMS ((const char *, int, int));
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 **,
char *fd_read_line PARAMS ((int));
uerr_t retrieve_url PARAMS ((const char *, char **, char **,