diff options
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 242 |
1 files changed, 235 insertions, 7 deletions
@@ -605,6 +605,10 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) { ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); + if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || + (ctxt->str_xml_ns == NULL)) { + xmlErrMemory(ctxt, NULL); + } } typedef struct _xmlDefAttrs xmlDefAttrs; @@ -3470,13 +3474,16 @@ xmlParseComment(xmlParserCtxtPtr ctxt) { xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL); } if (len + 5 >= size) { + xmlChar *new_buf; size *= 2; - buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); - if (buf == NULL) { + new_buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (new_buf == NULL) { + xmlFree (buf); xmlErrMemory(ctxt, NULL); ctxt->instate = state; return; } + buf = new_buf; } COPY_BUF(ql,buf,len,q); q = r; @@ -7628,7 +7635,8 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix, } SKIP(2); - if ((tlen > 0) && (strncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) { + if ((tlen > 0) && (strncmp(ctxt->input->cur, + (const char *)ctxt->name, tlen) == 0)) { if (ctxt->input->cur[tlen] == '>') { ctxt->input->cur += tlen + 1; goto done; @@ -9075,6 +9083,10 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator); ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); + if (ctxt->version == NULL) { + xmlErrMemory(ctxt, NULL); + break; + } if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) ctxt->sax->startDocument(ctxt->userData); @@ -9733,8 +9745,14 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { int base = ctxt->input->base - ctxt->input->buf->buffer->content; int cur = ctxt->input->cur - ctxt->input->base; + int res; - xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + res =xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + if (res < 0) { + ctxt->errNo = XML_PARSER_EOF; + ctxt->disableSAX = 1; + return (XML_PARSER_EOF); + } ctxt->input->base = ctxt->input->buf->buffer->content + base; ctxt->input->cur = ctxt->input->base + cur; ctxt->input->end = @@ -9893,9 +9911,15 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, if (filename == NULL) inputStream->filename = NULL; - else + else { inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) filename); + if (inputStream->filename == NULL) { + xmlFreeParserCtxt(ctxt); + xmlFreeParserInputBuffer(buf); + return(NULL); + } + } inputStream->buf = buf; inputStream->base = inputStream->buf->buffer->content; inputStream->cur = inputStream->buf->buffer->content; @@ -10127,6 +10151,7 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, xmlParserCtxtPtr ctxt; xmlParserInputPtr input = NULL; xmlCharEncoding enc; + xmlChar* systemIdCanonic; if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL); @@ -10144,16 +10169,26 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, ctxt->sax = sax; ctxt->userData = ctxt; } + + /* + * Canonicalise the system ID + */ + systemIdCanonic = xmlCanonicPath(SystemID); + if (systemIdCanonic == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } /* * Ask the Entity resolver to load the damn thing */ if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL)) - input = ctxt->sax->resolveEntity(ctxt, ExternalID, SystemID); + input = ctxt->sax->resolveEntity(ctxt, ExternalID, systemIdCanonic); if (input == NULL) { if (sax != NULL) ctxt->sax = NULL; xmlFreeParserCtxt(ctxt); + xmlFree(systemIdCanonic); return(NULL); } @@ -10167,7 +10202,9 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, } if (input->filename == NULL) - input->filename = (char *) xmlCanonicPath(SystemID); + input->filename = (char *) systemIdCanonic; + else + xmlFree(systemIdCanonic); input->line = 1; input->col = 1; input->base = ctxt->input->cur; @@ -10359,6 +10396,7 @@ xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL, ctxt->dictNames = ctx->dictNames; ctxt->attsDefault = ctx->attsDefault; ctxt->attsSpecial = ctx->attsSpecial; + ctxt->linenumbers = ctx->linenumbers; xmlParseContent(ctxt); @@ -10807,6 +10845,196 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, return(ret); } +/** + * xmlParseInNodeContext: + * @node: the context node + * @data: the input string + * @datalen: the input string length in bytes + * @options: a combination of xmlParserOption + * @lst: the return value for the set of parsed nodes + * + * Parse a well-balanced chunk of an XML document + * within the context (DTD, namespaces, etc ...) of the given node. + * + * The allowed sequence for the data is a Well Balanced Chunk defined by + * the content production in the XML grammar: + * + * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)* + * + * Returns XML_ERR_OK if the chunk is well balanced, and the parser + * error code otherwise + */ +xmlParserErrors +xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, + int options, xmlNodePtr *lst) { +#ifdef SAX2 + xmlParserCtxtPtr ctxt; + xmlDocPtr doc = NULL; + xmlNodePtr fake, cur; + int nsnr = 0; + + xmlParserErrors ret = XML_ERR_OK; + + /* + * check all input parameters, grab the document + */ + if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0)) + return(XML_ERR_INTERNAL_ERROR); + switch (node->type) { + case XML_ELEMENT_NODE: + case XML_ATTRIBUTE_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_ENTITY_REF_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + break; + default: + return(XML_ERR_INTERNAL_ERROR); + + } + while ((node != NULL) && (node->type != XML_ELEMENT_NODE) && + (node->type != XML_DOCUMENT_NODE) && + (node->type != XML_HTML_DOCUMENT_NODE)) + node = node->parent; + if (node == NULL) + return(XML_ERR_INTERNAL_ERROR); + if (node->type == XML_ELEMENT_NODE) + doc = node->doc; + else + doc = (xmlDocPtr) node; + if (doc == NULL) + return(XML_ERR_INTERNAL_ERROR); + + /* + * allocate a context and set-up everything not related to the + * node position in the tree + */ + if (doc->type == XML_DOCUMENT_NODE) + ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen); +#ifdef LIBXML_HTML_ENABLED + else if (doc->type == XML_HTML_DOCUMENT_NODE) + ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen); +#endif + else + return(XML_ERR_INTERNAL_ERROR); + + if (ctxt == NULL) + return(XML_ERR_NO_MEMORY); + fake = xmlNewComment(NULL); + if (fake == NULL) { + xmlFreeParserCtxt(ctxt); + return(XML_ERR_NO_MEMORY); + } + xmlAddChild(node, fake); + + xmlCtxtUseOptions(ctxt, options); + if (doc->dict != NULL) { + if (ctxt->dict != NULL) + xmlDictFree(ctxt->dict); + ctxt->dict = doc->dict; + } + xmlDetectSAX2(ctxt); + ctxt->myDoc = doc; + + if (node->type == XML_ELEMENT_NODE) { + nodePush(ctxt, node); + /* + * initialize the SAX2 namespaces stack + */ + cur = node; + while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) { + xmlNsPtr ns = cur->nsDef; + const xmlChar *iprefix, *ihref; + + while (ns != NULL) { + if (ctxt->dict) { + iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1); + ihref = xmlDictLookup(ctxt->dict, ns->href, -1); + } else { + iprefix = ns->prefix; + ihref = ns->href; + } + + if (xmlGetNamespace(ctxt, iprefix) == NULL) { + nsPush(ctxt, iprefix, ihref); + nsnr++; + } + ns = ns->next; + } + cur = cur->parent; + } + ctxt->instate = XML_PARSER_CONTENT; + } + + if ((ctxt->validate) || (ctxt->replaceEntities != 0)) { + /* + * ID/IDREF registration will be done in xmlValidateElement below + */ + ctxt->loadsubset |= XML_SKIP_IDS; + } + + xmlParseContent(ctxt); + nsPop(ctxt, nsnr); + if ((RAW == '<') && (NXT(1) == '/')) { + xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); + } else if (RAW != 0) { + xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL); + } + if ((ctxt->node != NULL) && (ctxt->node != node)) { + xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); + ctxt->wellFormed = 0; + } + + if (!ctxt->wellFormed) { + if (ctxt->errNo == 0) + ret = XML_ERR_INTERNAL_ERROR; + else + ret = (xmlParserErrors)ctxt->errNo; + } else { + ret = XML_ERR_OK; + } + + /* + * Return the newly created nodeset after unlinking it from + * the pseudo sibling. + */ + + cur = fake->next; + fake->next = NULL; + node->last = fake; + + if (cur != NULL) { + cur->prev = NULL; + } + + *lst = cur; + + while (cur != NULL) { + cur->parent = NULL; + cur = cur->next; + } + + xmlUnlinkNode(fake); + xmlFreeNode(fake); + + + if (ret != XML_ERR_OK) { + xmlFreeNodeList(*lst); + *lst = NULL; + } + + ctxt->dict = NULL; + xmlFreeParserCtxt(ctxt); + + return(ret); +#else /* !SAX2 */ + return(XML_ERR_INTERNAL_ERROR); +#endif +} + #ifdef LIBXML_SAX1_ENABLED /** * xmlParseBalancedChunkMemoryRecover: |