diff options
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 209 |
1 files changed, 164 insertions, 45 deletions
@@ -122,7 +122,7 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID, */ static int xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, - xmlEntityPtr ent) + xmlEntityPtr ent, size_t replacement) { size_t consumed = 0; @@ -130,7 +130,24 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, return (0); if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) return (1); - if (size != 0) { + if (replacement != 0) { + if (replacement < XML_MAX_TEXT_LENGTH) + return(0); + + /* + * If the volume of entity copy reaches 10 times the + * amount of parsed data and over the large text threshold + * then that's very likely to be an abuse. + */ + if (ctxt->input != NULL) { + consumed = ctxt->input->consumed + + (ctxt->input->cur - ctxt->input->base); + } + consumed += ctxt->sizeentities; + + if (replacement < XML_PARSER_NON_LINEAR * consumed) + return(0); + } else if (size != 0) { /* * Do the check based on the replacement size of the entity */ @@ -153,7 +170,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, /* * use the number of parsed entities in the replacement */ - size = ent->checked; + size = ent->checked / 2; /* * The amount of data parsed counting entities size only once @@ -176,7 +193,6 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, */ return (0); } - xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); return (1); } @@ -1540,7 +1556,7 @@ nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL) { if (ctxt->options & XML_PARSE_NSCLEAN) { int i; - for (i = 0;i < ctxt->nsNr;i += 2) { + for (i = ctxt->nsNr - 2;i >= 0;i -= 2) { if (ctxt->nsTab[i] == prefix) { /* in scope */ if (ctxt->nsTab[i + 1] == URL) @@ -2025,6 +2041,7 @@ static void xmlSHRINK (xmlParserCtxtPtr ctxt) { static void xmlGROW (xmlParserCtxtPtr ctxt) { if ((((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) || ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) && + ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup"); ctxt->instate = XML_PARSER_EOF; @@ -2532,6 +2549,8 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) { NEXT; if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL)) entity = ctxt->sax->getParameterEntity(ctxt->userData, name); + if (ctxt->instate == XML_PARSER_EOF) + return; if (entity == NULL) { /* @@ -2719,7 +2738,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR)) goto int_error; if (ent != NULL) - ctxt->nbentities += ent->checked; + ctxt->nbentities += ent->checked / 2; if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { if (ent->content != NULL) { @@ -2742,7 +2761,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, while (*current != 0) { /* non input consuming loop */ buffer[nbchars++] = *current++; if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { - if (xmlParserEntityCheck(ctxt, nbchars, ent)) + if (xmlParserEntityCheck(ctxt, nbchars, ent, 0)) goto int_error; growBuffer(buffer, XML_PARSER_BUFFER_SIZE); } @@ -2770,7 +2789,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) goto int_error; if (ent != NULL) - ctxt->nbentities += ent->checked; + ctxt->nbentities += ent->checked / 2; if (ent != NULL) { if (ent->content == NULL) { xmlLoadEntityContent(ctxt, ent); @@ -2784,7 +2803,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, while (*current != 0) { /* non input consuming loop */ buffer[nbchars++] = *current++; if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { - if (xmlParserEntityCheck(ctxt, nbchars, ent)) + if (xmlParserEntityCheck(ctxt, nbchars, ent, 0)) goto int_error; growBuffer(buffer, XML_PARSER_BUFFER_SIZE); } @@ -3435,7 +3454,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { /** * xmlParseNCName: * @ctxt: an XML parser context - * @len: lenght of the string parsed + * @len: length of the string parsed * * parse an XML name. * @@ -3934,7 +3953,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { if ((len > XML_MAX_TEXT_LENGTH) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); goto mem_error; } if (c == 0) break; @@ -4027,10 +4046,16 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { * entities problems */ if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && - (ent->content != NULL)) { + (ent->content != NULL) && (ent->checked == 0)) { + unsigned long oldnbent = ctxt->nbentities; + rep = xmlStringDecodeEntities(ctxt, ent->content, XML_SUBSTITUTE_REF, 0, 0, 0); + + ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; if (rep != NULL) { + if (xmlStrchr(rep, '<')) + ent->checked |= 1; xmlFree(rep); rep = NULL; } @@ -4075,7 +4100,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { goto error; if ((in_space) && (normalize)) { - while (buf[len - 1] == 0x20) len--; + while ((len > 0) && (buf[len - 1] == 0x20)) len--; } buf[len] = 0; if (RAW == '<') { @@ -4093,11 +4118,11 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { /* * There we potentially risk an overflow, don't allow attribute value of - * lenght more than INT_MAX it is a very reasonnable assumption ! + * length more than INT_MAX it is a very reasonnable assumption ! */ if (len >= INT_MAX) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); goto mem_error; } @@ -4983,7 +5008,8 @@ get_more: } if (buf != NULL) xmlFree(buf); - ctxt->instate = state; + if (ctxt->instate != XML_PARSER_EOF) + ctxt->instate = state; return; } if (buf != NULL) { @@ -5571,6 +5597,8 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) { } } } + if (ctxt->instate == XML_PARSER_EOF) + return; SKIP_BLANKS; if (RAW != '>') { xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, @@ -7196,13 +7224,15 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { * Store the number of entities needing parsing for this entity * content and do checkings */ - ent->checked = ctxt->nbentities - oldnbent; + ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; + if ((ent->content != NULL) && (xmlStrchr(ent->content, '<'))) + ent->checked |= 1; if (ret == XML_ERR_ENTITY_LOOP) { xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); xmlFreeNodeList(list); return; } - if (xmlParserEntityCheck(ctxt, 0, ent)) { + if (xmlParserEntityCheck(ctxt, 0, ent, 0)) { xmlFreeNodeList(list); return; } @@ -7261,9 +7291,9 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { list = NULL; } if (ent->checked == 0) - ent->checked = 1; + ent->checked = 2; } else if (ent->checked != 1) { - ctxt->nbentities += ent->checked; + ctxt->nbentities += ent->checked / 2; } /* @@ -7360,6 +7390,13 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { xmlNodePtr nw = NULL, cur, firstChild = NULL; /* + * We are copying here, make sure there is no abuse + */ + ctxt->sizeentcopy += ent->length; + if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy)) + return; + + /* * when operating on a reader, the entities definitions * are always owning the entities subtree. if (ctxt->parseMode == XML_PARSE_READER) @@ -7399,6 +7436,14 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { } else if ((list == NULL) || (ctxt->inputNr > 0)) { xmlNodePtr nw = NULL, cur, next, last, firstChild = NULL; + + /* + * We are copying here, make sure there is no abuse + */ + ctxt->sizeentcopy += ent->length; + if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy)) + return; + /* * Copy the entity child list and make it the new * entity child list. The goal is to make sure any @@ -7515,7 +7560,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { NEXT; /* - * Predefined entites override any extra definition + * Predefined entities override any extra definition */ if ((ctxt->options & XML_PARSE_OLDSAX) == 0) { ent = xmlGetPredefinedEntity(name); @@ -7524,7 +7569,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { } /* - * Increate the number of entity references parsed + * Increase the number of entity references parsed */ ctxt->nbentities++; @@ -7543,6 +7588,8 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { ent = xmlSAX2GetEntity(ctxt, name); } } + if (ctxt->instate == XML_PARSER_EOF) + return(NULL); /* * [ WFC: Entity Declared ] * In a document without any DTD, a document with only an @@ -7609,11 +7656,13 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { * not contain a <. */ else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) && - (ent != NULL) && (ent->content != NULL) && - (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && - (xmlStrchr(ent->content, '<'))) { - xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, - "'<' in entity '%s' is not allowed in attributes values\n", name); + (ent != NULL) && + (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) { + if ((ent->checked & 1) || ((ent->checked == 0) && + (ent->content != NULL) &&(xmlStrchr(ent->content, '<')))) { + xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, + "'<' in entity '%s' is not allowed in attributes values\n", name); + } } /* @@ -7733,6 +7782,10 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) { ent = xmlSAX2GetEntity(ctxt, name); } } + if (ctxt->instate == XML_PARSER_EOF) { + xmlFree(name); + return(NULL); + } /* * [ WFC: Entity Declared ] @@ -7894,8 +7947,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt) */ if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL)) - entity = ctxt->sax->getParameterEntity(ctxt->userData, - name); + entity = ctxt->sax->getParameterEntity(ctxt->userData, name); + if (ctxt->instate == XML_PARSER_EOF) + return; if (entity == NULL) { /* * [ WFC: Entity Declared ] @@ -8132,8 +8186,11 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) { */ if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL)) - entity = ctxt->sax->getParameterEntity(ctxt->userData, - name); + entity = ctxt->sax->getParameterEntity(ctxt->userData, name); + if (ctxt->instate == XML_PARSER_EOF) { + xmlFree(name); + return(NULL); + } if (entity == NULL) { /* * [ WFC: Entity Declared ] @@ -8235,6 +8292,8 @@ xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) { if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) && (!ctxt->disableSAX)) ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI); + if (ctxt->instate == XML_PARSER_EOF) + return; /* * Is there any internal subset declarations ? @@ -8897,7 +8956,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, if (((in - start) > XML_MAX_TEXT_LENGTH) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); return(NULL); } } @@ -8919,7 +8978,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, if (((in - start) > XML_MAX_TEXT_LENGTH) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); return(NULL); } } @@ -8948,7 +9007,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, if (((in - start) > XML_MAX_TEXT_LENGTH) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); return(NULL); } } @@ -8956,7 +9015,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, if (((in - start) > XML_MAX_TEXT_LENGTH) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); return(NULL); } if (*in != limit) goto need_complex; @@ -8978,7 +9037,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, if (((in - start) > XML_MAX_TEXT_LENGTH) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); return(NULL); } } @@ -8987,7 +9046,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, if (((in - start) > XML_MAX_TEXT_LENGTH) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, - "AttValue lenght too long\n"); + "AttValue length too long\n"); return(NULL); } if (*in != limit) goto need_complex; @@ -9993,6 +10052,8 @@ xmlParseElement(xmlParserCtxtPtr ctxt) { * Parse the content of the element: */ xmlParseContent(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + return; if (!IS_BYTE_CHAR(RAW)) { xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED, "Premature end of data in tag %s line %d\n", @@ -10565,6 +10626,8 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { */ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator); + if (ctxt->instate == XML_PARSER_EOF) + return(-1); if ((ctxt->encoding == NULL) && ((ctxt->input->end - ctxt->input->cur) >= 4)) { @@ -10616,6 +10679,8 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { } if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) ctxt->sax->startDocument(ctxt->userData); + if (ctxt->instate == XML_PARSER_EOF) + return(-1); /* * The Misc part of the Prolog @@ -10635,6 +10700,8 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { if (RAW == '[') { ctxt->instate = XML_PARSER_DTD; xmlParseInternalSubset(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + return(-1); } /* @@ -10645,6 +10712,8 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { (!ctxt->disableSAX)) ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName, ctxt->extSubSystem, ctxt->extSubURI); + if (ctxt->instate == XML_PARSER_EOF) + return(-1); ctxt->inSubset = 0; xmlCleanSpecialAttr(ctxt); @@ -10785,6 +10854,8 @@ xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) { } if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) ctxt->sax->startDocument(ctxt->userData); + if (ctxt->instate == XML_PARSER_EOF) + return(-1); /* * Doing validity checking on chunk doesn't make sense @@ -10795,6 +10866,8 @@ xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) { ctxt->depth = 0; xmlParseContent(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + return(-1); if ((RAW == '<') && (NXT(1) == '/')) { xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); @@ -11102,7 +11175,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { } xmlParseGetLasts(ctxt, &lastlt, &lastgt); - while (1) { + while (ctxt->instate != XML_PARSER_EOF) { if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) return(0); @@ -11121,9 +11194,13 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { /* * If we are operating on converted input, try to flush * remainng chars to avoid them stalling in the non-converted - * buffer. + * buffer. But do not do this in document start where + * encoding="..." may not have been read and we work on a + * guessed encoding. */ - if (xmlBufIsEmpty(ctxt->input->buf->buffer) == 0) { + if ((ctxt->instate != XML_PARSER_START) && + (ctxt->input->buf->raw != NULL) && + (xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) { size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); size_t current = ctxt->input->cur - ctxt->input->base; @@ -11338,6 +11415,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->endElement(ctxt->userData, name); #endif /* LIBXML_SAX1_ENABLED */ } + if (ctxt->instate == XML_PARSER_EOF) + goto done; spacePop(ctxt); if (ctxt->nameNr == 0) { ctxt->instate = XML_PARSER_EPILOG; @@ -11528,6 +11607,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->characters(ctxt->userData, ctxt->input->cur, tmp); } + if (ctxt->instate == XML_PARSER_EOF) + goto done; SKIPL(tmp); ctxt->checkIndex = 0; } @@ -11563,6 +11644,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->characters(ctxt->userData, ctxt->input->cur, base); } + if (ctxt->instate == XML_PARSER_EOF) + goto done; SKIPL(base + 3); ctxt->checkIndex = 0; ctxt->instate = XML_PARSER_CONTENT; @@ -11596,6 +11679,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { "PP: Parsing PI\n"); #endif xmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_MISC; ctxt->progressive = 1; ctxt->checkIndex = 0; @@ -11612,6 +11697,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { "PP: Parsing Comment\n"); #endif xmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_MISC; ctxt->progressive = 1; ctxt->checkIndex = 0; @@ -11633,9 +11720,11 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { "PP: Parsing internal subset\n"); #endif ctxt->inSubset = 1; - ctxt->progressive = 1; + ctxt->progressive = 0; ctxt->checkIndex = 0; xmlParseDocTypeDecl(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; if (RAW == '[') { ctxt->instate = XML_PARSER_DTD; #ifdef DEBUG_PUSH @@ -11695,6 +11784,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { "PP: Parsing PI\n"); #endif xmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_PROLOG; ctxt->progressive = 1; } else if ((cur == '<') && (next == '!') && @@ -11709,6 +11800,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { "PP: Parsing Comment\n"); #endif xmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_PROLOG; ctxt->progressive = 1; } else if ((cur == '<') && (next == '!') && @@ -11747,6 +11840,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { "PP: Parsing PI\n"); #endif xmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_EPILOG; ctxt->progressive = 1; } else if ((cur == '<') && (next == '!') && @@ -11761,6 +11856,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { "PP: Parsing Comment\n"); #endif xmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_EPILOG; ctxt->progressive = 1; } else if ((cur == '<') && (next == '!') && @@ -11891,6 +11988,8 @@ not_end_of_int_subset: found_end_int_subset: ctxt->checkIndex = 0; xmlParseInternalSubset(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->inSubset = 2; if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && (ctxt->sax->externalSubset != NULL)) @@ -11898,6 +11997,8 @@ found_end_int_subset: ctxt->extSubSystem, ctxt->extSubURI); ctxt->inSubset = 0; xmlCleanSpecialAttr(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_PROLOG; ctxt->checkIndex = 0; #ifdef DEBUG_PUSH @@ -12041,7 +12142,7 @@ xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) { } if ((ctxt->progressive == XML_PARSER_DTD) || (ctxt->instate == XML_PARSER_DTD)) { - if (memchr(chunk, ']', size) != NULL) + if (memchr(chunk, '>', size) != NULL) return(1); return(0); } @@ -12125,7 +12226,7 @@ xmldecl_done: remain = 0; } } - 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; @@ -12142,14 +12243,17 @@ xmldecl_done: if ((in->encoder != NULL) && (in->buffer != NULL) && (in->raw != NULL)) { int nbchars; + size_t base = xmlBufGetInputBase(in->buffer, ctxt->input); + size_t current = ctxt->input->cur - ctxt->input->base; - nbchars = xmlCharEncInput(in); + nbchars = xmlCharEncInput(in, terminate); if (nbchars < 0) { /* TODO 2.6.0 */ xmlGenericError(xmlGenericErrorContext, "xmlParseChunk: encoder error\n"); return(XML_ERR_INVALID_ENCODING); } + xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current); } } } @@ -12171,6 +12275,9 @@ xmldecl_done: avail - old_avail))) xmlParseTryOrFinish(ctxt, terminate); } + if (ctxt->instate == XML_PARSER_EOF) + return(ctxt->errNo); + if ((ctxt->input != NULL) && (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) || ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) && @@ -12189,7 +12296,14 @@ xmldecl_done: } if ((end_in_lf == 1) && (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { + size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, + ctxt->input); + size_t current = ctxt->input->cur - ctxt->input->base; + xmlParserInputBufferPush(ctxt->input->buf, 1, "\r"); + + xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, + base, current); } if (terminate) { /* @@ -12219,7 +12333,10 @@ xmldecl_done: } ctxt->instate = XML_PARSER_EOF; } - return((xmlParserErrors) ctxt->errNo); + if (ctxt->wellFormed == 0) + return((xmlParserErrors) ctxt->errNo); + else + return(0); } /************************************************************************ @@ -12364,6 +12481,7 @@ xmlStopParser(xmlParserCtxtPtr ctxt) { if (ctxt == NULL) return; ctxt->instate = XML_PARSER_EOF; + ctxt->errNo = XML_ERR_USER_STOP; ctxt->disableSAX = 1; if (ctxt->input != NULL) { ctxt->input->cur = BAD_CAST""; @@ -14749,6 +14867,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt) ctxt->catalogs = NULL; ctxt->nbentities = 0; ctxt->sizeentities = 0; + ctxt->sizeentcopy = 0; xmlInitNodeInfoSeq(&ctxt->node_seq); if (ctxt->attsDefault != NULL) { |