mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Limit the maximum amount of memory allocated by fd_read_hunk and its
callers. Don't allocate more than 64k bytes on headers; don't allocate more than 4k bytes on a single line.
This commit is contained in:
parent
b90b20763b
commit
72ce32e8ab
@ -1,3 +1,18 @@
|
||||
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.
|
||||
|
@ -123,10 +123,7 @@ ftp_login (int csock, const char *acc, const char *pass)
|
||||
/* Get greeting. */
|
||||
err = ftp_response (csock, &respline);
|
||||
if (err != FTPOK)
|
||||
{
|
||||
xfree (respline);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
if (*respline != '2')
|
||||
{
|
||||
xfree (respline);
|
||||
|
10
src/http.c
10
src/http.c
@ -432,6 +432,13 @@ response_head_terminator (const char *hunk, int oldlen, int peeklen)
|
||||
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.
|
||||
|
||||
@ -443,7 +450,8 @@ response_head_terminator (const char *hunk, int oldlen, int peeklen)
|
||||
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 {
|
||||
|
33
src/retr.c
33
src/retr.c
@ -375,18 +375,23 @@ fd_read_body (int fd, FILE *out, wgint toread, wgint startpos,
|
||||
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;
|
||||
@ -400,7 +405,7 @@ fd_read_hunk (int fd, hunk_terminator_t hunk_terminator, int bufsize)
|
||||
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
|
||||
@ -458,7 +463,17 @@ fd_read_hunk (int fd, hunk_terminator_t hunk_terminator, int bufsize)
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -474,8 +489,14 @@ line_terminator (const char *hunk, int oldlen, int peeklen)
|
||||
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
|
||||
@ -484,7 +505,7 @@ line_terminator (const char *hunk, int oldlen, int peeklen)
|
||||
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);
|
||||
}
|
||||
|
||||
/* Return a printed representation of the download rate, as
|
||||
|
@ -41,7 +41,7 @@ int fd_read_body PARAMS ((int, FILE *, wgint, wgint, wgint *, wgint *, double *,
|
||||
|
||||
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 **,
|
||||
|
Loading…
Reference in New Issue
Block a user