mirror of
https://github.com/rkd77/elinks.git
synced 2025-04-18 00:47:36 -04: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:
parent
4086418069
commit
a2404407ce
1
NEWS
1
NEWS
@ -10,6 +10,7 @@ ELinks 0.11.5.GIT now:
|
|||||||
|
|
||||||
To be released as 0.11.6.
|
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
|
* critical bug 1053: fix crash if a download finishes after ELinks has
|
||||||
closed the terminal from which the download was started
|
closed the terminal from which the download was started
|
||||||
* major bug 1004: ignore locales when comparing HTML element names and
|
* major bug 1004: ignore locales when comparing HTML element names and
|
||||||
|
@ -511,6 +511,9 @@ look_for_tag(unsigned char **pos, unsigned char *eof,
|
|||||||
return 0;
|
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
|
static int
|
||||||
look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
|
look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
|
||||||
struct memory_list **ml, struct uri *href_base,
|
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)++;
|
(*pos)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*pos >= eof) return 0;
|
if (*pos >= eof) return -1;
|
||||||
|
|
||||||
if (*pos + 2 <= eof && ((*pos)[1] == '!' || (*pos)[1] == '?')) {
|
if (*pos + 2 <= eof && ((*pos)[1] == '!' || (*pos)[1] == '?')) {
|
||||||
*pos = skip_comment(*pos, eof);
|
*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)) {
|
if (!c_strlcasecmp(name, namelen, "A", 1)) {
|
||||||
while (look_for_tag(pos, eof, name, namelen, &label));
|
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)) {
|
} else if (!c_strlcasecmp(name, namelen, "AREA", 4)) {
|
||||||
unsigned char *alt = get_attr_val(attr, "alt", options);
|
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 conv_table *ct;
|
||||||
struct string hd;
|
struct string hd;
|
||||||
|
int look_result;
|
||||||
|
|
||||||
if (!init_string(&hd)) return -1;
|
if (!init_string(&hd)) return -1;
|
||||||
|
|
||||||
@ -676,10 +680,13 @@ get_image_map(unsigned char *head, unsigned char *pos, unsigned char *eof,
|
|||||||
|
|
||||||
*ml = NULL;
|
*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);
|
freeml(*ml);
|
||||||
mem_free(*menu);
|
mem_free(*menu);
|
||||||
return -1;
|
return -1;
|
||||||
|
5
test/imgmap2.html
Normal file
5
test/imgmap2.html
Normal 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>
|
Loading…
x
Reference in New Issue
Block a user