1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

Fix double-free crash if EOF immediately follows </MAP>.

look_for_link() used to return 0 both when it found the closing </MAP>
tag, and when it hit the end of the file.  In the first case, it also
added *menu to the memory_list; in the second case, it did not.  The
caller get_image_map() supposedly distinguished between these cases by
checking whether pos >= eof, and freed *menu separately if so.

However, if the </MAP> was at the very end of the HTML file, so that
not even a newline followed it, then look_for_link() left pos == eof
even though it had found the </MAP> and added *menu to the memory_list.
This made get_image_map() misinterpret the result and mem_free(*menu)
even though *menu had already been freed as part of the memory_list;
thus the crash.

To fix this, make look_for_link() return -1 instead of 0 if it hits
EOF without finding the </MAP>.  Then make get_image_map() check the
return value instead of comparing pos to eof.  And add a test case,
although not an automated one.

Alternatively, look_for_link() could have been changed to decrement
pos between finding the </MAP> and returning 0.  Then, the pos >= eof
comparison in get_image_map() would have been false.  That scheme
would however have been a bit more difficult to understand and
maintain, I think.

Reported by Paul B. Mahol.
This commit is contained in:
Kalle Olavi Niemitalo 2008-12-31 20:06:49 +00:00 committed by Kalle Olavi Niemitalo
parent 4086418069
commit a2404407ce
3 changed files with 18 additions and 5 deletions

1
NEWS
View File

@ -10,6 +10,7 @@ ELinks 0.11.5.GIT now:
To be released as 0.11.6.
* critical: fix double-free crash if EOF immediately follows </MAP>
* critical bug 1053: fix crash if a download finishes after ELinks has
closed the terminal from which the download was started
* major bug 1004: ignore locales when comparing HTML element names and

View File

@ -511,6 +511,9 @@ look_for_tag(unsigned char **pos, unsigned char *eof,
return 0;
}
/** @return -1 if EOF is hit without the closing tag; 0 if the closing
* tag is found (in which case this also adds *@a menu to *@a ml); or
* 1 if this should be called again. */
static int
look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
struct memory_list **ml, struct uri *href_base,
@ -528,7 +531,7 @@ look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
(*pos)++;
}
if (*pos >= eof) return 0;
if (*pos >= eof) return -1;
if (*pos + 2 <= eof && ((*pos)[1] == '!' || (*pos)[1] == '?')) {
*pos = skip_comment(*pos, eof);
@ -543,7 +546,7 @@ look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
if (!c_strlcasecmp(name, namelen, "A", 1)) {
while (look_for_tag(pos, eof, name, namelen, &label));
if (*pos >= eof) return 0;
if (*pos >= eof) return -1;
} else if (!c_strlcasecmp(name, namelen, "AREA", 4)) {
unsigned char *alt = get_attr_val(attr, "alt", options);
@ -656,6 +659,7 @@ get_image_map(unsigned char *head, unsigned char *pos, unsigned char *eof,
{
struct conv_table *ct;
struct string hd;
int look_result;
if (!init_string(&hd)) return -1;
@ -676,10 +680,13 @@ get_image_map(unsigned char *head, unsigned char *pos, unsigned char *eof,
*ml = NULL;
while (look_for_link(&pos, eof, menu, ml, uri, target_base, ct, options))
;
do {
/* This call can modify both *ml and *menu. */
look_result = look_for_link(&pos, eof, menu, ml, uri,
target_base, ct, options);
} while (look_result > 0);
if (pos >= eof) {
if (look_result < 0) {
freeml(*ml);
mem_free(*menu);
return -1;

5
test/imgmap2.html Normal file
View File

@ -0,0 +1,5 @@
<TITLE>Double-free crash in USEMAP</TITLE>
<P><IMG src="/dev/null" usemap="#crasher"></P>
<MAP name="crasher">
<AREA shape="rect" coords="42,42,69,69" href="http://elinks.cz/" alt="see this?">
<!-- no newline at the end of this line --></MAP>