summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2005-02-15 22:34:22 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2005-02-15 22:34:22 +0000
commitf93e387801979a10b37382cabe05ee6a6600c984 (patch)
tree197a4b88b65adae4ce9810fffeac74484bfe8861
parenta91cd779021852dbe8160b63150773023d0d7c33 (diff)
downloadnetsurf-f93e387801979a10b37382cabe05ee6a6600c984.tar.gz
netsurf-f93e387801979a10b37382cabe05ee6a6600c984.tar.bz2
[project @ 2005-02-15 22:34:22 by jmb]
Fix loads of object/embed/applet/iframe memory leaks. Disable handling of applet tag as the implementation's broken and we don't have a sensible JVM anyway. svn path=/import/netsurf/; revision=1514
-rw-r--r--render/box.c406
1 files changed, 241 insertions, 165 deletions
diff --git a/render/box.c b/render/box.c
index 8b043ce50..f93c3c99b 100644
--- a/render/box.c
+++ b/render/box.c
@@ -156,6 +156,7 @@ static bool calculate_table_row(struct columns *col_info,
unsigned int *start_column);
static bool box_normalise_inline_container(struct box *cont, pool box_pool);
static void box_free_box(struct box *box);
+static void box_free_object_params(struct object_params *op);
static struct box_result box_object(xmlNode *n, struct box_status *status,
struct css_style *style);
static struct box_result box_embed(xmlNode *n, struct box_status *status,
@@ -164,8 +165,7 @@ static struct box_result box_applet(xmlNode *n, struct box_status *status,
struct css_style *style);
static struct box_result box_iframe(xmlNode *n, struct box_status *status,
struct css_style *style);
-static bool plugin_decode(struct content* content, char* url, struct box* box,
- struct object_params* po);
+static bool plugin_decode(struct content* content, struct box* box);
static struct box_multi_length *box_parse_multi_lengths(const char *s,
unsigned int *count);
static bool box_contains_point(struct box *box, int x, int y);
@@ -181,7 +181,7 @@ struct element_entry {
};
static const struct element_entry element_table[] = {
{"a", box_a},
- {"applet", box_applet},
+/* {"applet", box_applet},*/
{"body", box_body},
{"br", box_br},
{"button", box_button},
@@ -2470,9 +2470,39 @@ void box_free_box(struct box *box)
free(box->usemap);
free(box->text);
free(box->id);
- /* TODO: free object_params */
+ box_free_object_params(box->object_params);
}
+/**
+ * Free an object parameter struct
+ *
+ * \param op The struct to free
+ */
+void box_free_object_params(struct object_params *op)
+{
+ struct plugin_params *a, *b;
+
+ if (!op)
+ return;
+
+ free(op->data);
+ free(op->type);
+ free(op->codetype);
+ free(op->codebase);
+ free(op->classid);
+ free(op->basehref);
+
+ for (a = op->params; a; a = b) {
+ b = a->next;
+ free(a->name);
+ free(a->value);
+ free(a->type);
+ free(a->valuetype);
+ free(a);
+ }
+
+ free(op);
+}
/**
* add an object to the box tree
@@ -2482,43 +2512,28 @@ struct box_result box_object(xmlNode *n, struct box_status *status,
{
struct box *box;
struct object_params *po;
- struct plugin_params* pp;
- char *s, *url = NULL, *map;
+ struct plugin_params *pp = NULL;
+ char *s, *map;
xmlNode *c;
- url_func_result res;
- po = malloc(sizeof *po);
+ po = calloc(1, sizeof(struct object_params));
if (!po)
return (struct box_result) {0, false, true};
box = box_create(style, status->href, 0, status->id,
status->content->data.html.box_pool);
- if (!box)
+ if (!box) {
+ free(po);
return (struct box_result) {0, false, true};
-
- /* initialise po struct */
- po->data = 0;
- po->type = 0;
- po->codetype = 0;
- po->codebase = 0;
- po->classid = 0;
- po->params = 0;
+ }
/* object data */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "data")) != NULL) {
- res = url_join(s, status->content->data.html.base_url, &url);
- /* if url is equivalent to the parent's url,
- * we've got infinite inclusion. stop it here.
- * also bail if url_join failed.
- */
- if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) {
- free(po);
- xmlFree(s);
- return (struct box_result) {0, true, true};
- }
po->data = strdup(s);
- LOG(("object '%s'", po->data));
xmlFree(s);
+ if (!po->data)
+ goto no_memory;
+ LOG(("object '%s'", po->data));
}
/* imagemap associated with this object */
@@ -2526,35 +2541,43 @@ struct box_result box_object(xmlNode *n, struct box_status *status,
box->usemap = (map[0] == '#') ? strdup(map+1) : strdup(map);
xmlFree(map);
if (!box->usemap)
- return (struct box_result) {0, false, true};
+ goto no_memory;
}
/* object type */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "type")) != NULL) {
po->type = strdup(s);
- LOG(("type: %s", s));
xmlFree(s);
+ if (!po->type)
+ goto no_memory;
+ LOG(("type: %s", po->type));
}
/* object codetype */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "codetype")) != NULL) {
po->codetype = strdup(s);
- LOG(("codetype: %s", s));
xmlFree(s);
+ if (!po->codetype)
+ goto no_memory;
+ LOG(("codetype: %s", po->codetype));
}
/* object codebase */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "codebase")) != NULL) {
po->codebase = strdup(s);
- LOG(("codebase: %s", s));
xmlFree(s);
+ if (!po->codebase)
+ goto no_memory;
+ LOG(("codebase: %s", po->codebase));
}
/* object classid */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "classid")) != NULL) {
po->classid = strdup(s);
- LOG(("classid: %s", s));
xmlFree(s);
+ if (!po->classid)
+ goto no_memory;
+ LOG(("classid: %s", po->classid));
}
/* parameters
@@ -2563,35 +2586,41 @@ struct box_result box_object(xmlNode *n, struct box_status *status,
* new parameters are added to the head of the list.
*/
for (c = n->children; c != NULL; c = c->next) {
+ if (c->type != XML_ELEMENT_NODE)
+ continue;
+
if (strcmp((const char *) c->name, "param") == 0) {
- pp = malloc(sizeof *pp);
+ pp = calloc(1, sizeof(struct plugin_params));
if (!pp)
- return (struct box_result) {0, false, true};
-
- /* initialise pp struct */
- pp->name = 0;
- pp->value = 0;
- pp->valuetype = 0;
- pp->type = 0;
- pp->next = 0;
+ goto no_memory;
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "name")) != NULL) {
pp->name = strdup(s);
xmlFree(s);
+ if (!pp->name)
+ goto no_memory;
}
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "value")) != NULL) {
pp->value = strdup(s);
xmlFree(s);
+ if (!pp->value)
+ goto no_memory;
}
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "type")) != NULL) {
pp->type = strdup(s);
xmlFree(s);
+ if (!pp->type)
+ goto no_memory;
}
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "valuetype")) != NULL) {
pp->valuetype = strdup(s);
xmlFree(s);
+ if (!pp->valuetype)
+ goto no_memory;
} else {
pp->valuetype = strdup("data");
+ if (!pp->valuetype)
+ goto no_memory;
}
pp->next = po->params;
@@ -2601,87 +2630,82 @@ struct box_result box_object(xmlNode *n, struct box_status *status,
* of the alt html. Therefore, we should
* break out of this loop.
*/
- /** \todo: following statement is *not* breaking the loop ?! Is comment or code wrong here ? */
- continue;
+ break;
}
}
box->object_params = po;
/* start fetch */
- if (plugin_decode(status->content, url, box, po))
+ if (plugin_decode(status->content, box))
return (struct box_result) {box, false, false};
return (struct box_result) {box, true, false};
+
+no_memory:
+ if (pp && pp != po->params) {
+ /* ran out of memory creating parameter struct */
+ free(pp->name);
+ free(pp->value);
+ free(pp->type);
+ free(pp->valuetype);
+ free(pp);
+ }
+
+ box_free_object_params(po);
+ box_free_box(box);
+
+ return (struct box_result) {0, false, true};
}
/**
* add an embed to the box tree
*/
-
struct box_result box_embed(xmlNode *n, struct box_status *status,
struct css_style *style)
{
struct box *box;
struct object_params *po;
- struct plugin_params *pp;
- char *s, *url = NULL;
+ struct plugin_params *pp = NULL;
+ char *s;
xmlAttr *a;
- url_func_result res;
- po = malloc(sizeof *po);
+ po = calloc(1, sizeof(struct object_params));
if (!po)
return (struct box_result) {0, false, true};
box = box_create(style, status->href, 0, status->id,
status->content->data.html.box_pool);
- if (!box)
+ if (!box) {
+ free(po);
return (struct box_result) {0, false, true};
-
- /* initialise po struct */
- po->data = 0;
- po->type = 0;
- po->codetype = 0;
- po->codebase = 0;
- po->classid = 0;
- po->params = 0;
+ }
/* embed src */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src")) != NULL) {
- res = url_join(s, status->content->data.html.base_url, &url);
- /* if url is equivalent to the parent's url,
- * we've got infinite inclusion. stop it here.
- * also bail if url_join failed.
- */
- if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) {
- free(po);
- xmlFree(s);
- return (struct box_result) {0, false, true};
- }
- LOG(("embed '%s'", url));
+ LOG(("embed '%s'", s));
po->data = strdup(s);
xmlFree(s);
+ if (!po->data)
+ goto no_memory;
}
/**
* we munge all other attributes into a plugin_parameter structure
*/
for (a=n->properties; a != NULL; a=a->next) {
- pp = malloc(sizeof *pp);
+ pp = calloc(1, sizeof(struct plugin_params));
if (!pp)
- return (struct box_result) {0, false, true};
-
- /* initialise pp struct */
- pp->name = 0;
- pp->value = 0;
- pp->valuetype = 0;
- pp->type = 0;
- pp->next = 0;
+ goto no_memory;
- if (strcasecmp((const char*)a->name, "src") != 0) {
+ if (strcasecmp((const char*)a->name, "src") != 0 &&
+ a->children && a->children->content) {
pp->name = strdup((const char*)a->name);
pp->value = strdup((char*)a->children->content);
pp->valuetype = strdup("data");
+ if (!pp->name || !pp->value || !pp->valuetype)
+ goto no_memory;
+
pp->next = po->params;
po->params = pp;
}
@@ -2690,57 +2714,69 @@ struct box_result box_embed(xmlNode *n, struct box_status *status,
box->object_params = po;
/* start fetch */
- plugin_decode(status->content, url, box, po);
+ /* embeds have no content, so we don't care if this returns false */
+ plugin_decode(status->content, box);
return (struct box_result) {box, false, false};
+
+no_memory:
+ if (pp && pp != po->params) {
+ /* ran out of memory creating parameter struct */
+ free(pp->name);
+ free(pp->value);
+ free(pp->type);
+ free(pp->valuetype);
+ free(pp);
+ }
+
+ box_free_object_params(po);
+ box_free_box(box);
+
+ return (struct box_result) {0, false, true};
}
/**
* add an applet to the box tree
+ *
+ * \todo This needs reworking to be compliant to the spec
+ * For now, we simply ignore all applet tags.
*/
-
struct box_result box_applet(xmlNode *n, struct box_status *status,
struct css_style *style)
{
struct box *box;
struct object_params *po;
- struct plugin_params *pp;
- char *s, *url = NULL;
+ struct plugin_params *pp = NULL;
+ char *s;
xmlNode *c;
- url_func_result res;
- po = malloc(sizeof *po);
+ po = calloc(1, sizeof(struct object_params));
if (!po)
return (struct box_result) {0, false, true};
box = box_create(style, status->href, 0, status->id,
status->content->data.html.box_pool);
- if (!box)
+ if (!box) {
+ free(po);
return (struct box_result) {0, false, true};
+ }
- /* initialise po struct */
- po->data = 0;
- po->type = 0;
- po->codetype = 0;
- po->codebase = 0;
- po->classid = 0;
- po->params = 0;
-
+ /* archive */
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "archive")) != NULL ) {
+ /** \todo tokenise this comma separated list */
+ LOG(("archive '%s'", s));
+ po->data = strdup(s);
+ xmlFree(s);
+ if (!po->data)
+ goto no_memory;
+ }
/* code */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "code")) != NULL) {
- res = url_join(s, status->content->data.html.base_url, &url);
- /* if url is equivalent to the parent's url,
- * we've got infinite inclusion. stop it here.
- * also bail if url_join failed.
- */
- if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) {
- free(po);
- xmlFree(s);
- return (struct box_result) {box, true, false};
- }
- LOG(("applet '%s'", url));
+ LOG(("applet '%s'", s));
po->classid = strdup(s);
xmlFree(s);
+ if (!po->classid)
+ goto no_memory;
}
/* object codebase */
@@ -2748,6 +2784,8 @@ struct box_result box_applet(xmlNode *n, struct box_status *status,
po->codebase = strdup(s);
LOG(("codebase: %s", s));
xmlFree(s);
+ if (!po->codebase)
+ goto no_memory;
}
/* parameters
@@ -2756,35 +2794,41 @@ struct box_result box_applet(xmlNode *n, struct box_status *status,
* new parameters are added to the head of the list.
*/
for (c = n->children; c != 0; c = c->next) {
+ if (c->type != XML_ELEMENT_NODE)
+ continue;
+
if (strcmp((const char *) c->name, "param") == 0) {
- pp = malloc(sizeof *pp);
+ pp = calloc(1, sizeof(struct plugin_params));
if (!pp)
- return (struct box_result) {0, false, true};
-
- /* initialise pp struct */
- pp->name = 0;
- pp->value = 0;
- pp->valuetype = 0;
- pp->type = 0;
- pp->next = 0;
+ goto no_memory;
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "name")) != NULL) {
pp->name = strdup(s);
xmlFree(s);
+ if (!pp->name)
+ goto no_memory;
}
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "value")) != NULL) {
pp->value = strdup(s);
xmlFree(s);
+ if (!pp->value)
+ goto no_memory;
}
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "type")) != NULL) {
pp->type = strdup(s);
xmlFree(s);
+ if (!pp->type)
+ goto no_memory;
}
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "valuetype")) != NULL) {
pp->valuetype = strdup(s);
xmlFree(s);
+ if (!pp->valuetype)
+ goto no_memory;
} else {
pp->valuetype = strdup("data");
+ if (!pp->valuetype)
+ goto no_memory;
}
pp->next = po->params;
@@ -2794,18 +2838,32 @@ struct box_result box_applet(xmlNode *n, struct box_status *status,
* of the alt html. Therefore, we should
* break out of this loop.
*/
- /** \todo: following statement is *not* breaking the loop ?! Is comment or code wrong here ? */
- continue;
+ break;
}
}
box->object_params = po;
/* start fetch */
- if (plugin_decode(status->content, url, box, po))
+ if (plugin_decode(status->content, box))
return (struct box_result) {box, false, false};
return (struct box_result) {box, true, false};
+
+no_memory:
+ if (pp && pp != po->params) {
+ /* ran out of memory creating parameter struct */
+ free(pp->name);
+ free(pp->value);
+ free(pp->type);
+ free(pp->valuetype);
+ free(pp);
+ }
+
+ box_free_object_params(po);
+ box_free_box(box);
+
+ return (struct box_result) {0, false, true};
}
/**
@@ -2818,49 +2876,40 @@ struct box_result box_iframe(xmlNode *n, struct box_status *status,
{
struct box *box;
struct object_params *po;
- char *s, *url = NULL;
- url_func_result res;
+ char *s;
- po = malloc(sizeof *po);
+ po = calloc(1, sizeof(struct object_params));
if (!po)
return (struct box_result) {0, false, true};
box = box_create(style, status->href, 0, status->id,
status->content->data.html.box_pool);
- if (!box)
+ if (!box) {
+ free(po);
return (struct box_result) {0, false, true};
-
- /* initialise po struct */
- po->data = 0;
- po->type = 0;
- po->codetype = 0;
- po->codebase = 0;
- po->classid = 0;
- po->params = 0;
+ }
/* iframe src */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src")) != NULL) {
- res = url_join(s, status->content->data.html.base_url, &url);
- /* if url is equivalent to the parent's url,
- * we've got infinite inclusion. stop it here.
- * also bail if url_join failed.
- */
- if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) {
- free(po);
- xmlFree(s);
- return (struct box_result) {0, false, true};
- }
- LOG(("embed '%s'", url));
+ LOG(("iframe '%s'", s));
po->data = strdup(s);
xmlFree(s);
+ if (!po->data)
+ goto no_memory;
}
box->object_params = po;
/* start fetch */
- plugin_decode(status->content, url, box, po);
+ plugin_decode(status->content, box);
return (struct box_result) {box, false, false};
+
+no_memory:
+ box_free_object_params(po);
+ box_free_box(box);
+
+ return (struct box_result) {0, false, true};
}
/**
@@ -2871,45 +2920,52 @@ struct box_result box_iframe(xmlNode *n, struct box_status *status,
* necessary as there are multiple ways of declaring an object's attributes.
*
* Returns false if the object could not be handled.
- *
- * TODO: plug failure leaks
*/
-bool plugin_decode(struct content* content, char* url, struct box* box,
- struct object_params* po)
+bool plugin_decode(struct content *content, struct box *box)
{
- struct plugin_params * pp;
+ char *codebase, *url = NULL;
+ struct object_params *po;
+ struct plugin_params *pp;
url_func_result res;
+ assert(content && box);
+
+ po = box->object_params;
+
/* Check if the codebase attribute is defined.
* If it is not, set it to the codebase of the current document.
*/
if (po->codebase == 0)
- res = url_join("./", content->data.html.base_url, &po->codebase);
+ res = url_join("./", content->data.html.base_url,
+ &codebase);
else
- res = url_join(po->codebase, content->data.html.base_url, &po->codebase);
+ res = url_join(po->codebase, content->data.html.base_url,
+ &codebase);
if (res != URL_FUNC_OK)
return false;
+ /* free pre-existing codebase */
+ if (po->codebase)
+ free(po->codebase);
+
+ po->codebase = codebase;
+
/* Set basehref */
po->basehref = strdup(content->data.html.base_url);
- /* Check that we have some data specified.
- * First, check the data attribute.
- * Second, check the classid attribute.
- * The data attribute takes precedence.
- * If neither are specified or if classid begins "clsid:",
- * we can't handle this object.
- */
if (po->data == 0 && po->classid == 0)
+ /* no data => ignore this object */
return false;
if (po->data == 0 && po->classid != 0) {
+ /* just classid specified */
if (strncasecmp(po->classid, "clsid:", 6) == 0) {
- /* Flash */
if (strcasecmp(po->classid, "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000") == 0) {
+ /* Flash */
for (pp = po->params;
- pp != 0 && strcasecmp(pp->name, "movie") != 0;
+ pp != 0 &&
+ strcasecmp(pp->name, "movie") != 0;
pp = pp->next)
/* no body */;
if (pp == 0)
@@ -2920,12 +2976,17 @@ bool plugin_decode(struct content* content, char* url, struct box* box,
/* munge the codebase */
res = url_join("./",
content->data.html.base_url,
- &po->codebase);
- if (res != URL_FUNC_OK)
+ &codebase);
+ if (res != URL_FUNC_OK) {
+ free(url);
return false;
+ }
+ if (po->codebase)
+ free(po->codebase);
+ po->codebase = codebase;
}
else {
- LOG(("ActiveX object - n0"));
+ LOG(("ActiveX object"));
return false;
}
} else {
@@ -2933,14 +2994,18 @@ bool plugin_decode(struct content* content, char* url, struct box* box,
if (res != URL_FUNC_OK)
return false;
+#if 0
+ /* jmb - I'm not convinced by this */
/* The java plugin doesn't need the .class extension
* so we strip it.
*/
if (strcasecmp(&po->classid[strlen(po->classid)-6],
".class") == 0)
po->classid[strlen(po->classid)-6] = 0;
+#endif
}
} else {
+ /* just data (or both) specified - data takes precedence */
res = url_join(po->data, po->codebase, &url);
if (res != URL_FUNC_OK)
return false;
@@ -2950,9 +3015,14 @@ bool plugin_decode(struct content* content, char* url, struct box* box,
* Checks type and codetype attributes.
*/
if (po->type != 0 && content_lookup(po->type) == CONTENT_OTHER)
- return false;
- if (po->codetype != 0 && content_lookup(po->codetype) == CONTENT_OTHER)
- return false;
+ goto no_handler;
+ if (po->codetype != 0 &&
+ content_lookup(po->codetype) == CONTENT_OTHER)
+ goto no_handler;
+
+ /* Ensure that the object to be included isn't this document */
+ if (strcasecmp(url, content->data.html.base_url) == 0)
+ goto no_handler;
/* If we've got to here, the object declaration has provided us with
* enough data to enable us to have a go at downloading and
@@ -2963,9 +3033,15 @@ bool plugin_decode(struct content* content, char* url, struct box* box,
* different to that given in the attributes).
*/
if (!html_fetch_object(content, url, box, 0, 1000, 1000, false))
- return false;
+ goto no_handler;
+
+ /* do _not_ free url here - html_fetch_object doesn't copy it */
return true;
+
+no_handler:
+ free(url);
+ return false;
}