mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-02-11 01:58:56 +03:00
SAX2: Fix quadratic behavior in xmlSAX2AttributeNs
The last missing piece to make parsing of attributes O(n).
This commit is contained in:
parent
a40c32ac1f
commit
a31e1b0665
69
SAX2.c
69
SAX2.c
@ -1855,8 +1855,10 @@ decode:
|
||||
* The default handling is to convert the attribute into an
|
||||
* DOM subtree and past it in a new xmlAttr element added to
|
||||
* the element.
|
||||
*
|
||||
* Returns the new attribute or NULL in case of error.
|
||||
*/
|
||||
static void
|
||||
static xmlAttrPtr
|
||||
xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
|
||||
const xmlChar * localname,
|
||||
const xmlChar * prefix,
|
||||
@ -1884,6 +1886,14 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
|
||||
ret = ctxt->freeAttrs;
|
||||
ctxt->freeAttrs = ret->next;
|
||||
ctxt->freeAttrsNr--;
|
||||
} else {
|
||||
ret = xmlMalloc(sizeof(*ret));
|
||||
if (ret == NULL) {
|
||||
xmlSAX2ErrMemory(ctxt, NULL);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
memset(ret, 0, sizeof(xmlAttr));
|
||||
ret->type = XML_ATTRIBUTE_NODE;
|
||||
|
||||
@ -1896,30 +1906,8 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
|
||||
else
|
||||
ret->name = xmlStrdup(localname);
|
||||
|
||||
/* link at the end to preserve order, TODO speed up with a last */
|
||||
if (ctxt->node->properties == NULL) {
|
||||
ctxt->node->properties = ret;
|
||||
} else {
|
||||
xmlAttrPtr prev = ctxt->node->properties;
|
||||
|
||||
while (prev->next != NULL) prev = prev->next;
|
||||
prev->next = ret;
|
||||
ret->prev = prev;
|
||||
}
|
||||
|
||||
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
|
||||
xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
|
||||
} else {
|
||||
if (ctxt->dictNames)
|
||||
ret = xmlNewNsPropEatName(ctxt->node, namespace,
|
||||
(xmlChar *) localname, NULL);
|
||||
else
|
||||
ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
|
||||
if (ret == NULL) {
|
||||
xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
|
||||
xmlNodePtr tmp;
|
||||
@ -2065,6 +2053,8 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
|
||||
}
|
||||
if (dup != NULL)
|
||||
xmlFree(dup);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2275,7 +2265,11 @@ xmlSAX2StartElementNs(void *ctx,
|
||||
* process all the other attributes
|
||||
*/
|
||||
if (nb_attributes > 0) {
|
||||
xmlAttrPtr prev = NULL;
|
||||
|
||||
for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
|
||||
xmlAttrPtr attr = NULL;
|
||||
|
||||
/*
|
||||
* Handle the rare case of an undefined attribute prefix
|
||||
*/
|
||||
@ -2286,23 +2280,38 @@ xmlSAX2StartElementNs(void *ctx,
|
||||
fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
|
||||
attributes[j]);
|
||||
if (fullname != NULL) {
|
||||
xmlSAX2AttributeNs(ctxt, fullname, NULL,
|
||||
attributes[j+3], attributes[j+4]);
|
||||
continue;
|
||||
attr = xmlSAX2AttributeNs(ctxt, fullname, NULL,
|
||||
attributes[j+3],
|
||||
attributes[j+4]);
|
||||
goto have_attr;
|
||||
}
|
||||
} else {
|
||||
lname = xmlBuildQName(attributes[j], attributes[j+1],
|
||||
NULL, 0);
|
||||
if (lname != NULL) {
|
||||
xmlSAX2AttributeNs(ctxt, lname, NULL,
|
||||
attributes[j+3], attributes[j+4]);
|
||||
attr = xmlSAX2AttributeNs(ctxt, lname, NULL,
|
||||
attributes[j+3],
|
||||
attributes[j+4]);
|
||||
xmlFree(lname);
|
||||
continue;
|
||||
goto have_attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
|
||||
attr = xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
|
||||
attributes[j+3], attributes[j+4]);
|
||||
have_attr:
|
||||
if (attr == NULL)
|
||||
continue;
|
||||
|
||||
/* link at the end to preserve order */
|
||||
if (prev == NULL) {
|
||||
ctxt->node->properties = attr;
|
||||
} else {
|
||||
prev->next = attr;
|
||||
attr->prev = prev;
|
||||
}
|
||||
|
||||
prev = attr;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user