1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-01-13 13:17:36 +03:00

fixing bug #107129, removing excessive allocation and calls to *printf in

* tree.c valid.c xpath.c include/libxml/tree.h include/libxml/valid.h:
  fixing bug #107129, removing excessive allocation and calls
  to *printf in the code to build QName strings.
Daniel
This commit is contained in:
Daniel Veillard 2003-04-07 10:22:39 +00:00
parent 6965118d3c
commit c00cda8c06
6 changed files with 233 additions and 160 deletions

View File

@ -1,3 +1,9 @@
Mon Apr 7 12:19:26 CEST 2003 Daniel Veillard <daniel@veillard.com>
* tree.c valid.c xpath.c include/libxml/tree.h include/libxml/valid.h:
fixing bug #107129, removing excessive allocation and calls
to *printf in the code to build QName strings.
Sat Apr 5 11:41:36 CEST 2003 Igoe Zlatkovic <igor@zlatkovic.com>
* win32/libxml2.def.src: fixed conditional exports, reported by

View File

@ -538,11 +538,24 @@ LIBXML_DLL_IMPORT extern int xmlSaveNoEmptyTags; /* save empty tags as <empty></
LIBXML_DLL_IMPORT extern int xmlDefaultBufferSize; /* default buffer size */
#endif
int xmlValidateNCName (const xmlChar *value, int space);
int xmlValidateQName (const xmlChar *value, int space);
int xmlValidateName (const xmlChar *value, int space);
int xmlValidateNMToken (const xmlChar *value, int space);
/*
* Some helper functions
*/
int xmlValidateNCName (const xmlChar *value,
int space);
int xmlValidateQName (const xmlChar *value,
int space);
int xmlValidateName (const xmlChar *value,
int space);
int xmlValidateNMToken (const xmlChar *value,
int space);
xmlChar * xmlBuildQName (const xmlChar *ncname,
const xmlChar *prefix,
xmlChar *memory,
int len);
xmlChar * xmlSplitQName2 (const xmlChar *name,
xmlChar **prefix);
/*
* Handling Buffers.
*/

View File

@ -127,10 +127,6 @@ typedef xmlIDTable *xmlIDTablePtr;
typedef struct _xmlHashTable xmlRefTable;
typedef xmlRefTable *xmlRefTablePtr;
/* helper */
xmlChar * xmlSplitQName2 (const xmlChar *name,
xmlChar **prefix);
/* Notation */
xmlNotationPtr xmlAddNotationDecl (xmlValidCtxtPtr ctxt,
xmlDtdPtr dtd,

97
tree.c
View File

@ -123,6 +123,102 @@ xmlGetParameterEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) {
return(NULL);
}
/************************************************************************
* *
* QName handling helper *
* *
************************************************************************/
/**
* xmlBuildQName:
* @ncname: the Name
* @prefix: the prefix
* @memory: preallocated memory
* @len: preallocated memory length
*
* Builds the QName @prefix:@ncname in @memory if there is enough space
* and prefix is not NULL nor empty, otherwise allocate a new string.
* If prefix is NULL or empty it returns ncname.
*
* Returns the new string which must be freed by the caller if different from
* @memory and @ncname or NULL in case of error
*/
xmlChar *
xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
xmlChar *memory, int len) {
int lenn, lenp;
xmlChar *ret;
if ((ncname == NULL) || (*ncname == 0)) return(NULL);
if ((prefix == NULL) || (*prefix == 0)) return((xmlChar *) ncname);
lenn = strlen((char *) ncname);
lenp = strlen((char *) prefix);
if ((memory == NULL) || (len < lenn + lenp + 2)) {
ret = (xmlChar *) xmlMalloc(lenn + lenp + 2);
if (ret == NULL) return(NULL);
} else {
ret = memory;
}
memcpy(&ret[0], prefix, lenp);
ret[lenp] = ':';
memcpy(&ret[lenp + 1], ncname, lenn);
ret[lenn + lenp + 1] = 0;
return(ret);
}
/**
* xmlSplitQName2:
* @name: the full QName
* @prefix: a xmlChar **
*
* parse an XML qualified name string
*
* [NS 5] QName ::= (Prefix ':')? LocalPart
*
* [NS 6] Prefix ::= NCName
*
* [NS 7] LocalPart ::= NCName
*
* Returns NULL if not a QName, otherwise the local part, and prefix
* is updated to get the Prefix if any.
*/
xmlChar *
xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
int len = 0;
xmlChar *ret = NULL;
*prefix = NULL;
#ifndef XML_XML_NAMESPACE
/* xml: prefix is not really a namespace */
if ((name[0] == 'x') && (name[1] == 'm') &&
(name[2] == 'l') && (name[3] == ':'))
return(NULL);
#endif
/* nasty but valid */
if (name[0] == ':')
return(NULL);
/*
* we are not trying to validate but just to cut, and yes it will
* work even if this is as set of UTF-8 encoded chars
*/
while ((name[len] != 0) && (name[len] != ':'))
len++;
if (name[len] == 0)
return(NULL);
*prefix = xmlStrndup(name, len);
ret = xmlStrdup(&name[len + 1]);
return(ret);
}
/************************************************************************
* *
* Check Name, NCName and QName strings *
@ -3915,6 +4011,7 @@ xmlGetNodePath(xmlNodePtr node)
/*
* Thumbler index computation
* TODO: the ocurence test seems bogus for namespaced names
*/
tmp = cur->prev;
while (tmp != NULL) {

243
valid.c
View File

@ -505,51 +505,40 @@ xmlValidBuildAContentModel(xmlElementContentPtr content,
break;
case XML_ELEMENT_CONTENT_ELEMENT: {
xmlAutomataStatePtr oldstate = ctxt->state;
xmlChar *QName = NULL;
const xmlChar *fname = content->name;
if (content->prefix != NULL) {
int len;
len = xmlStrlen(content->name) +
xmlStrlen(content->prefix) + 2;
QName = xmlMalloc(len);
if (QName == NULL) {
VERROR(ctxt->userData,
"ContentModel %s : alloc failed\n", name);
return(0);
}
snprintf((char *) QName, len, "%s:%s",
(char *)content->prefix,
(char *)content->name);
fname = QName;
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(content->name, content->prefix, fn, 50);
if (fullname == NULL) {
VERROR(ctxt->userData, "Out of memory\n");
return(0);
}
switch (content->ocur) {
case XML_ELEMENT_CONTENT_ONCE:
ctxt->state = xmlAutomataNewTransition(ctxt->am,
ctxt->state, NULL, fname, NULL);
ctxt->state, NULL, fullname, NULL);
break;
case XML_ELEMENT_CONTENT_OPT:
ctxt->state = xmlAutomataNewTransition(ctxt->am,
ctxt->state, NULL, fname, NULL);
ctxt->state, NULL, fullname, NULL);
xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
break;
case XML_ELEMENT_CONTENT_PLUS:
ctxt->state = xmlAutomataNewTransition(ctxt->am,
ctxt->state, NULL, fname, NULL);
ctxt->state, NULL, fullname, NULL);
xmlAutomataNewTransition(ctxt->am, ctxt->state,
ctxt->state, fname, NULL);
ctxt->state, fullname, NULL);
break;
case XML_ELEMENT_CONTENT_MULT:
xmlAutomataNewTransition(ctxt->am, ctxt->state,
ctxt->state, fname, NULL);
ctxt->state, fullname, NULL);
ctxt->state = xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
NULL);
break;
}
if (QName != NULL)
xmlFree(QName);
if ((fullname != fn) && (fullname != content->name))
xmlFree(fullname);
break;
}
case XML_ELEMENT_CONTENT_SEQ: {
@ -702,63 +691,6 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
#endif /* LIBXML_REGEXP_ENABLED */
/************************************************************************
* *
* QName handling helper *
* *
************************************************************************/
/**
* xmlSplitQName2:
* @name: an XML parser context
* @prefix: a xmlChar **
*
* parse an XML qualified name string
*
* [NS 5] QName ::= (Prefix ':')? LocalPart
*
* [NS 6] Prefix ::= NCName
*
* [NS 7] LocalPart ::= NCName
*
* Returns NULL if not a QName, otherwise the local part, and prefix
* is updated to get the Prefix if any.
*/
xmlChar *
xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
int len = 0;
xmlChar *ret = NULL;
*prefix = NULL;
#ifndef XML_XML_NAMESPACE
/* xml: prefix is not really a namespace */
if ((name[0] == 'x') && (name[1] == 'm') &&
(name[2] == 'l') && (name[3] == ':'))
return(NULL);
#endif
/* nasty but valid */
if (name[0] == ':')
return(NULL);
/*
* we are not trying to validate but just to cut, and yes it will
* work even if this is as set of UTF-8 encoded chars
*/
while ((name[len] != 0) && (name[len] != ':'))
len++;
if (name[len] == 0)
return(NULL);
*prefix = xmlStrndup(name, len);
ret = xmlStrdup(&name[len + 1]);
return(ret);
}
/****************************************************************
* *
* Util functions for data allocation/deallocation *
@ -2332,23 +2264,19 @@ xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) {
if (elem == NULL) return(0);
if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
/*
* TODO: this sucks ... recomputing this every time is stupid
*/
int len = xmlStrlen(elem->name) + xmlStrlen(elem->ns->prefix) + 2;
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlMalloc(len);
fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
if (fullname == NULL)
return(0);
snprintf((char *) fullname, len, "%s:%s", (char *) elem->ns->prefix,
(char *) elem->name);
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname,
attr->name);
if ((attrDecl == NULL) && (doc->extSubset != NULL))
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname,
attr->name);
xmlFree(fullname);
if ((fullname != fn) && (fullname != elem->name))
xmlFree(fullname);
} else {
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name,
attr->name);
@ -3469,16 +3397,20 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
if (value == NULL) return(NULL);
if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
xmlChar qname[500];
snprintf((char *) qname, sizeof(qname), "%s:%s",
elem->ns->prefix, elem->name);
qname[sizeof(qname) - 1] = 0;
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, qname, name);
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
if (fullname == NULL)
return(0);
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name);
if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, qname, name);
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name);
if (attrDecl != NULL)
extsubset = 1;
}
if ((fullname != fn) && (fullname != elem->name))
xmlFree(fullname);
}
if ((attrDecl == NULL) && (doc->intSubset != NULL))
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
@ -3550,13 +3482,17 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
if (value == NULL) return(NULL);
if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
xmlChar qname[500];
snprintf((char *) qname, sizeof(qname), "%s:%s",
elem->ns->prefix, elem->name);
qname[sizeof(qname) - 1] = 0;
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, qname, name);
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
if (fullname == NULL)
return(0);
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, name);
if ((attrDecl == NULL) && (doc->extSubset != NULL))
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, qname, name);
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname, name);
if ((fullname != fn) && (fullname != elem->name))
xmlFree(fullname);
}
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
if ((attrDecl == NULL) && (doc->extSubset != NULL))
@ -3836,22 +3772,26 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
if ((attr == NULL) || (attr->name == NULL)) return(0);
if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
xmlChar qname[500];
snprintf((char *) qname, sizeof(qname), "%s:%s",
elem->ns->prefix, elem->name);
qname[sizeof(qname) - 1] = 0;
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(elem->name, elem->ns->prefix, fn, 50);
if (fullname == NULL)
return(0);
if (attr->ns != NULL) {
attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, qname,
attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
attr->name, attr->ns->prefix);
if ((attrDecl == NULL) && (doc->extSubset != NULL))
attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, qname,
attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
attr->name, attr->ns->prefix);
} else {
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, qname, attr->name);
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname, attr->name);
if ((attrDecl == NULL) && (doc->extSubset != NULL))
attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
qname, attr->name);
fullname, attr->name);
}
if ((fullname != fn) && (fullname != elem->name))
xmlFree(fullname);
}
if (attrDecl == NULL) {
if (attr->ns != NULL) {
@ -4016,23 +3956,29 @@ xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value) {
if ((ns == NULL) || (ns->href == NULL)) return(0);
if (prefix != NULL) {
xmlChar qname[500];
snprintf((char *) qname, sizeof(qname), "%s:%s",
prefix, elem->name);
qname[sizeof(qname) - 1] = 0;
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(elem->name, prefix, fn, 50);
if (fullname == NULL) {
VERROR(ctxt->userData, "Out of memory\n");
return(0);
}
if (ns->prefix != NULL) {
attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, qname,
attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, fullname,
ns->prefix, BAD_CAST "xmlns");
if ((attrDecl == NULL) && (doc->extSubset != NULL))
attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, qname,
attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, fullname,
ns->prefix, BAD_CAST "xmlns");
} else {
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, qname,
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, fullname,
BAD_CAST "xmlns");
if ((attrDecl == NULL) && (doc->extSubset != NULL))
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, qname,
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, fullname,
BAD_CAST "xmlns");
}
if ((fullname != fn) && (fullname != elem->name))
xmlFree(fullname);
}
if (attrDecl == NULL) {
if (ns->prefix != NULL) {
@ -4766,21 +4712,18 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
goto fail;
case XML_ELEMENT_NODE:
if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
xmlChar *QName;
int len;
len = xmlStrlen(cur->name) +
xmlStrlen(cur->ns->prefix) + 2;
QName = xmlMalloc(len);
if (QName == NULL) {
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(cur->name,
cur->ns->prefix, fn, 50);
if (fullname == NULL) {
ret = -1;
goto fail;
}
snprintf((char *) QName, len, "%s:%s",
(char *)cur->ns->prefix,
(char *)cur->name);
ret = xmlRegExecPushString(exec, QName, NULL);
xmlFree(QName);
ret = xmlRegExecPushString(exec, fullname, NULL);
if ((fullname != fn) && (fullname != cur->name))
xmlFree(fullname);
} else {
ret = xmlRegExecPushString(exec, cur->name, NULL);
}
@ -5524,18 +5467,23 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
if (child->type == XML_ELEMENT_NODE) {
name = child->name;
if ((child->ns != NULL) && (child->ns->prefix != NULL)) {
xmlChar qname[500];
snprintf((char *) qname, sizeof(qname), "%s:%s",
child->ns->prefix, child->name);
qname[sizeof(qname) - 1] = 0;
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(child->name, child->ns->prefix,
fn, 50);
if (fullname == NULL)
return(0);
cont = elemDecl->content;
while (cont != NULL) {
if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
if (xmlStrEqual(cont->name, qname)) break;
if (xmlStrEqual(cont->name, fullname))
break;
} else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
(cont->c1 != NULL) &&
(cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
if (xmlStrEqual(cont->c1->name, qname)) break;
if (xmlStrEqual(cont->c1->name, fullname))
break;
} else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
(cont->c1 == NULL) ||
(cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
@ -5546,6 +5494,8 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
}
cont = cont->c2;
}
if ((fullname != fn) && (fullname != child->name))
xmlFree(fullname);
if (cont != NULL)
goto child_ok;
}
@ -5766,6 +5716,8 @@ found:
int
xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
xmlNodePtr root;
int ret;
if (doc == NULL) return(0);
root = xmlDocGetRootElement(doc);
@ -5785,11 +5737,18 @@ xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
*/
if (!xmlStrEqual(doc->intSubset->name, root->name)) {
if ((root->ns != NULL) && (root->ns->prefix != NULL)) {
xmlChar qname[500];
snprintf((char *) qname, sizeof(qname), "%s:%s",
root->ns->prefix, root->name);
qname[sizeof(qname) - 1] = 0;
if (xmlStrEqual(doc->intSubset->name, qname))
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(root->name, root->ns->prefix, fn, 50);
if (fullname == NULL) {
VERROR(ctxt->userData, "Out of memory\n");
return(0);
}
ret = xmlStrEqual(doc->intSubset->name, fullname);
if ((fullname != fn) && (fullname != root->name))
xmlFree(fullname);
if (ret == 1)
goto name_ok;
}
if ((xmlStrEqual(doc->intSubset->name, BAD_CAST "HTML")) &&

22
xpath.c
View File

@ -6186,18 +6186,20 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
(cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
valuePush(ctxt,
xmlXPathNewString(cur->nodesetval->
nodeTab[i]->name));
xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
} else {
char name[2000];
snprintf(name, sizeof(name), "%s:%s",
(char *) cur->nodesetval->nodeTab[i]->ns->
prefix,
(char *) cur->nodesetval->nodeTab[i]->name);
name[sizeof(name) - 1] = 0;
valuePush(ctxt, xmlXPathNewCString(name));
xmlChar *fullname;
fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
cur->nodesetval->nodeTab[i]->ns->prefix,
NULL, 0);
if (fullname == cur->nodesetval->nodeTab[i]->name)
fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
if (fullname == NULL) {
XP_ERROR(XPATH_MEMORY_ERROR);
}
valuePush(ctxt, xmlXPathWrapString(fullname));
}
break;
default: