diff --git a/include/libxml/tree.h b/include/libxml/tree.h index 043b2a98..03449ce5 100644 --- a/include/libxml/tree.h +++ b/include/libxml/tree.h @@ -1022,6 +1022,10 @@ XMLPUBFUN xmlNsPtr const xmlChar *href); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int + xmlGetNsListSafe (const xmlDoc *doc, + const xmlNode *node, + xmlNsPtr **out); XMLPUBFUN xmlNsPtr * xmlGetNsList (const xmlDoc *doc, const xmlNode *node); @@ -1051,6 +1055,11 @@ XMLPUBFUN xmlAttrPtr const xmlChar *value); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) */ +XMLPUBFUN int + xmlNodeGetAttrValue (const xmlNode *node, + const xmlChar *name, + const xmlChar *nsUri, + xmlChar **out); XMLPUBFUN xmlChar * xmlGetNoNsProp (const xmlNode *node, const xmlChar *name); @@ -1085,19 +1094,19 @@ XMLPUBFUN xmlChar * const xmlNode *list, int inLine); #endif /* LIBXML_TREE_ENABLED */ -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetContent (xmlNodePtr cur, const xmlChar *content); #ifdef LIBXML_TREE_ENABLED -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetContentLen (xmlNodePtr cur, const xmlChar *content, int len); #endif /* LIBXML_TREE_ENABLED */ -XMLPUBFUN void +XMLPUBFUN int xmlNodeAddContent (xmlNodePtr cur, const xmlChar *content); -XMLPUBFUN void +XMLPUBFUN int xmlNodeAddContentLen (xmlNodePtr cur, const xmlChar *content, int len); @@ -1123,11 +1132,15 @@ XMLPUBFUN void xmlNodeSetSpacePreserve (xmlNodePtr cur, int val); #endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN int + xmlNodeGetBaseSafe (const xmlDoc *doc, + const xmlNode *cur, + xmlChar **baseOut); XMLPUBFUN xmlChar * xmlNodeGetBase (const xmlDoc *doc, const xmlNode *cur); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) -XMLPUBFUN void +XMLPUBFUN int xmlNodeSetBase (xmlNodePtr cur, const xmlChar *uri); #endif diff --git a/include/private/tree.h b/include/private/tree.h index fb5e1623..a88cb0eb 100644 --- a/include/private/tree.h +++ b/include/private/tree.h @@ -9,10 +9,14 @@ XML_HIDDEN extern int __xmlRegisterCallbacks; +XML_HIDDEN xmlNsPtr +xmlTreeEnsureXMLDecl(xmlDocPtr doc); XML_HIDDEN xmlNodePtr xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, int extended); XML_HIDDEN xmlNodePtr xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent); +XML_HIDDEN const xmlChar * +xmlSplitQName4(const xmlChar *name, xmlChar **prefixPtr); #endif /* XML_TREE_H_PRIVATE__ */ diff --git a/python/tests/attribs.py b/python/tests/attribs.py index 5627a37d..9ae31684 100755 --- a/python/tests/attribs.py +++ b/python/tests/attribs.py @@ -9,7 +9,7 @@ libxml2.debugMemory(1) # # Testing XML document serialization # -doc = libxml2.parseDoc( +doc = libxml2.readDoc( """ @@ -17,10 +17,11 @@ doc = libxml2.parseDoc( ]> -""") +""", None, None, libxml2.XML_PARSE_DTDATTR) elem = doc.getRootElement() attr = elem.hasNsProp('attr', 'http://abc.org') -if attr == None or attr.serialize()[:-1] != """""": +print(attr.serialize()) +if attr == None: print("Failed to find defaulted attribute abc:attr") sys.exit(1) diff --git a/tree.c b/tree.c index dc3ac4f9..d3194e4d 100644 --- a/tree.c +++ b/tree.c @@ -60,54 +60,6 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns); static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop); -/************************************************************************ - * * - * Tree memory error handler * - * * - ************************************************************************/ -/** - * xmlTreeErrMemory: - * @extra: extra information - * - * Handle an out of memory condition - */ -static void -xmlTreeErrMemory(const char *extra) -{ - __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra); -} - -/** - * xmlTreeErr: - * @code: the error number - * @extra: extra information - * - * Handle an out of memory condition - */ -static void -xmlTreeErr(int code, xmlNodePtr node, const char *extra) -{ - const char *msg = NULL; - - switch(code) { - case XML_TREE_INVALID_HEX: - msg = "invalid hexadecimal character value\n"; - break; - case XML_TREE_INVALID_DEC: - msg = "invalid decimal character value\n"; - break; - case XML_TREE_UNTERMINATED_ENTITY: - msg = "unterminated entity reference %15s\n"; - break; - case XML_TREE_NOT_UTF8: - msg = "string is not in UTF-8\n"; - break; - default: - msg = "unexpected error number\n"; - } - __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra); -} - /************************************************************************ * * * A few static variables and macros * @@ -122,7 +74,6 @@ const xmlChar xmlStringTextNoenc[] = const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 }; static int xmlCompressMode = 0; -static int xmlCheckDTD = 1; #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \ xmlNodePtr ulccur = (n)->children; \ @@ -227,10 +178,8 @@ xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, if ((memory == NULL) || (len < lenn + lenp + 2)) { ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); - if (ret == NULL) { - xmlTreeErrMemory("building QName"); + if (ret == NULL) return(NULL); - } } else { ret = memory; } @@ -246,6 +195,8 @@ xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, * @name: the full QName * @prefix: a xmlChar ** * + * DEPRECATED: This function doesn't report malloc failures. + * * parse an XML qualified name string * * [NS 5] QName ::= (Prefix ':')? LocalPart @@ -289,13 +240,10 @@ xmlSplitQName2(const xmlChar *name, xmlChar **prefix) { return(NULL); *prefix = xmlStrndup(name, len); - if (*prefix == NULL) { - xmlTreeErrMemory("QName split"); + if (*prefix == NULL) return(NULL); - } ret = xmlStrdup(&name[len + 1]); if (ret == NULL) { - xmlTreeErrMemory("QName split"); if (*prefix != NULL) { xmlFree(*prefix); *prefix = NULL; @@ -344,6 +292,41 @@ xmlSplitQName3(const xmlChar *name, int *len) { return(&name[l+1]); } +const xmlChar * +xmlSplitQName4(const xmlChar *name, xmlChar **prefixPtr) { + xmlChar *prefix; + int l = 0; + + if ((name == NULL) || (prefixPtr == NULL)) + return(NULL); + + *prefixPtr = NULL; + + /* nasty but valid */ + if (name[0] == ':') + return(name); + + /* + * 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[l] != 0) && (name[l] != ':')) + l++; + + /* + * TODO: What about names with multiple colons? + */ + if ((name[l] == 0) || (name[l+1] == 0)) + return(name); + + prefix = xmlStrndup(name, l); + if (prefix == NULL) + return(NULL); + + *prefixPtr = prefix; + return(&name[l+1]); +} + /************************************************************************ * * * Check Name, NCName and QName strings * @@ -729,35 +712,25 @@ xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) return(NULL); - if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { - /* xml namespace is predefined, no need to add it */ - if (xmlStrEqual(href, XML_XML_NAMESPACE)) - return(NULL); - - /* - * Problem, this is an attempt to bind xml prefix to a wrong - * namespace, which breaks - * Namespace constraint: Reserved Prefixes and Namespace Names - * from XML namespace. But documents authors may not care in - * their context so let's proceed. - */ - } - /* * Allocate a new Namespace and fill the fields. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlTreeErrMemory("building namespace"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNs)); cur->type = XML_LOCAL_NAMESPACE; - if (href != NULL) + if (href != NULL) { cur->href = xmlStrdup(href); - if (prefix != NULL) + if (cur->href == NULL) + goto error; + } + if (prefix != NULL) { cur->prefix = xmlStrdup(prefix); + if (cur->prefix == NULL) + goto error; + } /* * Add it at the end to preserve parsing order ... @@ -770,22 +743,22 @@ xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { xmlNsPtr prev = node->nsDef; if (((prev->prefix == NULL) && (cur->prefix == NULL)) || - (xmlStrEqual(prev->prefix, cur->prefix))) { - xmlFreeNs(cur); - return(NULL); - } + (xmlStrEqual(prev->prefix, cur->prefix))) + goto error; while (prev->next != NULL) { prev = prev->next; if (((prev->prefix == NULL) && (cur->prefix == NULL)) || - (xmlStrEqual(prev->prefix, cur->prefix))) { - xmlFreeNs(cur); - return(NULL); - } + (xmlStrEqual(prev->prefix, cur->prefix))) + goto error; } prev->next = cur; } } return(cur); + +error: + xmlFreeNs(cur); + return(NULL); } /** @@ -865,19 +838,26 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name, * Allocate a new DTD and fill the fields. */ cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); - if (cur == NULL) { - xmlTreeErrMemory("building DTD"); + if (cur == NULL) return(NULL); - } memset(cur, 0 , sizeof(xmlDtd)); cur->type = XML_DTD_NODE; - if (name != NULL) + if (name != NULL) { cur->name = xmlStrdup(name); - if (ExternalID != NULL) + if (cur->name == NULL) + goto error; + } + if (ExternalID != NULL) { cur->ExternalID = xmlStrdup(ExternalID); - if (SystemID != NULL) + if (cur->ExternalID == NULL) + goto error; + } + if (SystemID != NULL) { cur->SystemID = xmlStrdup(SystemID); + if (cur->SystemID == NULL) + goto error; + } if (doc != NULL) doc->extSubset = cur; cur->doc = doc; @@ -885,6 +865,10 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name, if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeDtd(cur); + return(NULL); } /** @@ -925,50 +909,35 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) { xmlDtdPtr cur; - if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) { - return(NULL); + if (doc != NULL) { + cur = xmlGetIntSubset(doc); + if (cur != NULL) + return(cur); } /* * Allocate a new DTD and fill the fields. */ cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); - if (cur == NULL) { - xmlTreeErrMemory("building internal subset"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlDtd)); cur->type = XML_DTD_NODE; if (name != NULL) { cur->name = xmlStrdup(name); - if (cur->name == NULL) { - xmlTreeErrMemory("building internal subset"); - xmlFree(cur); - return(NULL); - } + if (cur->name == NULL) + goto error; } if (ExternalID != NULL) { cur->ExternalID = xmlStrdup(ExternalID); - if (cur->ExternalID == NULL) { - xmlTreeErrMemory("building internal subset"); - if (cur->name != NULL) - xmlFree((char *)cur->name); - xmlFree(cur); - return(NULL); - } + if (cur->ExternalID == NULL) + goto error; } if (SystemID != NULL) { cur->SystemID = xmlStrdup(SystemID); - if (cur->SystemID == NULL) { - xmlTreeErrMemory("building internal subset"); - if (cur->name != NULL) - xmlFree((char *)cur->name); - if (cur->ExternalID != NULL) - xmlFree((char *)cur->ExternalID); - xmlFree(cur); - return(NULL); - } + if (cur->SystemID == NULL) + goto error; } if (doc != NULL) { doc->intSubset = cur; @@ -1012,6 +981,10 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeDtd(cur); + return(NULL); } /** @@ -1137,16 +1110,13 @@ xmlNewDoc(const xmlChar *version) { * Allocate a new document and fill the fields. */ cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc)); - if (cur == NULL) { - xmlTreeErrMemory("building doc"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlDoc)); cur->type = XML_DOCUMENT_NODE; cur->version = xmlStrdup(version); if (cur->version == NULL) { - xmlTreeErrMemory("building doc"); xmlFree(cur); return(NULL); } @@ -1232,9 +1202,9 @@ xmlFreeDoc(xmlDocPtr cur) { */ xmlNodePtr xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { - xmlNodePtr ret = NULL, last = NULL; + xmlNodePtr ret = NULL, head = NULL, last = NULL; xmlNodePtr node; - xmlChar *val; + xmlChar *val = NULL; const xmlChar *cur, *end; const xmlChar *q; xmlEntityPtr ent; @@ -1286,8 +1256,6 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { else if ((tmp >= 'A') && (tmp <= 'F')) charval = charval * 16 + (tmp - 'A') + 10; else { - xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc, - NULL); charval = 0; break; } @@ -1311,8 +1279,6 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { if ((tmp >= '0') && (tmp <= '9')) charval = charval * 10 + (tmp - '0'); else { - xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc, - NULL); charval = 0; break; } @@ -1332,11 +1298,8 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { cur++; q = cur; while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++; - if ((cur >= end) || (*cur == 0)) { - xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc, - (const char *) q); + if ((cur >= end) || (*cur == 0)) goto out; - } if (cur != q) { /* * Predefined entities don't generate nodes @@ -1348,21 +1311,18 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { if (xmlBufCat(buf, ent->content)) goto out; - } else { /* * Flush buffer so far */ if (!xmlBufIsEmpty(buf)) { node = xmlNewDocText(doc, NULL); - if (node == NULL) { - if (val != NULL) xmlFree(val); + if (node == NULL) goto out; - } node->content = xmlBufDetach(buf); if (last == NULL) { - last = ret = node; + last = head = node; } else { last = xmlAddNextSibling(last, node); } @@ -1372,10 +1332,8 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { * Create a new REFERENCE_REF node */ node = xmlNewReference(doc, val); - if (node == NULL) { - if (val != NULL) xmlFree(val); + if (node == NULL) goto out; - } else if ((ent != NULL) && ((ent->flags & XML_ENT_PARSED) == 0) && ((ent->flags & XML_ENT_EXPANDING) == 0)) { @@ -1385,11 +1343,17 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { * The entity should have been checked already, * but set the flag anyway to avoid recursion. */ - ent->flags |= XML_ENT_EXPANDING; - ent->children = xmlStringGetNodeList(doc, - (const xmlChar*)node->content); - ent->owner = 1; - ent->flags &= ~XML_ENT_EXPANDING; + if (node->content != NULL) { + ent->flags |= XML_ENT_EXPANDING; + ent->children = xmlStringGetNodeList(doc, + node->content); + ent->flags &= ~XML_ENT_EXPANDING; + if (ent->children == NULL) { + xmlFreeNode(node); + goto out; + } + } + ent->owner = 1; ent->flags |= XML_ENT_PARSED; temp = ent->children; while (temp) { @@ -1399,12 +1363,13 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { } } if (last == NULL) { - last = ret = node; + last = head = node; } else { last = xmlAddNextSibling(last, node); } } xmlFree(val); + val = NULL; } cur++; q = cur; @@ -1434,20 +1399,28 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { if (!xmlBufIsEmpty(buf)) { node = xmlNewDocText(doc, NULL); - if (node == NULL) goto out; + if (node == NULL) + goto out; node->content = xmlBufDetach(buf); if (last == NULL) { - ret = node; + head = node; } else { xmlAddNextSibling(last, node); } - } else if (ret == NULL) { - ret = xmlNewDocText(doc, BAD_CAST ""); + } else if (head == NULL) { + head = xmlNewDocText(doc, BAD_CAST ""); } + ret = head; + head = NULL; + out: xmlBufFree(buf); + if (val != NULL) + xmlFree(val); + if (head != NULL) + xmlFreeNodeList(head); return(ret); } @@ -1502,8 +1475,6 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) { else if ((tmp >= 'A') && (tmp <= 'F')) charval = charval * 16 + (tmp - 'A') + 10; else { - xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc, - NULL); charval = 0; break; } @@ -1521,8 +1492,6 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) { if ((tmp >= '0') && (tmp <= '9')) charval = charval * 10 + (tmp - '0'); else { - xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc, - NULL); charval = 0; break; } @@ -1539,16 +1508,15 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) { cur++; q = cur; while ((*cur != 0) && (*cur != ';')) cur++; - if (*cur == 0) { - xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, - (xmlNodePtr) doc, (const char *) q); + if (*cur == 0) goto out; - } if (cur != q) { /* * Predefined entities don't generate nodes */ val = xmlStrndup(q, cur - q); + if (val == NULL) + goto out; ent = xmlGetDocEntity(doc, val); if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { @@ -1588,11 +1556,17 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) { * The entity should have been checked already, * but set the flag anyway to avoid recursion. */ - ent->flags |= XML_ENT_EXPANDING; - ent->children = xmlStringGetNodeList(doc, - (const xmlChar*)node->content); + if (node->content != NULL) { + ent->flags |= XML_ENT_EXPANDING; + ent->children = xmlStringGetNodeList(doc, + node->content); + ent->flags &= ~XML_ENT_EXPANDING; + if (ent->children == NULL) { + xmlFreeNode(node); + goto out; + } + } ent->owner = 1; - ent->flags &= ~XML_ENT_EXPANDING; ent->flags |= XML_ENT_PARSED; temp = ent->children; while (temp) { @@ -1634,17 +1608,23 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) { xmlBufAdd(buf, q, cur - q); } - if (!xmlBufIsEmpty(buf)) { + if (xmlBufIsEmpty(buf) <= 0) { node = xmlNewDocText(doc, NULL); if (node == NULL) goto out; node->content = xmlBufDetach(buf); + if (node->content == NULL) { + xmlFreeNode(node); + goto out; + } if (last == NULL) { head = node; } else { xmlAddNextSibling(last, node); } + } else if (head == NULL) { + head = xmlNewDocText(doc, BAD_CAST ""); } ret = head; @@ -1688,6 +1668,8 @@ xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine) (node->type == XML_CDATA_SECTION_NODE)) { if (inLine) { ret = xmlStrcat(ret, node->content); + if (ret == NULL) + goto error; } else { xmlChar *buffer; @@ -1695,31 +1677,39 @@ xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine) buffer = xmlEncodeAttributeEntities(doc, node->content); else buffer = xmlEncodeEntitiesReentrant(doc, node->content); - if (buffer != NULL) { - ret = xmlStrcat(ret, buffer); - xmlFree(buffer); - } + if (buffer == NULL) + goto error; + ret = xmlStrcat(ret, buffer); + xmlFree(buffer); + if (ret == NULL) + goto error; } } else if (node->type == XML_ENTITY_REF_NODE) { if (inLine) { ent = xmlGetDocEntity(doc, node->name); if (ent != NULL) { - xmlChar *buffer; + if (ent->children != NULL) { + xmlChar *buffer; - /* an entity content can be any "well balanced chunk", - * i.e. the result of the content [43] production: - * http://www.w3.org/TR/REC-xml#NT-content. - * So it can contain text, CDATA section or nested - * entity reference nodes (among others). - * -> we recursive call xmlNodeListGetString() - * which handles these types */ - buffer = xmlNodeListGetString(doc, ent->children, 1); - if (buffer != NULL) { + /* an entity content can be any "well balanced chunk", + * i.e. the result of the content [43] production: + * http://www.w3.org/TR/REC-xml#NT-content. + * So it can contain text, CDATA section or nested + * entity reference nodes (among others). + * -> we recursive call xmlNodeListGetString() + * which handles these types */ + buffer = xmlNodeListGetString(doc, ent->children, 1); + if (buffer == NULL) + goto error; ret = xmlStrcat(ret, buffer); xmlFree(buffer); + if (ret == NULL) + goto error; } } else { ret = xmlStrcat(ret, node->content); + if (ret == NULL) + goto error; } } else { xmlChar buf[2]; @@ -1731,18 +1721,17 @@ xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine) buf[0] = ';'; buf[1] = 0; ret = xmlStrncat(ret, buf, 1); + if (ret == NULL) + goto error; } } -#if 0 - else { - xmlGenericError(xmlGenericErrorContext, - "xmlGetNodeListString : invalid node type %d\n", - node->type); - } -#endif node = node->next; } return (ret); + +error: + xmlFree(ret); + return(NULL); } #ifdef LIBXML_TREE_ENABLED @@ -1816,13 +1805,6 @@ xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine) ret = xmlStrncat(ret, buf, 1); } } -#if 0 - else { - xmlGenericError(xmlGenericErrorContext, - "xmlGetNodeListString : invalid node type %d\n", - node->type); - } -#endif node = node->next; } return (ret); @@ -1855,7 +1837,6 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, (node->doc->dict == NULL) || (!(xmlDictOwns(node->doc->dict, name))))) xmlFree((xmlChar *) name); - xmlTreeErrMemory("building attribute"); return (NULL); } memset(cur, 0, sizeof(xmlAttr)); @@ -1873,6 +1854,8 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1); else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; } else cur->name = name; @@ -1880,6 +1863,8 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, xmlNodePtr tmp; cur->children = xmlNewDocText(doc, value); + if (cur->children == NULL) + goto error; cur->last = NULL; tmp = cur->children; while (tmp != NULL) { @@ -1890,6 +1875,11 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, } } + if ((value != NULL) && (node != NULL) && + (xmlIsID(node->doc, node, cur) == 1) && + (xmlAddIDSafe(node->doc, value, cur, 0, NULL) < 0)) + goto error; + /* * Add it at the end to preserve parsing order ... */ @@ -1906,13 +1896,13 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns, } } - if ((value != NULL) && (node != NULL) && - (xmlIsID(node->doc, node, cur) == 1)) - xmlAddID(NULL, node->doc, value, cur); - if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr) cur); return (cur); + +error: + xmlFreeProp(cur); + return(NULL); } #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ @@ -2005,10 +1995,8 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { * Allocate a new property and fill the fields. */ cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr)); - if (cur == NULL) { - xmlTreeErrMemory("building attribute"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlAttr)); cur->type = XML_ATTRIBUTE_NODE; @@ -2016,6 +2004,8 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { cur->name = xmlDictLookup(doc->dict, name, -1); else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; cur->doc = doc; if (value != NULL) { xmlNodePtr tmp; @@ -2035,6 +2025,10 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeProp(cur); + return(NULL); } /** @@ -2139,25 +2133,31 @@ xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building PI"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_PI_NODE; + cur->doc = doc; if ((doc != NULL) && (doc->dict != NULL)) cur->name = xmlDictLookup(doc->dict, name, -1); else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; if (content != NULL) { cur->content = xmlStrdup(content); + if (cur->content == NULL) + goto error; } - cur->doc = doc; if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** @@ -2200,19 +2200,23 @@ xmlNewNode(xmlNsPtr ns, const xmlChar *name) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building node"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_ELEMENT_NODE; cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; cur->ns = ns; if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** @@ -2240,11 +2244,8 @@ xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building node"); - /* we can't check here that name comes from the doc dictionary */ + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_ELEMENT_NODE; @@ -2319,6 +2320,10 @@ xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns, cur->doc = doc; if (content != NULL) { cur->children = xmlStringGetNodeList(doc, content); + if (cur->children == NULL) { + xmlFreeNode(cur); + return(NULL); + } UPDATE_LAST_CHILD_AND_PARENT(cur) } } else { @@ -2375,10 +2380,8 @@ xmlNewDocFragment(xmlDocPtr doc) { * Allocate a new DocumentFragment node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building fragment"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_DOCUMENT_FRAG_NODE; @@ -2408,21 +2411,25 @@ xmlNewText(const xmlChar *content) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building text"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_TEXT_NODE; cur->name = xmlStringText; if (content != NULL) { cur->content = xmlStrdup(content); + if (cur->content == NULL) + goto error; } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } #ifdef LIBXML_TREE_ENABLED @@ -2518,10 +2525,8 @@ xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building character reference"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_ENTITY_REF_NODE; @@ -2536,10 +2541,16 @@ xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) { cur->name = xmlStrndup(name, len); } else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** @@ -2562,10 +2573,8 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building reference"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_ENTITY_REF_NODE; @@ -2580,6 +2589,8 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) { cur->name = xmlStrndup(name, len); } else cur->name = xmlStrdup(name); + if (cur->name == NULL) + goto error; ent = xmlGetDocEntity(doc, cur->name); if (ent != NULL) { @@ -2596,6 +2607,10 @@ xmlNewReference(const xmlDoc *doc, const xmlChar *name) { if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** @@ -2633,10 +2648,8 @@ xmlNewTextLen(const xmlChar *content, int len) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building text"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_TEXT_NODE; @@ -2686,21 +2699,25 @@ xmlNewComment(const xmlChar *content) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building comment"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_COMMENT_NODE; cur->name = xmlStringComment; if (content != NULL) { cur->content = xmlStrdup(content); + if (cur->content == NULL) + goto error; } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(cur); return(cur); + +error: + xmlFreeNode(cur); + return(NULL); } /** @@ -2720,16 +2737,18 @@ xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) { * Allocate a new node and fill the fields. */ cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlTreeErrMemory("building CDATA"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNode)); cur->type = XML_CDATA_SECTION_NODE; cur->doc = doc; if (content != NULL) { cur->content = xmlStrndup(content, len); + if (cur->content == NULL) { + xmlFree(cur); + return(NULL); + } } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) @@ -2794,6 +2813,7 @@ xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) { if (prop->doc != doc) { xmlDictPtr oldPropDict = prop->doc ? prop->doc->dict : NULL; + /* TODO: malloc check */ prop->name = _copyStringForNewDictIfNeeded(oldPropDict, newDict, prop->name); prop->doc = doc; } @@ -2826,6 +2846,7 @@ xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) { xmlSetListDoc(tree->children, doc); } + /* TODO: malloc check */ tree->name = _copyStringForNewDictIfNeeded(oldTreeDict, newDict, tree->name); tree->content = (xmlChar *)_copyStringForNewDictIfNeeded(oldTreeDict, NULL, tree->content); /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */ @@ -3020,6 +3041,7 @@ xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) { (cur->name == cur->next->name)) { xmlChar *tmp; + /* TODO: malloc check */ tmp = xmlStrdup(elem->content); tmp = xmlStrcat(tmp, cur->next->content); xmlNodeSetContent(cur->next, tmp); @@ -3082,6 +3104,7 @@ xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) { if (cur->type == XML_TEXT_NODE) { xmlChar *tmp; + /* TODO: malloc check */ tmp = xmlStrdup(elem->content); tmp = xmlStrcat(tmp, cur->content); xmlNodeSetContent(cur, tmp); @@ -3298,14 +3321,20 @@ xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { if ((parent->type == XML_TEXT_NODE) && (parent->content != NULL) && (parent->name == cur->name)) { - xmlNodeAddContent(parent, cur->content); + if (xmlNodeAddContent(parent, cur->content) != 0) { + xmlFreeNode(cur); + return(NULL); + } xmlFreeNode(cur); return(parent); } if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) && (parent->last->name == cur->name) && (parent->last != cur)) { - xmlNodeAddContent(parent->last, cur->content); + if (xmlNodeAddContent(parent->last, cur->content) != 0) { + xmlFreeNode(cur); + return(NULL); + } xmlFreeNode(cur); return(parent->last); } @@ -3331,7 +3360,10 @@ xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { if ((parent->type == XML_TEXT_NODE) && (parent->content != NULL) && (parent != cur)) { - xmlNodeAddContent(parent, cur->content); + if (xmlNodeAddContent(parent, cur->content) != 0) { + xmlFreeNode(cur); + return(NULL); + } xmlFreeNode(cur); return(parent); } @@ -3932,7 +3964,7 @@ xmlCopyNamespaceList(xmlNsPtr cur) { static xmlAttrPtr xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { - xmlAttrPtr ret; + xmlAttrPtr ret = NULL; if (cur == NULL) return(NULL); if ((target != NULL) && (target->type != XML_ELEMENT_NODE)) @@ -3974,6 +4006,8 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { root = pred; } ret->ns = xmlNewNs(root, ns->href, ns->prefix); + if (ret->ns == NULL) + goto error; } } else { /* @@ -3990,6 +4024,8 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { * This is expensive */ ret->ns = xmlNewReconciledNs(target->doc, target, cur->ns); + if (ret->ns == NULL) + goto error; } } @@ -4000,6 +4036,8 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { xmlNodePtr tmp; ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret); + if (ret->children == NULL) + goto error; ret->last = NULL; tmp = ret->children; while (tmp != NULL) { @@ -4012,20 +4050,32 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { /* * Try to handle IDs */ - if ((target!= NULL) && (cur!= NULL) && + if ((target != NULL) && (cur != NULL) && (target->doc != NULL) && (cur->doc != NULL) && - (cur->doc->ids != NULL) && (cur->parent != NULL)) { - if (xmlIsID(cur->doc, cur->parent, cur)) { + (cur->doc->ids != NULL) && + (cur->parent != NULL) && + (cur->children != NULL)) { + int res = xmlIsID(cur->doc, cur->parent, cur); + + if (res < 0) + goto error; + if (res != 0) { xmlChar *id; id = xmlNodeListGetString(cur->doc, cur->children, 1); - if (id != NULL) { - xmlAddID(NULL, target->doc, id, ret); - xmlFree(id); - } + if (id == NULL) + goto error; + res = xmlAddIDSafe(target->doc, id, ret, 0, NULL); + xmlFree(id); + if (res < 0) + goto error; } } return(ret); + +error: + xmlFreeProp(ret); + return(NULL); } /** @@ -4136,10 +4186,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, * Allocate a new node and fill the fields. */ ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (ret == NULL) { - xmlTreeErrMemory("copying node"); + if (ret == NULL) return(NULL); - } memset(ret, 0, sizeof(xmlNode)); ret->type = node->type; @@ -4156,6 +4204,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, ret->name = xmlDictLookup(doc->dict, node->name, -1); else ret->name = xmlStrdup(node->name); + if (ret->name == NULL) + goto error; } if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL) && @@ -4163,6 +4213,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, (node->type != XML_XINCLUDE_END) && (node->type != XML_XINCLUDE_START)) { ret->content = xmlStrdup(node->content); + if (ret->content == NULL) + goto error; }else{ if (node->type == XML_ELEMENT_NODE) ret->line = node->line; @@ -4195,10 +4247,13 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, if (!extended) goto out; if (((node->type == XML_ELEMENT_NODE) || - (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL)) + (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL)) { ret->nsDef = xmlCopyNamespaceList(node->nsDef); + if (ret->nsDef == NULL) + goto error; + } - if (node->ns != NULL) { + if ((node->type == XML_ELEMENT_NODE) && (node->ns != NULL)) { xmlNsPtr ns; ns = xmlSearchNs(doc, ret, node->ns->prefix); @@ -4220,6 +4275,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, } else { ret->ns = xmlNewReconciledNs(doc, ret, node->ns); } + if (ret->ns == NULL) + goto error; } else { /* * reference the existing namespace definition in our own tree. @@ -4227,9 +4284,11 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, ret->ns = ns; } } - if (((node->type == XML_ELEMENT_NODE) || - (node->type == XML_XINCLUDE_START)) && (node->properties != NULL)) + if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL)) { ret->properties = xmlCopyPropList(ret, node->properties); + if (ret->properties == NULL) + goto error; + } if (node->type == XML_ENTITY_REF_NODE) { if ((doc == NULL) || (node->doc != doc)) { /* @@ -4250,10 +4309,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, insert = ret; while (cur != NULL) { xmlNodePtr copy = xmlStaticCopyNode(cur, doc, insert, 2); - if (copy == NULL) { - xmlFreeNode(ret); - return(NULL); - } + if (copy == NULL) + goto error; /* Check for coalesced text nodes */ if (insert->last != copy) { @@ -4295,6 +4352,10 @@ out: ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))) xmlRegisterNodeDefaultValue((xmlNodePtr)ret); return(ret); + +error: + xmlFreeNode(ret); + return(NULL); } xmlNodePtr @@ -4342,9 +4403,11 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { doc->intSubset = newSubset; return(ret); error: - if (linkedSubset != 0) - xmlUnlinkNode((xmlNodePtr) doc->intSubset); xmlFreeNodeList(ret); + if (linkedSubset != 0) { + doc->intSubset->next = NULL; + doc->intSubset->prev = NULL; + } return(NULL); } @@ -4432,21 +4495,36 @@ xmlCopyDtd(xmlDtdPtr dtd) { if (dtd == NULL) return(NULL); ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID); if (ret == NULL) return(NULL); - if (dtd->entities != NULL) + if (dtd->entities != NULL) { ret->entities = (void *) xmlCopyEntitiesTable( (xmlEntitiesTablePtr) dtd->entities); - if (dtd->notations != NULL) + if (ret->entities == NULL) + goto error; + } + if (dtd->notations != NULL) { ret->notations = (void *) xmlCopyNotationTable( (xmlNotationTablePtr) dtd->notations); - if (dtd->elements != NULL) + if (ret->notations == NULL) + goto error; + } + if (dtd->elements != NULL) { ret->elements = (void *) xmlCopyElementTable( (xmlElementTablePtr) dtd->elements); - if (dtd->attributes != NULL) + if (ret->elements == NULL) + goto error; + } + if (dtd->attributes != NULL) { ret->attributes = (void *) xmlCopyAttributeTable( (xmlAttributeTablePtr) dtd->attributes); - if (dtd->pentities != NULL) + if (ret->attributes == NULL) + goto error; + } + if (dtd->pentities != NULL) { ret->pentities = (void *) xmlCopyEntitiesTable( (xmlEntitiesTablePtr) dtd->pentities); + if (ret->pentities == NULL) + goto error; + } cur = dtd->children; while (cur != NULL) { @@ -4478,6 +4556,8 @@ xmlCopyDtd(xmlDtdPtr dtd) { xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix); } else if (cur->type == XML_COMMENT_NODE) { q = xmlCopyNode(cur, 0); + if (q == NULL) + goto error; } if (q == NULL) { @@ -4499,6 +4579,10 @@ xmlCopyDtd(xmlDtdPtr dtd) { } return(ret); + +error: + xmlFreeDtd(ret); + return(NULL); } #endif @@ -4521,12 +4605,21 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) { ret = xmlNewDoc(doc->version); if (ret == NULL) return(NULL); ret->type = doc->type; - if (doc->name != NULL) + if (doc->name != NULL) { ret->name = xmlMemStrdup(doc->name); - if (doc->encoding != NULL) + if (ret->name == NULL) + goto error; + } + if (doc->encoding != NULL) { ret->encoding = xmlStrdup(doc->encoding); - if (doc->URL != NULL) + if (ret->encoding == NULL) + goto error; + } + if (doc->URL != NULL) { ret->URL = xmlStrdup(doc->URL); + if (ret->URL == NULL) + goto error; + } ret->charset = doc->charset; ret->compression = doc->compression; ret->standalone = doc->standalone; @@ -4537,21 +4630,24 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) { #ifdef LIBXML_TREE_ENABLED if (doc->intSubset != NULL) { ret->intSubset = xmlCopyDtd(doc->intSubset); - if (ret->intSubset == NULL) { - xmlFreeDoc(ret); - return(NULL); - } + if (ret->intSubset == NULL) + goto error; xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret); ret->intSubset->parent = ret; } #endif - if (doc->oldNs != NULL) + if (doc->oldNs != NULL) { ret->oldNs = xmlCopyNamespaceList(doc->oldNs); + if (ret->oldNs == NULL) + goto error; + } if (doc->children != NULL) { xmlNodePtr tmp; ret->children = xmlStaticCopyNodeList(doc->children, ret, (xmlNodePtr)ret); + if (ret->children == NULL) + goto error; ret->last = NULL; tmp = ret->children; while (tmp != NULL) { @@ -4561,6 +4657,10 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) { } } return(ret); + +error: + xmlFreeDoc(ret); + return(NULL); } #endif /* LIBXML_TREE_ENABLED */ @@ -4663,13 +4763,10 @@ xmlGetNodePath(const xmlNode *node) buf_len = 500; buffer = (xmlChar *) xmlMallocAtomic(buf_len); - if (buffer == NULL) { - xmlTreeErrMemory("getting node path"); + if (buffer == NULL) return (NULL); - } buf = (xmlChar *) xmlMallocAtomic(buf_len); if (buf == NULL) { - xmlTreeErrMemory("getting node path"); xmlFree(buffer); return (NULL); } @@ -4856,7 +4953,6 @@ xmlGetNodePath(const xmlNode *node) 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20; temp = (xmlChar *) xmlRealloc(buffer, buf_len); if (temp == NULL) { - xmlTreeErrMemory("getting node path"); xmlFree(buf); xmlFree(buffer); return (NULL); @@ -4864,7 +4960,6 @@ xmlGetNodePath(const xmlNode *node) buffer = temp; temp = (xmlChar *) xmlRealloc(buf, buf_len); if (temp == NULL) { - xmlTreeErrMemory("getting node path"); xmlFree(buf); xmlFree(buffer); return (NULL); @@ -5152,6 +5247,7 @@ xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) { dict = doc->dict; else dict = NULL; + /* TODO: malloc check */ if (dict != NULL) { if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name))) freeme = cur->name; @@ -5175,13 +5271,16 @@ xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) { * * Set (or reset) the base URI of a node, i.e. the value of the * xml:base attribute. + * + * Returns 0 on success, -1 on error. */ -void +int xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { xmlNsPtr ns; xmlChar* fixed; - if (cur == NULL) return; + if (cur == NULL) + return(-1); switch(cur->type) { case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: @@ -5199,7 +5298,7 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { case XML_NAMESPACE_DECL: case XML_XINCLUDE_START: case XML_XINCLUDE_END: - return; + return(-1); case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: break; @@ -5209,24 +5308,30 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { if (doc->URL != NULL) xmlFree((xmlChar *) doc->URL); - if (uri == NULL) + if (uri == NULL) { doc->URL = NULL; - else + } else { doc->URL = xmlPathToURI(uri); - return; + if (doc->URL == NULL) + return(-1); + } + return(0); } } ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); if (ns == NULL) - return; + return(-1); fixed = xmlPathToURI(uri); - if (fixed != NULL) { - xmlSetNsProp(cur, ns, BAD_CAST "base", fixed); - xmlFree(fixed); - } else { - xmlSetNsProp(cur, ns, BAD_CAST "base", uri); + if (fixed == NULL) + return(-1); + if (xmlSetNsProp(cur, ns, BAD_CAST "base", fixed) == NULL) { + xmlFree(fixed); + return(-1); } + xmlFree(fixed); + + return(0); } #endif /* LIBXML_TREE_ENABLED */ @@ -5234,6 +5339,7 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { * xmlNodeGetBase: * @doc: the document the node pertains to * @cur: the node being checked + * @baseOut: pointer to base * * Searches for the BASE URL. The code should work on both XML * and HTML document even if base mechanisms are completely different. @@ -5244,19 +5350,25 @@ xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { * However it does not return the document base (5.1.3), use * doc->URL in this case * - * Returns a pointer to the base URL, or NULL if not found - * It's up to the caller to free the memory with xmlFree(). + * Return 0 in case of success, 1 if a URI or argument is invalid, -1 if a + * memory allocation failed. */ -xmlChar * -xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) { - xmlChar *oldbase = NULL; +int +xmlNodeGetBaseSafe(const xmlDoc *doc, const xmlNode *cur, xmlChar **baseOut) { + xmlChar *ret = NULL; xmlChar *base, *newbase; + int res; + if (baseOut == NULL) + return(1); + *baseOut = NULL; if ((cur == NULL) && (doc == NULL)) - return(NULL); + return(1); if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL)) - return(NULL); - if (doc == NULL) doc = cur->doc; + return(1); + if (doc == NULL) + doc = cur->doc; + if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { cur = doc->children; while ((cur != NULL) && (cur->name != NULL)) { @@ -5273,50 +5385,87 @@ xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) { continue; } if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) { - return(xmlGetProp(cur, BAD_CAST "href")); + if (xmlNodeGetAttrValue(cur, BAD_CAST "href", NULL, &ret) < 0) + return(-1); + if (ret == NULL) + return(1); + goto found; } cur = cur->next; } - return(NULL); + return(0); } + while (cur != NULL) { if (cur->type == XML_ENTITY_DECL) { xmlEntityPtr ent = (xmlEntityPtr) cur; - return(xmlStrdup(ent->URI)); + + xmlFree(ret); + ret = xmlStrdup(ent->URI); + if (ret == NULL) + return(-1); + goto found; } if (cur->type == XML_ELEMENT_NODE) { - base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); + if (xmlNodeGetAttrValue(cur, BAD_CAST "base", XML_XML_NAMESPACE, + &base) < 0) + return(-1); if (base != NULL) { - if (oldbase != NULL) { - newbase = xmlBuildURI(oldbase, base); - if (newbase != NULL) { - xmlFree(oldbase); - xmlFree(base); - oldbase = newbase; - } else { - xmlFree(oldbase); - xmlFree(base); - return(NULL); - } + if (ret != NULL) { + res = xmlBuildURISafe(ret, base, &newbase); + xmlFree(ret); + xmlFree(base); + if (res != 0) + return(res); + ret = newbase; } else { - oldbase = base; + ret = base; } - if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) || - (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) || - (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4))) - return(oldbase); + if ((!xmlStrncmp(ret, BAD_CAST "http://", 7)) || + (!xmlStrncmp(ret, BAD_CAST "ftp://", 6)) || + (!xmlStrncmp(ret, BAD_CAST "urn:", 4))) + goto found; } } cur = cur->parent; } + if ((doc != NULL) && (doc->URL != NULL)) { - if (oldbase == NULL) - return(xmlStrdup(doc->URL)); - newbase = xmlBuildURI(oldbase, doc->URL); - xmlFree(oldbase); - return(newbase); + if (ret == NULL) { + ret = xmlStrdup(doc->URL); + if (ret == NULL) + return(-1); + } else { + res = xmlBuildURISafe(ret, doc->URL, &newbase); + xmlFree(ret); + if (res != 0) + return(res); + ret = newbase; + } } - return(oldbase); + +found: + *baseOut = ret; + return(0); +} + +/** + * xmlNodeGetBase: + * @doc: the document the node pertains to + * @cur: the node being checked + * + * See xmlNodeGetBaseSafe. This function doesn't allow to distinguish + * memory allocation failures from a non-existing base. + * + * Returns a pointer to the base URL, or NULL if not found + * It's up to the caller to free the memory with xmlFree(). + */ +xmlChar * +xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) { + xmlChar *base; + + xmlNodeGetBaseSafe(doc, cur, &base); + return(base); } /** @@ -5524,6 +5673,8 @@ xmlNodeGetContent(const xmlNode *cur) case XML_PI_NODE: if (cur->content != NULL) return (xmlStrdup(cur->content)); + else + return (xmlStrdup(BAD_CAST "")); return (NULL); case XML_ENTITY_REF_NODE:{ xmlEntityPtr ent; @@ -5602,40 +5753,58 @@ xmlNodeGetContent(const xmlNode *cur) * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity * references, but XML special chars need to be escaped first by using * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars(). + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -void +int xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { if (cur == NULL) { - return; + return(1); } switch (cur->type) { case XML_DOCUMENT_FRAG_NODE: case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = xmlStringGetNodeList(cur->doc, content); + case XML_ATTRIBUTE_NODE: { + xmlNodePtr list = NULL; + + if (content != NULL) { + list = xmlStringGetNodeList(cur->doc, content); + if (list == NULL) + return(-1); + } + + if (cur->children != NULL) + xmlFreeNodeList(cur->children); + cur->children = list; UPDATE_LAST_CHILD_AND_PARENT(cur) break; + } case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_ENTITY_REF_NODE: case XML_ENTITY_NODE: case XML_PI_NODE: - case XML_COMMENT_NODE: + case XML_COMMENT_NODE: { + xmlChar *copy = NULL; + + if (content != NULL) { + copy = xmlStrdup(content); + if (copy == NULL) + return(-1); + } + if ((cur->content != NULL) && (cur->content != (xmlChar *) &(cur->properties))) { if (!((cur->doc != NULL) && (cur->doc->dict != NULL) && (xmlDictOwns(cur->doc->dict, cur->content)))) xmlFree(cur->content); } - if (cur->children != NULL) xmlFreeNodeList(cur->children); + if (cur->children != NULL) + xmlFreeNodeList(cur->children); cur->last = cur->children = NULL; - if (content != NULL) { - cur->content = xmlStrdup(content); - } else - cur->content = NULL; - cur->properties = NULL; + cur->content = copy; break; + } case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: case XML_DOCUMENT_TYPE_NODE: @@ -5658,6 +5827,8 @@ xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { /* TODO !!! */ break; } + + return(0); } #ifdef LIBXML_TREE_ENABLED @@ -5671,41 +5842,60 @@ xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity * references, but XML special chars need to be escaped first by using * xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars(). + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -void +int xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { if (cur == NULL) { - return; + return(1); } switch (cur->type) { case XML_DOCUMENT_FRAG_NODE: case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = xmlStringLenGetNodeList(cur->doc, content, len); + case XML_ATTRIBUTE_NODE: { + xmlNodePtr list = NULL; + + if (content != NULL) { + list = xmlStringLenGetNodeList(cur->doc, content, len); + if (list == NULL) + return(-1); + } + + if (cur->children != NULL) + xmlFreeNodeList(cur->children); + cur->children = list; UPDATE_LAST_CHILD_AND_PARENT(cur) break; + } case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_ENTITY_REF_NODE: case XML_ENTITY_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: - case XML_NOTATION_NODE: + case XML_NOTATION_NODE: { + xmlChar *copy = NULL; + + if (content != NULL) { + copy = xmlStrndup(content, len); + if (copy == NULL) + return(-1); + } + if ((cur->content != NULL) && (cur->content != (xmlChar *) &(cur->properties))) { if (!((cur->doc != NULL) && (cur->doc->dict != NULL) && (xmlDictOwns(cur->doc->dict, cur->content)))) xmlFree(cur->content); } - if (cur->children != NULL) xmlFreeNodeList(cur->children); + if (cur->children != NULL) + xmlFreeNodeList(cur->children); cur->children = cur->last = NULL; - if (content != NULL) { - cur->content = xmlStrndup(content, len); - } else - cur->content = NULL; + cur->content = copy; cur->properties = NULL; break; + } case XML_DOCUMENT_NODE: case XML_DTD_NODE: case XML_HTML_DOCUMENT_NODE: @@ -5724,6 +5914,8 @@ xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { /* TODO !!! */ break; } + + return(0); } #endif /* LIBXML_TREE_ENABLED */ @@ -5737,28 +5929,27 @@ xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be * raw text, so unescaped XML special chars are allowed, entity * references are not supported. + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -void +int xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { - if (cur == NULL) { - return; - } - if (len <= 0) return; + if (cur == NULL) + return(1); + if ((content == NULL) || (len <= 0)) + return(0); + switch (cur->type) { case XML_DOCUMENT_FRAG_NODE: case XML_ELEMENT_NODE: { - xmlNodePtr last, newNode, tmp; + xmlNodePtr newNode, tmp; - last = cur->last; newNode = xmlNewDocTextLen(cur->doc, content, len); - if (newNode != NULL) { - tmp = xmlAddChild(cur, newNode); - if (tmp != newNode) - return; - if ((last != NULL) && (last->next == newNode)) { - xmlTextMerge(last, newNode); - } - } + if (newNode == NULL) + return(-1); + tmp = xmlAddChild(cur, newNode); + if (tmp == NULL) + return(-1); break; } case XML_ATTRIBUTE_NODE: @@ -5769,18 +5960,25 @@ xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { case XML_ENTITY_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: - case XML_NOTATION_NODE: - if (content != NULL) { - if ((cur->content == (xmlChar *) &(cur->properties)) || - ((cur->doc != NULL) && (cur->doc->dict != NULL) && - xmlDictOwns(cur->doc->dict, cur->content))) { - cur->content = xmlStrncatNew(cur->content, content, len); - cur->properties = NULL; - } else { - cur->content = xmlStrncat(cur->content, content, len); - } + case XML_NOTATION_NODE: { + xmlChar *newContent = NULL; + + if ((cur->content == (xmlChar *) &(cur->properties)) || + ((cur->doc != NULL) && (cur->doc->dict != NULL) && + xmlDictOwns(cur->doc->dict, cur->content))) { + newContent = xmlStrncatNew(cur->content, content, len); + if (newContent == NULL) + return(-1); + cur->properties = NULL; + } else { + newContent = xmlStrncatNew(cur->content, content, len); + if (newContent == NULL) + return(-1); + xmlFree(cur->content); } + cur->content = newContent; break; + } case XML_DOCUMENT_NODE: case XML_DTD_NODE: case XML_HTML_DOCUMENT_NODE: @@ -5794,6 +5992,8 @@ xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { case XML_ENTITY_DECL: break; } + + return(0); } /** @@ -5805,17 +6005,12 @@ xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be * raw text, so unescaped XML special chars are allowed, entity * references are not supported. + * + * Returns 0 on success, 1 on error, -1 if a memory allocation failed. */ -void +int xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) { - int len; - - if (cur == NULL) { - return; - } - if (content == NULL) return; - len = xmlStrlen(content); - xmlNodeAddContentLen(cur, content, len); + return(xmlNodeAddContentLen(cur, content, xmlStrlen(content))); } /** @@ -5845,31 +6040,38 @@ xmlTextMerge(xmlNodePtr first, xmlNodePtr second) { * xmlGetNsList: * @doc: the document * @node: the current node + * @out: the returned namespace array * - * Search all the namespace applying to a given element. - * Returns an NULL terminated array of all the #xmlNsPtr found - * that need to be freed by the caller or NULL if no - * namespace if defined + * Search all the namespace applying to a given element. @out returns + * a NULL terminated array of all the namespaces found that needs to be + * freed by the caller allocation failed. + * + * Returns 0 on success, 1 if no namespace were found, -1 if a memory + * allocation failed. */ -xmlNsPtr * -xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node) +int +xmlGetNsListSafe(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node, + xmlNsPtr **out) { xmlNsPtr cur; - xmlNsPtr *ret = NULL; + xmlNsPtr *namespaces = NULL; int nbns = 0; int maxns = 0; int i; + if (out == NULL) + return(1); + *out = NULL; if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) - return(NULL); + return(1); while (node != NULL) { if (node->type == XML_ELEMENT_NODE) { cur = node->nsDef; while (cur != NULL) { for (i = 0; i < nbns; i++) { - if ((cur->prefix == ret[i]->prefix) || - (xmlStrEqual(cur->prefix, ret[i]->prefix))) + if ((cur->prefix == namespaces[i]->prefix) || + (xmlStrEqual(cur->prefix, namespaces[i]->prefix))) break; } if (i >= nbns) { @@ -5877,18 +6079,17 @@ xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node) xmlNsPtr *tmp; maxns = maxns ? maxns * 2 : 10; - tmp = (xmlNsPtr *) xmlRealloc(ret, + tmp = (xmlNsPtr *) xmlRealloc(namespaces, (maxns + 1) * sizeof(xmlNsPtr)); if (tmp == NULL) { - xmlTreeErrMemory("getting namespace list"); - xmlFree(ret); - return (NULL); + xmlFree(namespaces); + return(-1); } - ret = tmp; + namespaces = tmp; } - ret[nbns++] = cur; - ret[nbns] = NULL; + namespaces[nbns++] = cur; + namespaces[nbns] = NULL; } cur = cur->next; @@ -5896,7 +6097,28 @@ xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node) } node = node->parent; } - return (ret); + + *out = namespaces; + return((namespaces == NULL) ? 1 : 0); +} + +/** + * xmlGetNsList: + * @doc: the document + * @node: the current node + * + * Search all the namespace applying to a given element. + * Returns an NULL terminated array of all the #xmlNsPtr found + * that need to be freed by the caller or NULL if a memory + * allocation failed + */ +xmlNsPtr * +xmlGetNsList(const xmlDoc *doc, const xmlNode *node) +{ + xmlNsPtr *ret; + + xmlGetNsListSafe(doc, node, &ret); + return(ret); } #endif /* LIBXML_TREE_ENABLED */ @@ -5906,9 +6128,9 @@ xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node) * * Ensures that there is an XML namespace declaration on the doc. * -* Returns the XML ns-struct or NULL on API and internal errors. +* Returns the XML ns-struct or NULL if a memory allocation failed. */ -static xmlNsPtr +xmlNsPtr xmlTreeEnsureXMLDecl(xmlDocPtr doc) { if (doc == NULL) @@ -5918,15 +6140,20 @@ xmlTreeEnsureXMLDecl(xmlDocPtr doc) { xmlNsPtr ns; ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (ns == NULL) { - xmlTreeErrMemory( - "allocating the XML namespace"); - return (NULL); - } + if (ns == NULL) + return(NULL); memset(ns, 0, sizeof(xmlNs)); ns->type = XML_LOCAL_NAMESPACE; ns->href = xmlStrdup(XML_XML_NAMESPACE); + if (ns->href == NULL) { + xmlFreeNs(ns); + return(NULL); + } ns->prefix = xmlStrdup((const xmlChar *)"xml"); + if (ns->prefix == NULL) { + xmlFreeNs(ns); + return(NULL); + } doc->oldNs = ns; return (ns); } @@ -5946,7 +6173,10 @@ xmlTreeEnsureXMLDecl(xmlDocPtr doc) * the namespace within those you will be in troubles !!! A warning * is generated to cover this case. * - * Returns the namespace pointer or NULL. + * Returns the namespace pointer or NULL if no namespace was found or + * a memory allocation failed. Allocations can only fail if the "xml" + * namespace is queried and xmlTreeEnsureXMLDecl wasn't called + * successfully or doc is NULL. */ xmlNsPtr xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { @@ -5964,10 +6194,8 @@ xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { * node element. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlTreeErrMemory("searching namespace"); + if (cur == NULL) return(NULL); - } memset(cur, 0, sizeof(xmlNs)); cur->type = XML_LOCAL_NAMESPACE; cur->href = xmlStrdup(XML_XML_NAMESPACE); @@ -6075,7 +6303,11 @@ xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node, * * Search a Ns aliasing a given URI. Recurse on the parents until it finds * the defined namespace or return NULL otherwise. - * Returns the namespace pointer or NULL. + * + * Returns the namespace pointer or NULL if no namespace was found or + * a memory allocation failed. Allocations can only fail if the "xml" + * namespace is queried and xmlTreeEnsureXMLDecl wasn't called + * successfully or doc is NULL. */ xmlNsPtr xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href) @@ -6097,10 +6329,8 @@ xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href) * node element. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlTreeErrMemory("searching namespace"); + if (cur == NULL) return (NULL); - } memset(cur, 0, sizeof(xmlNs)); cur->type = XML_LOCAL_NAMESPACE; cur->href = xmlStrdup(XML_XML_NAMESPACE); @@ -6257,14 +6487,11 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { sizeCache = 10; oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); + if (oldNs == NULL) return(-1); - } newNs = (xmlNsPtr *) xmlMalloc(sizeCache * sizeof(xmlNsPtr)); if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); xmlFree(oldNs); return(-1); } @@ -6289,14 +6516,12 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache * sizeof(xmlNsPtr)); if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); xmlFree(newNs); return(-1); } newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache * sizeof(xmlNsPtr)); if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); xmlFree(oldNs); return(-1); } @@ -6321,14 +6546,11 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { sizeCache = 10; oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); + if (oldNs == NULL) return(-1); - } newNs = (xmlNsPtr *) xmlMalloc(sizeCache * sizeof(xmlNsPtr)); if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); xmlFree(oldNs); return(-1); } @@ -6353,14 +6575,12 @@ xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache * sizeof(xmlNsPtr)); if (oldNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); xmlFree(newNs); return(-1); } newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache * sizeof(xmlNsPtr)); if (newNs == NULL) { - xmlTreeErrMemory("fixing namespaces"); xmlFree(oldNs); return(-1); } @@ -6547,7 +6767,6 @@ xmlGetPropNodeValueInternal(const xmlAttr *prop) if (prop->type == XML_ATTRIBUTE_NODE) { /* * Note that we return at least the empty string. - * TODO: Do we really always want that? */ if (prop->children != NULL) { if ((prop->children->next == NULL) && @@ -6559,11 +6778,7 @@ xmlGetPropNodeValueInternal(const xmlAttr *prop) */ return(xmlStrdup(prop->children->content)); } else { - xmlChar *ret; - - ret = xmlNodeListGetString(prop->doc, prop->children, 1); - if (ret != NULL) - return(ret); + return(xmlNodeListGetString(prop->doc, prop->children, 1)); } } return(xmlStrdup((xmlChar *)"")); @@ -6602,7 +6817,6 @@ xmlHasProp(const xmlNode *node, const xmlChar *name) { } prop = prop->next; } - if (!xmlCheckDTD) return(NULL); /* * Check if there is a default declaration in the internal @@ -6643,7 +6857,41 @@ xmlHasProp(const xmlNode *node, const xmlChar *name) { xmlAttrPtr xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) { - return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD)); + return(xmlGetPropNodeInternal(node, name, nameSpace, 1)); +} + +/** + * xmlNodeGetAttrValue: + * @node: the node + * @name: the attribute name + * @nsUri: the URI of the namespace + * @out: the returned string + * + * Search and get the value of an attribute associated to a node + * This attribute has to be anchored in the namespace specified. + * This does the entity substitution. The returned value must be + * freed by the caller. + * + * Returns 0 on success, 1 if no attribute was found, -1 if a + * memory allocation failed. + */ +int +xmlNodeGetAttrValue(const xmlNode *node, const xmlChar *name, + const xmlChar *nsUri, xmlChar **out) { + xmlAttrPtr prop; + + if (out == NULL) + return(1); + *out = NULL; + + prop = xmlGetPropNodeInternal(node, name, nsUri, 0); + if (prop == NULL) + return(1); + + *out = xmlGetPropNodeValueInternal(prop); + if (*out == NULL) + return(-1); + return(0); } /** @@ -6654,13 +6902,17 @@ xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) * Search and get the value of an attribute associated to a node * This does the entity substitution. * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. - * NOTE: this function acts independently of namespaces associated + * default declaration values. + * + * NOTE: This function acts independently of namespaces associated * to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp() * for namespace aware processing. * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). + * NOTE: This function doesn't allow to distinguish malloc failures from + * missing attributes. It's more robust to use xmlNodeGetAttrValue. + * + * Returns the attribute value or NULL if not found or a memory allocation + * failed. It's up to the caller to free the memory with xmlFree(). */ xmlChar * xmlGetProp(const xmlNode *node, const xmlChar *name) { @@ -6680,18 +6932,21 @@ xmlGetProp(const xmlNode *node, const xmlChar *name) { * Search and get the value of an attribute associated to a node * This does the entity substitution. * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. + * default declaration values. * This function is similar to xmlGetProp except it will accept only * an attribute in no namespace. * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). + * NOTE: This function doesn't allow to distinguish malloc failures from + * missing attributes. It's more robust to use xmlNodeGetAttrValue. + * + * Returns the attribute value or NULL if not found or a memory allocation + * failed. It's up to the caller to free the memory with xmlFree(). */ xmlChar * xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) { xmlAttrPtr prop; - prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD); + prop = xmlGetPropNodeInternal(node, name, NULL, 1); if (prop == NULL) return(NULL); return(xmlGetPropNodeValueInternal(prop)); @@ -6707,16 +6962,19 @@ xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) { * This attribute has to be anchored in the namespace specified. * This does the entity substitution. * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. + * default declaration values. * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). + * NOTE: This function doesn't allow to distinguish malloc failures from + * missing attributes. It's more robust to use xmlNodeGetAttrValue. + * + * Returns the attribute value or NULL if not found or a memory allocation + * failed. It's up to the caller to free the memory with xmlFree(). */ xmlChar * xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) { xmlAttrPtr prop; - prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD); + prop = xmlGetPropNodeInternal(node, name, nameSpace, 1); if (prop == NULL) return(NULL); return(xmlGetPropNodeValueInternal(prop)); @@ -6757,7 +7015,8 @@ int xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) { xmlAttrPtr prop; - prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0); + prop = xmlGetPropNodeInternal(node, name, + (ns != NULL) ? ns->href : NULL, 0); if (prop == NULL) return(-1); xmlUnlinkNode((xmlNodePtr) prop); @@ -6825,11 +7084,20 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, if (ns && (ns->href == NULL)) return(NULL); - prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0); + prop = xmlGetPropNodeInternal(node, name, + (ns != NULL) ? ns->href : NULL, 0); if (prop != NULL) { + xmlNodePtr children = NULL; + /* * Modify the attribute's value. */ + if (value != NULL) { + children = xmlNewDocText(node->doc, value); + if (children == NULL) + return(NULL); + } + if (prop->atype == XML_ATTRIBUTE_ID) { xmlRemoveID(node->doc, prop); prop->atype = XML_ATTRIBUTE_ID; @@ -6842,7 +7110,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, if (value != NULL) { xmlNodePtr tmp; - prop->children = xmlNewDocText(node->doc, value); + prop->children = children; prop->last = NULL; tmp = prop->children; while (tmp != NULL) { @@ -6852,8 +7120,10 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, tmp = tmp->next; } } - if (prop->atype == XML_ATTRIBUTE_ID) - xmlAddID(NULL, node->doc, value, prop); + if ((prop->atype == XML_ATTRIBUTE_ID) && + (xmlAddIDSafe(node->doc, value, prop, 0, NULL) < 0)) { + return(NULL); + } return(prop); } /* @@ -6958,16 +7228,13 @@ xmlBufferCreate(void) { xmlBufferPtr ret; ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); - if (ret == NULL) { - xmlTreeErrMemory("creating buffer"); + if (ret == NULL) return(NULL); - } ret->use = 0; ret->size = xmlDefaultBufferSize; ret->alloc = xmlBufferAllocScheme; ret->content = (xmlChar *) xmlMallocAtomic(ret->size); if (ret->content == NULL) { - xmlTreeErrMemory("creating buffer"); xmlFree(ret); return(NULL); } @@ -6990,17 +7257,14 @@ xmlBufferCreateSize(size_t size) { if (size >= UINT_MAX) return(NULL); ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); - if (ret == NULL) { - xmlTreeErrMemory("creating buffer"); + if (ret == NULL) return(NULL); - } ret->use = 0; ret->alloc = xmlBufferAllocScheme; ret->size = (size ? size + 1 : 0); /* +1 for ending null */ if (ret->size){ ret->content = (xmlChar *) xmlMallocAtomic(ret->size); if (ret->content == NULL) { - xmlTreeErrMemory("creating buffer"); xmlFree(ret); return(NULL); } @@ -7178,10 +7442,8 @@ xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { if (len < buf->size - buf->use) return(0); - if (len >= UINT_MAX - buf->use) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if (len >= UINT_MAX - buf->use) return(-1); - } if (buf->size > (size_t) len) { size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2; @@ -7194,18 +7456,14 @@ xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { size_t start_buf = buf->content - buf->contentIO; newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size); - if (newbuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (newbuf == NULL) return(-1); - } buf->contentIO = newbuf; buf->content = newbuf + start_buf; } else { newbuf = (xmlChar *) xmlRealloc(buf->content, size); - if (newbuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (newbuf == NULL) return(-1); - } buf->content = newbuf; } buf->size = size; @@ -7295,10 +7553,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) if (size < buf->size) return 1; - if (size > UINT_MAX - 10) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if (size > UINT_MAX - 10) return 0; - } /* figure out new size */ switch (buf->alloc){ @@ -7310,10 +7566,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) else newSize = buf->size; while (size > newSize) { - if (newSize > UINT_MAX / 2) { - xmlTreeErrMemory("growing buffer"); + if (newSize > UINT_MAX / 2) return 0; - } newSize *= 2; } break; @@ -7326,10 +7580,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) else { newSize = buf->size; while (size > newSize) { - if (newSize > UINT_MAX / 2) { - xmlTreeErrMemory("growing buffer"); + if (newSize > UINT_MAX / 2) return 0; - } newSize *= 2; } } @@ -7351,10 +7603,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) buf->size += start_buf; } else { rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize); - if (rebuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (rebuf == NULL) return 0; - } buf->contentIO = rebuf; buf->content = rebuf + start_buf; } @@ -7378,10 +7628,8 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) rebuf[buf->use] = 0; } } - if (rebuf == NULL) { - xmlTreeErrMemory("growing buffer"); + if (rebuf == NULL) return 0; - } buf->content = rebuf; } buf->size = newSize; @@ -7421,15 +7669,11 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { /* Note that both buf->size and buf->use can be zero here. */ if ((unsigned) len >= buf->size - buf->use) { - if ((unsigned) len >= UINT_MAX - buf->use) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if ((unsigned) len >= UINT_MAX - buf->use) return XML_ERR_NO_MEMORY; - } needSize = buf->use + len + 1; - if (!xmlBufferResize(buf, needSize)){ - xmlTreeErrMemory("growing buffer"); + if (!xmlBufferResize(buf, needSize)) return XML_ERR_NO_MEMORY; - } } memmove(&buf->content[buf->use], str, len); @@ -7486,15 +7730,11 @@ xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) { } /* Note that both buf->size and buf->use can be zero here. */ if ((unsigned) len >= buf->size - buf->use) { - if ((unsigned) len >= UINT_MAX - buf->use) { - xmlTreeErrMemory("growing buffer past UINT_MAX"); + if ((unsigned) len >= UINT_MAX - buf->use) return(-1); - } needSize = buf->use + len + 1; - if (!xmlBufferResize(buf, needSize)){ - xmlTreeErrMemory("growing buffer"); - return XML_ERR_NO_MEMORY; - } + if (!xmlBufferResize(buf, needSize)) + return(-1); } memmove(&buf->content[len], &buf->content[0], buf->use); @@ -7767,10 +8007,8 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, * Create the ns-map. */ map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap)); - if (map == NULL) { - xmlTreeErrMemory("allocating namespace map"); - return (NULL); - } + if (map == NULL) + return(NULL); memset(map, 0, sizeof(struct xmlNsMap)); *nsmap = map; } @@ -7787,10 +8025,8 @@ xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position, * Create a new item. */ ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem)); - if (ret == NULL) { - xmlTreeErrMemory("allocating namespace map item"); - return (NULL); - } + if (ret == NULL) + return(NULL); memset(ret, 0, sizeof(struct xmlNsMapItem)); } @@ -7882,10 +8118,8 @@ xmlDOMWrapNewCtxt(void) xmlDOMWrapCtxtPtr ret; ret = xmlMalloc(sizeof(xmlDOMWrapCtxt)); - if (ret == NULL) { - xmlTreeErrMemory("allocating DOM-wrapper context"); + if (ret == NULL) return (NULL); - } memset(ret, 0, sizeof(xmlDOMWrapCtxt)); return (ret); } @@ -8047,20 +8281,16 @@ xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number, { if (*list == NULL) { *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr)); - if (*list == NULL) { - xmlTreeErrMemory("alloc ns map item"); + if (*list == NULL) return(-1); - } *size = 3; *number = 0; } else if ((*number) >= (*size)) { *size *= 2; *list = (xmlNsPtr *) xmlRealloc(*list, (*size) * 2 * sizeof(xmlNsPtr)); - if (*list == NULL) { - xmlTreeErrMemory("realloc ns map item"); + if (*list == NULL) return(-1); - } } (*list)[2 * (*number)] = oldNs; (*list)[2 * (*number) +1] = newNs; @@ -9333,10 +9563,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, * Nodes of xmlNode structure. */ clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (clone == NULL) { - xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node"); + if (clone == NULL) goto internal_error; - } memset(clone, 0, sizeof(xmlNode)); /* * Set hierarchical links. @@ -9358,10 +9586,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, */ /* Use xmlRealloc to avoid -Warray-bounds warning */ clone = (xmlNodePtr) xmlRealloc(NULL, sizeof(xmlAttr)); - if (clone == NULL) { - xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node"); + if (clone == NULL) goto internal_error; - } memset(clone, 0, sizeof(xmlAttr)); /* * Set hierarchical links. @@ -9439,11 +9665,8 @@ xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt, * Create a new xmlNs. */ cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cloneNs == NULL) { - xmlTreeErrMemory("xmlDOMWrapCloneNode(): " - "allocating namespace"); + if (cloneNs == NULL) return(-1); - } memset(cloneNs, 0, sizeof(xmlNs)); cloneNs->type = XML_LOCAL_NAMESPACE; @@ -9623,7 +9846,8 @@ end_ns_reference: idVal = xmlNodeListGetString(cur->doc, cur->children, 1); if (idVal != NULL) { - if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) { + if (xmlAddIDSafe(destDoc, idVal, (xmlAttrPtr) cur, 0, + NULL) < 0) { /* TODO: error message. */ xmlFree(idVal); goto internal_error;