Audit memory error handling in xpath.c
Memory allocation errors in the following functions a often ignored.
Add TODO comments.
- xmlXPathNodeSetCreate
- xmlXPathNodeSetAdd*
- xmlXPathNodeSetMerge*
- xmlXPathNodeSetDupNs
Note that the following functions currently lack a way to propagate
memory errors:
- xmlXPathCompareNodeSets
- xmlXPathEqualNodeSets
diff --git a/xpath.c b/xpath.c
index ced5697..9f64ab9 100644
--- a/xpath.c
+++ b/xpath.c
@@ -2426,6 +2426,7 @@
if ((ret->nodesetval->nodeMax == 0) ||
(val->type == XML_NAMESPACE_DECL))
{
+ /* TODO: Check memory error. */
xmlXPathNodeSetAddUnique(ret->nodesetval, val);
} else {
ret->nodesetval->nodeTab[0] = val;
@@ -3584,6 +3585,7 @@
if (val->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns = (xmlNsPtr) val;
+ /* TODO: Check memory error. */
ret->nodeTab[ret->nodeNr++] =
xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
} else
@@ -3690,6 +3692,7 @@
cur->nodeMax *= 2;
cur->nodeTab = temp;
}
+ /* TODO: Check memory error. */
cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
return(0);
}
@@ -3748,6 +3751,7 @@
if (val->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns = (xmlNsPtr) val;
+ /* TODO: Check memory error. */
cur->nodeTab[cur->nodeNr++] =
xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
} else
@@ -3802,6 +3806,7 @@
if (val->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns = (xmlNsPtr) val;
+ /* TODO: Check memory error. */
cur->nodeTab[cur->nodeNr++] =
xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
} else
@@ -3918,6 +3923,7 @@
if (n2->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns = (xmlNsPtr) n2;
+ /* TODO: Check memory error. */
val1->nodeTab[val1->nodeNr++] =
xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
} else
@@ -4298,6 +4304,7 @@
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
ret->type = XPATH_NODESET;
ret->boolval = 0;
+ /* TODO: Check memory error. */
ret->nodesetval = xmlXPathNodeSetCreate(val);
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
#ifdef XP_DEBUG_OBJ_USAGE
@@ -4358,6 +4365,7 @@
ret = xmlXPathNewNodeSet(val->nodeTab[0]);
if (ret) {
for (i = 1; i < val->nodeNr; ++i) {
+ /* TODO: Propagate memory error. */
if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i])
< 0) break;
}
@@ -4429,6 +4437,7 @@
if (xmlXPathNodeSetIsEmpty(nodes2))
return(nodes1);
+ /* TODO: Check memory error. */
ret = xmlXPathNodeSetCreate(NULL);
if (xmlXPathNodeSetIsEmpty(nodes1))
return(ret);
@@ -4438,6 +4447,7 @@
for (i = 0; i < l1; i++) {
cur = xmlXPathNodeSetItem(nodes1, i);
if (!xmlXPathNodeSetContains(nodes2, cur)) {
+ /* TODO: Propagate memory error. */
if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
break;
}
@@ -4474,6 +4484,7 @@
for (i = 0; i < l1; i++) {
cur = xmlXPathNodeSetItem(nodes1, i);
if (xmlXPathNodeSetContains(nodes2, cur)) {
+ /* TODO: Propagate memory error. */
if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
break;
}
@@ -4512,6 +4523,7 @@
strval = xmlXPathCastNodeToString(cur);
if (xmlHashLookup(hash, strval) == NULL) {
xmlHashAddEntry(hash, strval, strval);
+ /* TODO: Propagate memory error. */
if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
break;
} else {
@@ -4605,6 +4617,7 @@
cur = xmlXPathNodeSetItem(nodes, i);
if (cur == node)
break;
+ /* TODO: Propagate memory error. */
if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
break;
}
@@ -4710,6 +4723,7 @@
cur = xmlXPathNodeSetItem(nodes, i);
if (cur == node)
break;
+ /* TODO: Propagate memory error. */
if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
break;
}
@@ -5409,6 +5423,7 @@
break;
#endif
case XPATH_NODESET:
+ /* TODO: Check memory error. */
ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
/* Do not deallocate the copied tree value */
ret->boolval = 0;
@@ -6598,6 +6613,7 @@
values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
if (values2 == NULL) {
+ /* TODO: Propagate memory error. */
xmlXPathErrMemory(NULL, "comparing nodesets\n");
xmlXPathFreeObject(arg1);
xmlXPathFreeObject(arg2);
@@ -6858,11 +6874,13 @@
values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
if (values1 == NULL) {
+ /* TODO: Propagate memory error. */
xmlXPathErrMemory(NULL, "comparing nodesets\n");
return(0);
}
hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
if (hashs1 == NULL) {
+ /* TODO: Propagate memory error. */
xmlXPathErrMemory(NULL, "comparing nodesets\n");
xmlFree(values1);
return(0);
@@ -6870,6 +6888,7 @@
memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
if (values2 == NULL) {
+ /* TODO: Propagate memory error. */
xmlXPathErrMemory(NULL, "comparing nodesets\n");
xmlFree(hashs1);
xmlFree(values1);
@@ -6877,6 +6896,7 @@
}
hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
if (hashs2 == NULL) {
+ /* TODO: Propagate memory error. */
xmlXPathErrMemory(NULL, "comparing nodesets\n");
xmlFree(hashs1);
xmlFree(values1);
@@ -8569,6 +8589,7 @@
elem = (xmlNodePtr) attr;
else
elem = NULL;
+ /* TODO: Check memory error. */
if (elem != NULL)
xmlXPathNodeSetAdd(ret, elem);
}
@@ -8612,18 +8633,15 @@
xmlNodeSetPtr ns;
int i;
+ /* TODO: Check memory error. */
ret = xmlXPathNodeSetCreate(NULL);
- /*
- * FIXME -- in an out-of-memory condition this will behave badly.
- * The solution is not clear -- we already popped an item from
- * ctxt, so the object is in a corrupt state.
- */
if (obj->nodesetval != NULL) {
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
tokens =
xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
+ /* TODO: Check memory error. */
ret = xmlXPathNodeSetMerge(ret, ns);
xmlXPathFreeNodeSet(ns);
if (tokens != NULL)
@@ -12167,6 +12185,7 @@
if (seq == NULL) {
seq = xmlXPathNodeSetCreate(NULL);
if (seq == NULL) {
+ /* TODO: Propagate memory error. */
total = 0;
goto error;
}
@@ -12388,6 +12407,7 @@
outSeq = seq;
seq = NULL;
} else
+ /* TODO: Check memory error. */
outSeq = mergeAndClear(outSeq, seq);
/*
* Break if only a true/false result was requested.
@@ -12405,6 +12425,7 @@
outSeq = seq;
seq = NULL;
} else
+ /* TODO: Check memory error. */
outSeq = mergeAndClear(outSeq, seq);
break;
@@ -12470,6 +12491,7 @@
outSeq = seq;
seq = NULL;
} else {
+ /* TODO: Check memory error. */
outSeq = mergeAndClear(outSeq, seq);
}
@@ -12499,8 +12521,8 @@
if ((seq != NULL) && (seq->nodeNr == 0))
outSeq = seq;
else
+ /* TODO: Check memory error. */
outSeq = xmlXPathNodeSetCreate(NULL);
- /* XXX what if xmlXPathNodeSetCreate returned NULL here? */
}
if ((seq != NULL) && (seq != outSeq)) {
xmlXPathFreeNodeSet(seq);
@@ -12613,6 +12635,7 @@
break;
}
+ /* TODO: Check memory error. */
arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
arg2->nodesetval);
valuePush(ctxt, arg1);
@@ -12752,6 +12775,7 @@
break;
}
+ /* TODO: Check memory error. */
arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
arg2->nodesetval);
valuePush(ctxt, arg1);
@@ -13035,6 +13059,7 @@
((arg2->nodesetval != NULL) &&
(arg2->nodesetval->nodeNr != 0)))
{
+ /* TODO: Check memory error. */
arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
arg2->nodesetval);
}
@@ -13634,12 +13659,14 @@
/* Select "/" */
if (toBool)
return(1);
+ /* TODO: Check memory error. */
xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
(xmlNodePtr) ctxt->doc);
} else {
/* Select "self::node()" */
if (toBool)
return(1);
+ /* TODO: Check memory error. */
xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node);
}
}
@@ -13700,6 +13727,7 @@
} else if (ret == 1) {
if (toBool)
goto return_1;
+ /* TODO: Check memory error. */
xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur);
}
}