From f19a95108a32b40eaa3b16b41d7a687896e61ce5 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 10 Dec 2023 17:50:22 +0100 Subject: [PATCH] parser: Report malloc failures Fix many places where malloc failures aren't reported. Make xmlErrMemory public. This is useful for custom external entity loaders. Introduce new API function xmlSwitchEncodingName. Change the way how we store whether the the parser is stopped. This used to be signaled by setting ctxt->instate to XML_PARSER_EOF which was misdesigned and error-prone. Set ctxt->disableSAX to 2 instead and introduce a macro PARSER_STOPPED. Also stop to remove parser inputs in xmlHaltParser. This allows to remove many checks of ctxt->instate. Introduce xmlErrParser to handle errors if a parser context is available. --- fuzz/fuzz.c | 6 + include/libxml/parserInternals.h | 6 + include/private/io.h | 4 +- include/private/parser.h | 12 +- parser.c | 1065 +++++++++++++----------------- parserInternals.c | 465 +++++++------ testapi.c | 6 - xmlIO.c | 143 ++-- 8 files changed, 796 insertions(+), 911 deletions(-) diff --git a/fuzz/fuzz.c b/fuzz/fuzz.c index f9331301..f8571c9a 100644 --- a/fuzz/fuzz.c +++ b/fuzz/fuzz.c @@ -377,9 +377,15 @@ xmlFuzzEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED, if (input == NULL) return(NULL); input->filename = (char *) xmlCharStrdup(URL); + if (input->filename == NULL) { + xmlErrMemory(ctxt, NULL); + xmlFreeInputStream(input); + return(NULL); + } input->buf = xmlParserInputBufferCreateMem(entity->data, entity->size, XML_CHAR_ENCODING_NONE); if (input->buf == NULL) { + xmlErrMemory(ctxt, NULL); xmlFreeInputStream(input); return(NULL); } diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h index 017ed273..5657046d 100644 --- a/include/libxml/parserInternals.h +++ b/include/libxml/parserInternals.h @@ -313,9 +313,15 @@ XMLPUBFUN xmlParserCtxtPtr xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, const xmlChar *base); +XMLPUBFUN void + xmlErrMemory (xmlParserCtxtPtr ctxt, + const char *extra); XMLPUBFUN int xmlSwitchEncoding (xmlParserCtxtPtr ctxt, xmlCharEncoding enc); +XMLPUBFUN int + xmlSwitchEncodingName (xmlParserCtxtPtr ctxt, + const char *encoding); XMLPUBFUN int xmlSwitchToEncoding (xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler); diff --git a/include/private/io.h b/include/private/io.h index 5f4b210a..4cc06482 100644 --- a/include/private/io.h +++ b/include/private/io.h @@ -8,8 +8,8 @@ XML_HIDDEN void __xmlIOErr(int domain, int code, const char *extra); XML_HIDDEN void -__xmlLoaderErr(void *ctx, const char *msg, - const char *filename) LIBXML_ATTR_FORMAT(2,0); +xmlLoaderErr(xmlParserCtxtPtr ctxt, const char *msg, + const char *filename) LIBXML_ATTR_FORMAT(2,0); xmlParserInputBufferPtr xmlParserInputBufferCreateString(const xmlChar *str); diff --git a/include/private/parser.h b/include/private/parser.h index 40d179fe..159541a4 100644 --- a/include/private/parser.h +++ b/include/private/parser.h @@ -26,8 +26,18 @@ #define XML_INPUT_USES_ENC_DECL (1u << 4) #define XML_INPUT_ENCODING_ERROR (1u << 5) +#define PARSER_STOPPED(ctxt) ((ctxt)->disableSAX > 1) + XML_HIDDEN void -xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra); +xmlVErrParser(xmlParserCtxtPtr ctxt, xmlNodePtr node, + int domain, int code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, va_list ap); +XML_HIDDEN void +xmlErrParser(xmlParserCtxtPtr ctxt, xmlNodePtr node, + int domain, int code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, ...); XML_HIDDEN void xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info); XML_HIDDEN void LIBXML_ATTR_FORMAT(3,0) diff --git a/parser.c b/parser.c index 699fccd9..43ef214e 100644 --- a/parser.c +++ b/parser.c @@ -241,28 +241,14 @@ static void xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix, const xmlChar * localname) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED; - if (prefix == NULL) - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0, - (const char *) localname, NULL, NULL, 0, 0, - "Attribute %s redefined\n", localname); + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED, + XML_ERR_FATAL, localname, NULL, NULL, 0, + "Attribute %s redefined\n", localname); else - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0, - (const char *) prefix, (const char *) localname, - NULL, 0, 0, "Attribute %s:%s redefined\n", prefix, - localname); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, XML_ERR_ATTRIBUTE_REDEFINED, + XML_ERR_FATAL, prefix, localname, NULL, 0, + "Attribute %s:%s redefined\n", prefix, localname); } /** @@ -277,18 +263,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, NULL, NULL, 0, "%s", msg); } /** @@ -305,29 +281,8 @@ void LIBXML_ATTR_FORMAT(3,0) xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - xmlStructuredErrorFunc schannel = NULL; - - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if ((ctxt != NULL) && (ctxt->sax != NULL) && - (ctxt->sax->initialized == XML_SAX2_MAGIC)) - schannel = ctxt->sax->serror; - if (ctxt != NULL) { - __xmlRaiseError(schannel, - (ctxt->sax) ? ctxt->sax->warning : NULL, - ctxt->userData, - ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_WARNING, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - } else { - __xmlRaiseError(schannel, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_WARNING, NULL, 0, - (const char *) str1, (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_WARNING, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -343,31 +298,10 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { - xmlStructuredErrorFunc schannel = NULL; + ctxt->valid = 0; - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) { - ctxt->errNo = error; - if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) - schannel = ctxt->sax->serror; - } - if (ctxt != NULL) { - __xmlRaiseError(schannel, - ctxt->vctxt.error, ctxt->vctxt.userData, - ctxt, NULL, XML_FROM_DTD, error, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - ctxt->valid = 0; - } else { - __xmlRaiseError(schannel, NULL, NULL, - ctxt, NULL, XML_FROM_DTD, error, - XML_ERR_ERROR, NULL, 0, (const char *) str1, - (const char *) str2, NULL, 0, 0, - msg, (const char *) str1, (const char *) str2); - } + xmlErrParser(ctxt, NULL, XML_FROM_DTD, error, XML_ERR_ERROR, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -383,19 +317,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, int val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, NULL, NULL, NULL, val, 0, msg, val); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, NULL, NULL, val, msg, val); } /** @@ -414,20 +337,8 @@ xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, int val, const xmlChar *str2) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, (const char *) str1, (const char *) str2, - NULL, val, 0, msg, str1, val, str2); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + str1, str2, NULL, val, msg, str1, val, str2); } /** @@ -443,20 +354,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar * val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, - XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, - val); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + val, NULL, NULL, 0, msg, val); } /** @@ -472,15 +371,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar * val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, - XML_FROM_PARSER, error, XML_ERR_ERROR, - NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg, - val); + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_ERROR, + val, NULL, NULL, 0, msg, val); } /** @@ -499,17 +391,10 @@ xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const xmlChar * info1, const xmlChar * info2, const xmlChar * info3) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, - XML_ERR_ERROR, NULL, 0, (const char *) info1, - (const char *) info2, (const char *) info3, 0, 0, msg, - info1, info2, info3); - if (ctxt != NULL) - ctxt->nsWellFormed = 0; + ctxt->nsWellFormed = 0; + + xmlErrParser(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_ERROR, + info1, info2, info3, 0, msg, info1, info2, info3); } /** @@ -528,13 +413,8 @@ xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error, const xmlChar * info1, const xmlChar * info2, const xmlChar * info3) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error, - XML_ERR_WARNING, NULL, 0, (const char *) info1, - (const char *) info2, (const char *) info3, 0, 0, msg, - info1, info2, info3); + xmlErrParser(ctxt, NULL, XML_FROM_NAMESPACE, error, XML_ERR_WARNING, + info1, info2, info3, 0, msg, info1, info2, info3); } static void @@ -1147,11 +1027,9 @@ xmlAddSpecialAttr(xmlParserCtxtPtr ctxt, goto mem_error; } - if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL) - return; - - xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr, - (void *) (ptrdiff_t) type); + if (xmlHashAdd2(ctxt->attsSpecial, fullname, fullattr, + (void *) (ptrdiff_t) type) < 0) + goto mem_error; return; mem_error: @@ -2344,7 +2222,7 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) { } else { int expandPE = ((ctxt->external != 0) || (ctxt->inputNr != 1)); - while (ctxt->instate != XML_PARSER_EOF) { + while (PARSER_STOPPED(ctxt) == 0) { if (IS_BLANK_CH(CUR)) { /* CHECKED tstblanks.xml */ NEXT; } else if (CUR == '%') { @@ -2421,10 +2299,6 @@ xmlPopInput(xmlParserCtxtPtr ctxt) { if (xmlParserDebugEntities) xmlGenericError(xmlGenericErrorContext, "Popping input %d\n", ctxt->inputNr); - if ((ctxt->inputNr > 1) && (ctxt->inSubset == 0) && - (ctxt->instate != XML_PARSER_EOF)) - xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, - "Unfinished entity outside the DTD"); input = inputPop(ctxt); if (input->entity != NULL) input->entity->flags &= ~XML_ENT_EXPANDING; @@ -2464,8 +2338,6 @@ xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) { return(-1); } ret = inputPush(ctxt, input); - if (ctxt->instate == XML_PARSER_EOF) - return(-1); GROW; return(ret); } @@ -2499,12 +2371,10 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) { (NXT(2) == 'x')) { SKIP(3); GROW; - while (RAW != ';') { /* loop blocked by count */ + while ((RAW != ';') && (PARSER_STOPPED(ctxt) == 0)) { if (count++ > 20) { count = 0; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(0); } if ((RAW >= '0') && (RAW <= '9')) val = val * 16 + (CUR - '0'); @@ -2535,8 +2405,6 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) { if (count++ > 20) { count = 0; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(0); } if ((RAW >= '0') && (RAW <= '9')) val = val * 10 + (CUR - '0'); @@ -2838,7 +2706,7 @@ xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, c = 0; while ((c != 0) && (c != end) && /* non input consuming loop */ (c != end2) && (c != end3) && - (ctxt->instate != XML_PARSER_EOF)) { + (PARSER_STOPPED(ctxt) == 0)) { if (c == 0) break; if ((c == '&') && (str[1] == '#')) { @@ -3072,7 +2940,7 @@ xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what, static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, int blank_chars) { - int i, ret; + int i; xmlNodePtr lastChild; /* @@ -3102,9 +2970,25 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, */ if (ctxt->node == NULL) return(0); if (ctxt->myDoc != NULL) { - ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name); - if (ret == 0) return(1); - if (ret == 1) return(0); + xmlElementPtr elemDecl = NULL; + xmlDocPtr doc = ctxt->myDoc; + const xmlChar *prefix = NULL; + + if (ctxt->node->ns) + prefix = ctxt->node->ns->prefix; + if (doc->intSubset != NULL) + elemDecl = xmlHashLookup2(doc->intSubset->elements, ctxt->node->name, + prefix); + if ((elemDecl == NULL) && (doc->extSubset != NULL)) + elemDecl = xmlHashLookup2(doc->extSubset->elements, ctxt->node->name, + prefix); + if (elemDecl != NULL) { + if (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT) + return(1); + if ((elemDecl->etype == XML_ELEMENT_TYPE_ANY) || + (elemDecl->etype == XML_ELEMENT_TYPE_MIXED)) + return(0); + } } /* @@ -3137,7 +3021,7 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, * xmlSplitQName: * @ctxt: an XML parser context * @name: an XML parser context - * @prefix: a xmlChar ** + * @prefixOut: a xmlChar ** * * parse an UTF8 encoded XML qualified name string * @@ -3152,17 +3036,18 @@ static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, */ xmlChar * -xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { +xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefixOut) { xmlChar buf[XML_MAX_NAMELEN + 5]; xmlChar *buffer = NULL; int len = 0; int max = XML_MAX_NAMELEN; xmlChar *ret = NULL; + xmlChar *prefix; const xmlChar *cur = name; int c; - if (prefix == NULL) return(NULL); - *prefix = NULL; + if (prefixOut == NULL) return(NULL); + *prefixOut = NULL; if (cur == NULL) return(NULL); @@ -3217,13 +3102,16 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { if ((c == ':') && (*cur == 0)) { if (buffer != NULL) xmlFree(buffer); - *prefix = NULL; return(xmlStrdup(name)); } - if (buffer == NULL) + if (buffer == NULL) { ret = xmlStrndup(buf, len); - else { + if (ret == NULL) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + } else { ret = buffer; buffer = NULL; max = XML_MAX_NAMELEN; @@ -3232,9 +3120,15 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { if (c == ':') { c = *cur; - *prefix = ret; + prefix = ret; if (c == 0) { - return(xmlStrndup(BAD_CAST "", 0)); + ret = xmlStrndup(BAD_CAST "", 0); + if (ret == NULL) { + xmlFree(prefix); + return(NULL); + } + *prefixOut = prefix; + return(ret); } len = 0; @@ -3270,6 +3164,7 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { buffer = (xmlChar *) xmlMallocAtomic(max); if (buffer == NULL) { xmlErrMemory(ctxt, NULL); + xmlFree(prefix); return(NULL); } memcpy(buffer, buf, len); @@ -3281,6 +3176,7 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { tmp = (xmlChar *) xmlRealloc(buffer, max); if (tmp == NULL) { xmlErrMemory(ctxt, NULL); + xmlFree(prefix); xmlFree(buffer); return(NULL); } @@ -3292,11 +3188,17 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { buffer[len] = 0; } - if (buffer == NULL) + if (buffer == NULL) { ret = xmlStrndup(buf, len); - else { + if (ret == NULL) { + xmlFree(prefix); + return(NULL); + } + } else { ret = buffer; } + + *prefixOut = prefix; } return(ret); @@ -3400,6 +3302,7 @@ static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, static const xmlChar * xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + const xmlChar *ret; int len = 0, l; int c; int maxLength = (ctxt->options & XML_PARSE_HUGE) ? @@ -3484,8 +3387,6 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { c = CUR_CHAR(l); } } - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); return(NULL); @@ -3501,8 +3402,12 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { return (NULL); } if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) - return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len)); - return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); + ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len); + else + ret = xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len); + if (ret == NULL) + xmlErrMemory(ctxt, NULL); + return(ret); } /** @@ -3533,8 +3438,6 @@ xmlParseName(xmlParserCtxtPtr ctxt) { XML_MAX_NAME_LENGTH; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); /* * Accelerator for simple ASCII names @@ -3598,13 +3501,13 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { NEXTL(l); c = CUR_CHAR(l); } - if (ctxt->instate == XML_PARSER_EOF) - return(ret); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); return(ret); } ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len); + if (ret.name == NULL) + xmlErrMemory(ctxt, NULL); return(ret); } @@ -3688,8 +3591,6 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) { const xmlChar *ret; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); in = ctxt->input->cur; while (*in != 0 && *in == *cmp) { @@ -3732,6 +3633,7 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) { static xmlChar * xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { xmlChar buf[XML_MAX_NAMELEN + 5]; + xmlChar *ret; const xmlChar *cur = *str; int len = 0, l; int c; @@ -3797,7 +3699,10 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { return(NULL); } *str = cur; - return(xmlStrndup(buf, len)); + ret = xmlStrndup(buf, len); + if (ret == NULL) + xmlErrMemory(ctxt, NULL); + return(ret); } /** @@ -3818,6 +3723,7 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { xmlChar * xmlParseNmtoken(xmlParserCtxtPtr ctxt) { xmlChar buf[XML_MAX_NAMELEN + 5]; + xmlChar *ret; int len = 0, l; int c; int maxLength = (ctxt->options & XML_PARSE_HUGE) ? @@ -3867,22 +3773,19 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { c = CUR_CHAR(l); } buffer[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buffer); - return(NULL); - } return(buffer); } } - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); if (len == 0) return(NULL); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); return(NULL); } - return(xmlStrndup(buf, len)); + ret = xmlStrndup(buf, len); + if (ret == NULL) + xmlErrMemory(ctxt, NULL); + return(ret); } /** @@ -3933,8 +3836,6 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { ctxt->instate = XML_PARSER_ENTITY_VALUE; input = ctxt->input; GROW; - if (ctxt->instate == XML_PARSER_EOF) - goto error; NEXT; c = CUR_CHAR(l); /* @@ -3947,7 +3848,7 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { * the initial entity and the quote is found */ while (((IS_CHAR(c)) && ((c != stop) || /* checked */ - (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) { + (ctxt->input != input))) && (PARSER_STOPPED(ctxt) == 0)) { if (len + 5 >= size) { xmlChar *tmp; @@ -3976,8 +3877,6 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { } } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) - goto error; if (c != stop) { xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL); goto error; @@ -4095,7 +3994,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { c = CUR_CHAR(l); while (((NXT(0) != limit) && /* checked */ (IS_CHAR(c)) && (c != '<')) && - (ctxt->instate != XML_PARSER_EOF)) { + (PARSER_STOPPED(ctxt) == 0)) { if (c == '&') { in_space = 0; if (NXT(1) == '#') { @@ -4264,11 +4163,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { if (len > maxLength) { xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, "AttValue length too long\n"); - goto mem_error; + goto error; } } - if (ctxt->instate == XML_PARSER_EOF) - goto error; if ((in_space) && (normalize)) { while ((len > 0) && (buf[len - 1] == 0x20)) len--; @@ -4394,7 +4291,6 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { if (tmp == NULL) { xmlFree(buf); xmlErrMemory(ctxt, NULL); - ctxt->instate = (xmlParserInputState) state; return(NULL); } buf = tmp; @@ -4410,10 +4306,6 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { cur = CUR_CHAR(l); } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return(NULL); - } ctxt->instate = (xmlParserInputState) state; if (!IS_CHAR(cur)) { xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); @@ -4465,7 +4357,8 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { } ctxt->instate = XML_PARSER_PUBLIC_LITERAL; cur = CUR; - while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */ + while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop) && + (PARSER_STOPPED(ctxt) == 0)) { /* checked */ if (len + 1 >= size) { xmlChar *tmp; @@ -4488,10 +4381,6 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { cur = CUR; } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return(NULL); - } if (cur != stop) { xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL); } else { @@ -4628,8 +4517,7 @@ get_more: if (*in == ']') { if ((in[1] == ']') && (in[2] == '>')) { xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL); - if (ctxt->instate != XML_PARSER_EOF) - ctxt->input->cur = in + 1; + ctxt->input->cur = in + 1; return; } in++; @@ -4667,8 +4555,6 @@ get_more: line = ctxt->input->line; col = ctxt->input->col; } - if (ctxt->instate == XML_PARSER_EOF) - return; } ctxt->input->cur = in; if (*in == 0xD) { @@ -4689,8 +4575,6 @@ get_more: } SHRINK; GROW; - if (ctxt->instate == XML_PARSER_EOF) - return; in = ctxt->input->cur; } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a)); @@ -4754,8 +4638,6 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) { } cur = CUR_CHAR(l); } - if (ctxt->instate == XML_PARSER_EOF) - return; if (nbchar != 0) { buf[nbchar] = 0; /* @@ -4777,9 +4659,8 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) { /* * cur == 0 can mean * - * - XML_PARSER_EOF or memory error. This is checked above. - * - An actual 0 character. * - End of buffer. + * - An actual 0 character. * - An incomplete UTF-8 sequence. This is allowed if partial is set. */ if (ctxt->input->cur < ctxt->input->end) { @@ -4984,10 +4865,6 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, } buf[len] = 0; - if (ctxt->instate == XML_PARSER_EOF) { - xmlFree(buf); - return; - } if (cur == 0) { xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, "Comment not terminated \n", 3))) goto done; xmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_CONTENT; break; } @@ -11878,8 +11705,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { else xmlParseEndTag1(ctxt, 0); #endif /* LIBXML_SAX1_ENABLED */ - if (ctxt->instate == XML_PARSER_EOF) - goto done; if (ctxt->nameNr == 0) { ctxt->instate = XML_PARSER_EPILOG; } else { @@ -11931,8 +11756,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->characters(ctxt->userData, ctxt->input->cur, tmp); } - if (ctxt->instate == XML_PARSER_EOF) - goto done; SKIPL(tmp); } else { int base = term - CUR_PTR; @@ -11966,8 +11789,6 @@ 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->instate = XML_PARSER_CONTENT; } @@ -11989,8 +11810,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { (!xmlParseLookupString(ctxt, 2, "?>", 2))) goto done; xmlParsePI(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; break; } else if (next == '!') { if ((!terminate) && (avail < 3)) @@ -12004,8 +11823,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { (!xmlParseLookupString(ctxt, 4, "-->", 3))) goto done; xmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; break; } } else if (ctxt->instate == XML_PARSER_MISC) { @@ -12022,8 +11839,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { goto done; ctxt->inSubset = 1; xmlParseDocTypeDecl(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; if (RAW == '[') { ctxt->instate = XML_PARSER_DTD; } else { @@ -12041,8 +11856,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->extSubURI); ctxt->inSubset = 0; xmlCleanSpecialAttr(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; } break; @@ -12065,8 +11878,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (!xmlParseLookupInternalSubset(ctxt))) goto done; xmlParseInternalSubset(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->inSubset = 2; if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && (ctxt->sax->externalSubset != NULL)) @@ -12074,8 +11885,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->extSubSystem, ctxt->extSubURI); ctxt->inSubset = 0; xmlCleanSpecialAttr(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; ctxt->instate = XML_PARSER_PROLOG; break; } @@ -12124,10 +11933,8 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, if (ctxt == NULL) return(XML_ERR_INTERNAL_ERROR); - if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) + if (ctxt->disableSAX != 0) return(ctxt->errNo); - if (ctxt->instate == XML_PARSER_EOF) - return(-1); if (ctxt->input == NULL) return(-1); @@ -12141,7 +11948,7 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, } if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && - (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { + (ctxt->input->buf != NULL)) { size_t pos = ctxt->input->cur - ctxt->input->base; int res; @@ -12155,14 +11962,13 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, } 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)) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { - xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup"); + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, + "Buffer size limit exceeded, try XML_PARSE_HUGE\n"); xmlHaltParser(ctxt); } if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) @@ -12254,7 +12060,6 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, ctxt = xmlNewSAXParserCtxt(sax, user_data); if (ctxt == NULL) { - xmlErrMemory(NULL, "creating parser: out of memory\n"); xmlFreeParserInputBuffer(buf); return(NULL); } @@ -12263,6 +12068,11 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, ctxt->directory = NULL; } else { ctxt->directory = xmlParserGetDirectory(filename); + if (ctxt->directory == NULL) { + xmlFreeParserCtxt(ctxt); + xmlFreeParserInputBuffer(buf); + return(NULL); + } } inputStream = xmlNewInputStream(ctxt); @@ -12316,7 +12126,8 @@ xmlStopParser(xmlParserCtxtPtr ctxt) { if (ctxt == NULL) return; xmlHaltParser(ctxt); - ctxt->errNo = XML_ERR_USER_STOP; + if (ctxt->errNo != XML_ERR_NO_MEMORY) + ctxt->errNo = XML_ERR_USER_STOP; } /** @@ -12554,6 +12365,11 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, ctxt->myDoc->properties = XML_DOC_INTERNAL; ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none", ExternalID, SystemID); + if (ctxt->myDoc->extSubset == NULL) { + xmlFreeDoc(ctxt->myDoc); + xmlFreeParserCtxt(ctxt); + return(NULL); + } xmlParseExternalSubset(ctxt, ExternalID, SystemID); if (ctxt->myDoc != NULL) { @@ -12671,8 +12487,9 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, if (((depth > 40) && ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) || (depth > 100)) { - xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP, - "Maximum entity nesting depth exceeded"); + if (oldctxt != NULL) + xmlFatalErrMsg(oldctxt, XML_ERR_ENTITY_LOOP, + "Maximum entity nesting depth exceeded"); return(XML_ERR_ENTITY_LOOP); } @@ -12685,7 +12502,8 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, ctxt = xmlCreateEntityParserCtxtInternal(sax, user_data, URL, ID, NULL, oldctxt); - if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); + if (ctxt == NULL) + return(oldctxt ? oldctxt->errNo : XML_ERR_INTERNAL_ERROR); if (oldctxt != NULL) { ctxt->nbErrors = oldctxt->nbErrors; ctxt->nbWarnings = oldctxt->nbWarnings; @@ -12694,8 +12512,8 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, newDoc = xmlNewDoc(BAD_CAST "1.0"); if (newDoc == NULL) { - xmlFreeParserCtxt(ctxt); - return(XML_ERR_INTERNAL_ERROR); + xmlErrMemory(oldctxt, NULL); + goto error; } newDoc->properties = XML_DOC_INTERNAL; if (doc) { @@ -12707,16 +12525,16 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, } if (doc->URL != NULL) { newDoc->URL = xmlStrdup(doc->URL); + if (newDoc->URL == NULL) { + xmlErrMemory(oldctxt, NULL); + goto error; + } } } newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL); if (newRoot == NULL) { - if (sax != NULL) - xmlFreeParserCtxt(ctxt); - newDoc->intSubset = NULL; - newDoc->extSubset = NULL; - xmlFreeDoc(newDoc); - return(XML_ERR_INTERNAL_ERROR); + xmlErrMemory(oldctxt, NULL); + goto error; } xmlAddChild((xmlNodePtr) newDoc, newRoot); nodePush(ctxt, newDoc->children); @@ -12755,7 +12573,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, if (oldctxt->validate) { ctxt->vctxt.error = oldctxt->vctxt.error; ctxt->vctxt.warning = oldctxt->vctxt.warning; - ctxt->vctxt.userData = oldctxt->vctxt.userData; + ctxt->vctxt.userData = ctxt; ctxt->vctxt.flags = oldctxt->vctxt.flags; } ctxt->external = oldctxt->external; @@ -12794,14 +12612,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); } - if (!ctxt->wellFormed) { - ret = (xmlParserErrors)ctxt->errNo; - if (oldctxt != NULL) { - oldctxt->errNo = ctxt->errNo; - oldctxt->wellFormed = 0; - xmlCopyError(&ctxt->lastError, &oldctxt->lastError); - } - } else { + if (ctxt->wellFormed) { if (list != NULL) { xmlNodePtr cur; @@ -12817,7 +12628,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, } newDoc->children->children = NULL; } - ret = XML_ERR_OK; + ctxt->errNo = XML_ERR_OK; } /* @@ -12850,10 +12661,25 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, ctxt->node_seq.maximum = 0; ctxt->node_seq.length = 0; ctxt->node_seq.buffer = NULL; + +error: + if ((oldctxt != NULL) && (ctxt->errNo != 0)) { + oldctxt->errNo = ctxt->errNo; + oldctxt->wellFormed = ctxt->wellFormed; + if (ctxt->disableSAX > oldctxt->disableSAX) + oldctxt->disableSAX = ctxt->disableSAX; + if (xmlCopyError(&ctxt->lastError, &oldctxt->lastError) < 0) { + xmlErrMemory(oldctxt, NULL); + } + } + + ret = ctxt->errNo; xmlFreeParserCtxt(ctxt); - newDoc->intSubset = NULL; - newDoc->extSubset = NULL; - xmlFreeDoc(newDoc); + if (newDoc != NULL) { + newDoc->intSubset = NULL; + newDoc->extSubset = NULL; + xmlFreeDoc(newDoc); + } return(ret); } @@ -12962,7 +12788,38 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, return(XML_ERR_INTERNAL_ERROR); ctxt = xmlCreateDocParserCtxt(string); - if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); + if (ctxt == NULL) { + xmlErrMemory(oldctxt, NULL); + return(XML_ERR_NO_MEMORY); + } + + if (oldctxt->myDoc == NULL) { + newDoc = xmlNewDoc(BAD_CAST "1.0"); + if (newDoc == NULL) { + xmlErrMemory(oldctxt, NULL); + ret = XML_ERR_NO_MEMORY; + goto error; + } + newDoc->properties = XML_DOC_INTERNAL; + newDoc->dict = ctxt->dict; + xmlDictReference(newDoc->dict); + ctxt->myDoc = newDoc; + } else { + ctxt->myDoc = oldctxt->myDoc; + content = ctxt->myDoc->children; + last = ctxt->myDoc->last; + } + newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL); + if (newRoot == NULL) { + xmlErrMemory(oldctxt, NULL); + ret = XML_ERR_NO_MEMORY; + goto error; + } + ctxt->myDoc->children = NULL; + ctxt->myDoc->last = NULL; + xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot); + nodePush(ctxt, ctxt->myDoc->children); + ctxt->nbErrors = oldctxt->nbErrors; ctxt->nbWarnings = oldctxt->nbWarnings; if (user_data != NULL) @@ -12972,6 +12829,7 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); ctxt->dict = oldctxt->dict; ctxt->input_id = oldctxt->input_id; + /* TODO: check malloc */ 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); @@ -13022,30 +12880,6 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, ctxt->options = oldctxt->options; ctxt->_private = oldctxt->_private; - if (oldctxt->myDoc == NULL) { - newDoc = xmlNewDoc(BAD_CAST "1.0"); - if (newDoc == NULL) { - ret = XML_ERR_INTERNAL_ERROR; - goto error; - } - newDoc->properties = XML_DOC_INTERNAL; - newDoc->dict = ctxt->dict; - xmlDictReference(newDoc->dict); - ctxt->myDoc = newDoc; - } else { - ctxt->myDoc = oldctxt->myDoc; - content = ctxt->myDoc->children; - last = ctxt->myDoc->last; - } - newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL); - if (newRoot == NULL) { - ret = XML_ERR_INTERNAL_ERROR; - goto error; - } - ctxt->myDoc->children = NULL; - ctxt->myDoc->last = NULL; - xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot); - nodePush(ctxt, ctxt->myDoc->children); ctxt->instate = XML_PARSER_CONTENT; ctxt->depth = oldctxt->depth; @@ -13075,7 +12909,12 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, ret = (xmlParserErrors)ctxt->errNo; oldctxt->errNo = ctxt->errNo; oldctxt->wellFormed = 0; - xmlCopyError(&ctxt->lastError, &oldctxt->lastError); + if (ctxt->disableSAX > oldctxt->disableSAX) + oldctxt->disableSAX = ctxt->disableSAX; + if (xmlCopyError(&ctxt->lastError, &oldctxt->lastError) < 0) { + xmlErrMemory(oldctxt, NULL); + ret = XML_ERR_NO_MEMORY; + } } else { ret = XML_ERR_OK; } @@ -13124,11 +12963,12 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, oldctxt->nbErrors = ctxt->nbErrors; oldctxt->nbWarnings = ctxt->nbWarnings; -error: ctxt->sax = oldsax; ctxt->dict = NULL; ctxt->attsDefault = NULL; ctxt->attsSpecial = NULL; + +error: xmlFreeParserCtxt(ctxt); if (newDoc != NULL) { xmlFreeDoc(newDoc); @@ -13233,16 +13073,8 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, } else options |= XML_PARSE_NODICT; - if (doc->encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; - - hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding); - if (hdlr != NULL) { - xmlSwitchToEncoding(ctxt, hdlr); - } else { - return(XML_ERR_UNSUPPORTED_ENCODING); - } - } + if (doc->encoding != NULL) + xmlSwitchEncodingName(ctxt, (const char *) doc->encoding); xmlCtxtUseOptionsInternal(ctxt, options, NULL); xmlDetectSAX2(ctxt); @@ -13604,11 +13436,11 @@ xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData, xmlParserCtxtPtr pctx) { xmlParserCtxtPtr ctxt; xmlParserInputPtr inputStream; - char *directory = NULL; - xmlChar *uri; + xmlChar *uri = NULL; ctxt = xmlNewSAXParserCtxt(sax, userData); if (ctxt == NULL) { + xmlErrMemory(pctx, NULL); return(NULL); } @@ -13622,38 +13454,48 @@ xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData, if (xmlStrcmp(URL, BAD_CAST "-") == 0) URL = BAD_CAST "./-"; - uri = xmlBuildURI(URL, base); - - if (uri == NULL) { - inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); - if (inputStream == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - inputPush(ctxt, inputStream); - - if ((ctxt->directory == NULL) && (directory == NULL)) - directory = xmlParserGetDirectory((char *)URL); - if ((ctxt->directory == NULL) && (directory != NULL)) - ctxt->directory = directory; - } else { - inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt); - if (inputStream == NULL) { - xmlFree(uri); - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - inputPush(ctxt, inputStream); - - if ((ctxt->directory == NULL) && (directory == NULL)) - directory = xmlParserGetDirectory((char *)uri); - if ((ctxt->directory == NULL) && (directory != NULL)) - ctxt->directory = directory; - xmlFree(uri); + if (base != NULL) { + if (xmlBuildURISafe(URL, base, &uri) < 0) { + xmlErrMemory(ctxt, NULL); + goto error; + } + if (uri != NULL) + URL = uri; } + + inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); + if (inputStream == NULL) + goto error; + + inputPush(ctxt, inputStream); + + if (ctxt->directory == NULL) { + ctxt->directory = xmlParserGetDirectory((char *)URL); + if (ctxt->directory == NULL) { + xmlErrMemory(ctxt, NULL); + goto error; + } + } + + xmlFree(uri); return(ctxt); + +error: + if (pctx != NULL) { + if (xmlCopyError(&ctxt->lastError, &pctx->lastError) < 0) { + xmlErrMemory(pctx, NULL); + } else { + pctx->errNo = ctxt->errNo; + if (ctxt->disableSAX > pctx->disableSAX) + pctx->disableSAX = ctxt->disableSAX; + if (ctxt->wellFormed == 0) + pctx->wellFormed = 0; + } + } + + xmlFree(uri); + xmlFreeParserCtxt(ctxt); + return(NULL); } /** @@ -13700,10 +13542,8 @@ xmlCreateURLParserCtxt(const char *filename, int options) char *directory = NULL; ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - xmlErrMemory(NULL, "cannot allocate parser context"); + if (ctxt == NULL) return(NULL); - } if (options) xmlCtxtUseOptionsInternal(ctxt, options, NULL); @@ -13912,14 +13752,12 @@ xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer, if ((ctxt == NULL) || (buffer == NULL)) return; - input = xmlNewInputStream(ctxt); - if (input == NULL) { - xmlErrMemory(NULL, "parsing new buffer: out of memory\n"); - xmlClearParserCtxt(ctxt); - return; - } - xmlClearParserCtxt(ctxt); + + input = xmlNewInputStream(ctxt); + if (input == NULL) + return; + if (filename != NULL) input->filename = (char *) xmlCanonicPath((const xmlChar *)filename); input->base = buffer; @@ -13949,13 +13787,13 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data, ctxt = xmlCreateFileParserCtxt(filename); if (ctxt == NULL) return -1; - if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) - xmlFree(ctxt->sax); - ctxt->sax = sax; - xmlDetectSAX2(ctxt); - - if (user_data != NULL) + if (sax != NULL) { + if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) + xmlFree(ctxt->sax); + ctxt->sax = sax; ctxt->userData = user_data; + } + xmlDetectSAX2(ctxt); xmlParseDocument(ctxt); @@ -13967,8 +13805,6 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data, else ret = -1; } - if (sax != NULL) - ctxt->sax = NULL; if (ctxt->myDoc != NULL) { xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL; @@ -14168,13 +14004,13 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data, ctxt = xmlCreateMemoryParserCtxt(buffer, size); if (ctxt == NULL) return -1; - if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) - xmlFree(ctxt->sax); - ctxt->sax = sax; - xmlDetectSAX2(ctxt); - - if (user_data != NULL) + if (sax != NULL) { + if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) + xmlFree(ctxt->sax); + ctxt->sax = sax; ctxt->userData = user_data; + } + xmlDetectSAX2(ctxt); xmlParseDocument(ctxt); @@ -14186,8 +14022,6 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data, else ret = -1; } - if (sax != NULL) - ctxt->sax = NULL; if (ctxt->myDoc != NULL) { xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL; @@ -14536,17 +14370,8 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, } } - if (encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; - - hdlr = xmlFindCharEncodingHandler(encoding); - if (hdlr != NULL) { - xmlSwitchToEncoding(ctxt, hdlr); - } else { - xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "Unsupported encoding %s\n", BAD_CAST encoding); - } - } + if (encoding != NULL) + xmlSwitchEncodingName(ctxt, encoding); return(0); } @@ -14743,35 +14568,32 @@ static xmlDocPtr xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding, int options, int reuse) { - xmlDocPtr ret; + xmlDocPtr ret = NULL; xmlCtxtUseOptionsInternal(ctxt, options, encoding); - if (encoding != NULL) { - xmlCharEncodingHandlerPtr hdlr; - - /* - * TODO: We should consider to set XML_PARSE_IGNORE_ENC if the - * caller provided an encoding. Otherwise, we might switch to - * the encoding from the XML declaration which is likely to - * break things. Also see xmlSwitchInputEncoding. - */ - hdlr = xmlFindCharEncodingHandler(encoding); - if (hdlr != NULL) - xmlSwitchToEncoding(ctxt, hdlr); - } + if (encoding != NULL) + xmlSwitchEncodingName(ctxt, encoding); if ((URL != NULL) && (ctxt->input != NULL) && - (ctxt->input->filename == NULL)) + (ctxt->input->filename == NULL)) { ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); + if (ctxt->input->filename == NULL) { + xmlErrMemory(ctxt, NULL); + goto error; + } + } xmlParseDocument(ctxt); - if ((ctxt->wellFormed) || ctxt->recovery) + if ((ctxt->wellFormed) || + ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) { ret = ctxt->myDoc; - else { + } else { ret = NULL; if (ctxt->myDoc != NULL) { xmlFreeDoc(ctxt->myDoc); } } ctxt->myDoc = NULL; + +error: if (!reuse) { xmlFreeParserCtxt(ctxt); } @@ -15051,6 +14873,7 @@ xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size, input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); if (input == NULL) { + xmlErrMemory(ctxt, NULL); return(NULL); } diff --git a/parserInternals.c b/parserInternals.c index 92c9c9ae..693cfd6d 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -45,6 +45,8 @@ #include "private/io.h" #include "private/parser.h" +#define XML_MAX_ERRORS 100 + /* * XML_MAX_AMPLIFICATION_DEFAULT is the default maximum allowed amplification * factor of serialized output after entity expansion. @@ -99,25 +101,138 @@ xmlCheckVersion(int version) { * Handle a redefinition of attribute error */ void -xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra) +xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra ATTRIBUTE_UNUSED) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) { - ctxt->errNo = XML_ERR_NO_MEMORY; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; + xmlError *lastError = &xmlLastError; + + xmlResetLastError(); + lastError->domain = XML_FROM_PARSER; + lastError->code = XML_ERR_NO_MEMORY; + lastError->level = XML_ERR_FATAL; + + ctxt->errNo = XML_ERR_NO_MEMORY; + ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */ + ctxt->wellFormed = 0; + ctxt->disableSAX = 2; + + xmlResetError(&ctxt->lastError); + ctxt->lastError.domain = XML_FROM_PARSER; + ctxt->lastError.code = XML_ERR_NO_MEMORY; + ctxt->lastError.level = XML_ERR_FATAL; + + if ((ctxt->sax->initialized == XML_SAX2_MAGIC) && + (ctxt->sax->serror != NULL)) { + ctxt->sax->serror(ctxt->userData, &ctxt->lastError); + } else if (xmlStructuredError != NULL) { + xmlStructuredError(ctxt->userData, &ctxt->lastError); + } else { + xmlGenericErrorFunc channel = ctxt->sax->error; + + if ((channel == xmlParserError) || + (channel == xmlParserWarning) || + (channel == xmlParserValidityError) || + (channel == xmlParserValidityWarning)) + channel = xmlGenericError; + + if (channel != NULL) + channel(ctxt->userData, "parser error : out of memory\n"); } - if (extra) - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, - NULL, NULL, 0, 0, - "Memory allocation failed : %s\n", extra); - else - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, - XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, - NULL, NULL, 0, 0, "Memory allocation failed\n"); +} + +void +xmlVErrParser(xmlParserCtxtPtr ctxt, xmlNodePtr node, + int domain, int code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, va_list ap) +{ + xmlStructuredErrorFunc schannel = NULL; + xmlGenericErrorFunc channel; + void *data; + const char *file = NULL; + int line = 0; + int col = 0; + int res; + + if (PARSER_STOPPED(ctxt)) + return; + + if (code == XML_ERR_NO_MEMORY) { + xmlErrMemory(ctxt, NULL); + return; + } + + if (level == XML_ERR_WARNING) { + if (ctxt->nbWarnings >= XML_MAX_ERRORS) + return; + ctxt->nbWarnings += 1; + } else { + if (ctxt->nbErrors >= XML_MAX_ERRORS) + return; + ctxt->nbErrors += 1; + } + + if (ctxt->sax->initialized == XML_SAX2_MAGIC) + schannel = ctxt->sax->serror; + + if ((domain == XML_FROM_VALID) || (domain == XML_FROM_DTD)) { + if (level == XML_ERR_WARNING) + channel = ctxt->vctxt.warning; + else + channel = ctxt->vctxt.error; + data = ctxt->vctxt.userData; + } else { + if (level == XML_ERR_WARNING) + channel = ctxt->sax->warning; + else + channel = ctxt->sax->error; + data = ctxt->userData; + } + + if (ctxt->input != NULL) { + xmlParserInputPtr input = ctxt->input; + + if ((input->filename == NULL) && + (ctxt->inputNr > 1)) { + input = ctxt->inputTab[ctxt->inputNr - 2]; + } + file = input->filename; + line = input->line; + col = input->col; + } + + res = xmlVRaiseError(schannel, channel, data, ctxt, node, domain, code, + level, file, line, (const char *) str1, + (const char *) str2, (const char *) str3, int1, col, + msg, ap); + + if (res < 0) { + xmlErrMemory(ctxt, NULL); + return; + } + + if (level >= XML_ERR_ERROR) + ctxt->errNo = code; + if (level == XML_ERR_FATAL) { + ctxt->wellFormed = 0; + if (ctxt->recovery == 0) + ctxt->disableSAX = 1; + } + + return; +} + +void +xmlErrParser(xmlParserCtxtPtr ctxt, xmlNodePtr node, + int domain, int code, xmlErrorLevel level, + const xmlChar *str1, const xmlChar *str2, const xmlChar *str3, + int int1, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + xmlVErrParser(ctxt, node, domain, code, level, + str1, str2, str3, int1, msg, ap); + va_end(ap); } /** @@ -134,20 +249,8 @@ void __xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr, const char *msg, const xmlChar * str1, const xmlChar * str2) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = xmlerr; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL, - NULL, 0, (const char *) str1, (const char *) str2, - NULL, 0, 0, msg, str1, str2); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL, + str1, str2, NULL, 0, msg, str1, str2); } /** @@ -161,20 +264,10 @@ __xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr, static void LIBXML_ATTR_FORMAT(2,0) xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = XML_ERR_INTERNAL_ERROR; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR, - XML_ERR_FATAL, NULL, 0, (const char *) str, NULL, NULL, - 0, 0, msg, str); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + if (ctxt == NULL) + return; + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR, + XML_ERR_FATAL, str, NULL, NULL, 0, msg, str); } /** @@ -190,9 +283,6 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info) { const char *errmsg; - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; switch (error) { case XML_ERR_INVALID_HEX_CHARREF: errmsg = "CharRef: invalid hexadecimal value"; @@ -393,21 +483,14 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info) default: errmsg = "Unregistered error message"; } - if (ctxt != NULL) - ctxt->errNo = error; + if (info == NULL) { - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n", - errmsg); + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, NULL, NULL, 0, "%s\n", errmsg); } else { - __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error, - XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n", - errmsg, info); - } - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + (const xmlChar *) info, NULL, NULL, 0, + "%s: %s\n", errmsg, info); } } @@ -424,19 +507,8 @@ static void LIBXML_ATTR_FORMAT(3,0) xmlErrEncodingInt(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, int val) { - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if (ctxt != NULL) - ctxt->errNo = error; - __xmlRaiseError(NULL, NULL, NULL, - ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, - NULL, 0, NULL, NULL, NULL, val, 0, msg, val); - if (ctxt != NULL) { - ctxt->wellFormed = 0; - if (ctxt->recovery == 0) - ctxt->disableSAX = 1; - } + xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL, + NULL, NULL, NULL, val, msg, val); } /** @@ -473,28 +545,8 @@ void xmlHaltParser(xmlParserCtxtPtr ctxt) { if (ctxt == NULL) return; - ctxt->instate = XML_PARSER_EOF; - ctxt->disableSAX = 1; - while (ctxt->inputNr > 1) - xmlFreeInputStream(inputPop(ctxt)); - if (ctxt->input != NULL) { - /* - * in case there was a specific allocation deallocate before - * overriding base - */ - if (ctxt->input->free != NULL) { - ctxt->input->free((xmlChar *) ctxt->input->base); - ctxt->input->free = NULL; - } - if (ctxt->input->buf != NULL) { - xmlFreeParserInputBuffer(ctxt->input->buf); - ctxt->input->buf = NULL; - } - ctxt->input->cur = BAD_CAST""; - ctxt->input->length = 0; - ctxt->input->base = ctxt->input->cur; - ctxt->input->end = ctxt->input->cur; - } + ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */ + ctxt->disableSAX = 2; } /** @@ -538,7 +590,8 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) { if (((curEnd > XML_MAX_LOOKUP_LIMIT) || (curBase > XML_MAX_LOOKUP_LIMIT)) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { - xmlErrMemory(ctxt, "Huge input lookup"); + xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT, + "Buffer size limit exceeded, try XML_PARSE_HUGE\n"); xmlHaltParser(ctxt); return(-1); } @@ -551,9 +604,6 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) { if (ret < 0) { xmlFatalErr(ctxt, buf->error, NULL); - /* Buffer contents may be lost in case of memory errors. */ - if (buf->error == XML_ERR_NO_MEMORY) - xmlHaltParser(ctxt); } return(ret); @@ -712,16 +762,14 @@ xmlNextChar(xmlParserCtxtPtr ctxt) size_t avail; int c; - if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) || - (ctxt->input == NULL)) + if ((ctxt == NULL) || (ctxt->input == NULL)) return; avail = ctxt->input->end - ctxt->input->cur; if (avail < INPUT_CHUNK) { xmlParserGrow(ctxt); - if ((ctxt->instate == XML_PARSER_EOF) || - (ctxt->input->cur >= ctxt->input->end)) + if (ctxt->input->cur >= ctxt->input->end) return; avail = ctxt->input->end - ctxt->input->cur; } @@ -836,15 +884,11 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { int c; if ((ctxt == NULL) || (len == NULL) || (ctxt->input == NULL)) return(0); - if (ctxt->instate == XML_PARSER_EOF) - return(0); avail = ctxt->input->end - ctxt->input->cur; if (avail < INPUT_CHUNK) { xmlParserGrow(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - return(0); avail = ctxt->input->end - ctxt->input->cur; } @@ -1070,24 +1114,30 @@ xmlCopyChar(int len ATTRIBUTE_UNUSED, xmlChar *out, int val) { * * ************************************************************************/ -static xmlCharEncodingHandlerPtr -xmlDetectEBCDIC(xmlParserInputPtr input) { +static int +xmlDetectEBCDIC(xmlParserInputPtr input, xmlCharEncodingHandlerPtr *hout) { xmlChar out[200]; xmlCharEncodingHandlerPtr handler; int inlen, outlen, res, i; + *hout = NULL; + /* * To detect the EBCDIC code page, we convert the first 200 bytes * to EBCDIC-US and try to find the encoding declaration. */ - handler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC); - if (handler == NULL) - return(NULL); + res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler); + if (res != 0) + return(res); outlen = sizeof(out) - 1; inlen = input->end - input->cur; res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen); + /* + * Return the EBCDIC handler if decoding failed. The error will + * be reported later. + */ if (res < 0) - return(handler); + goto done; out[outlen] = 0; for (i = 0; i < outlen; i++) { @@ -1119,15 +1169,24 @@ xmlDetectEBCDIC(xmlParserInputPtr input) { break; out[i] = 0; xmlCharEncCloseFunc(handler); - return(xmlFindCharEncodingHandler((char *) out + start)); + res = xmlOpenCharEncodingHandler((char *) out + start, &handler); + if (res != 0) + return(res); + *hout = handler; + return(0); } } +done: /* - * ICU handlers are stateful, so we have to recreate them. + * Encoding handlers are stateful, so we have to recreate them. */ xmlCharEncCloseFunc(handler); - return(xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC)); + res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler); + if (res != 0) + return(res); + *hout = handler; + return(0); } /** @@ -1135,10 +1194,11 @@ xmlDetectEBCDIC(xmlParserInputPtr input) { * @ctxt: the parser context * @enc: the encoding value (number) * - * Use encoding specified by enum to decode input data. + * Use encoding specified by enum to decode input data. This overrides + * the encoding found in the XML declaration. * - * This function can be used to enforce the encoding of chunks passed - * to xmlParseChunk. + * This function can also be used to override the encoding of chunks + * passed to xmlParseChunk. * * Returns 0 in case of success, -1 otherwise */ @@ -1146,8 +1206,8 @@ int xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) { xmlCharEncodingHandlerPtr handler = NULL; - int check = 1; int ret; + int res; if ((ctxt == NULL) || (ctxt->input == NULL)) return(-1); @@ -1156,28 +1216,25 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) case XML_CHAR_ENCODING_NONE: case XML_CHAR_ENCODING_UTF8: case XML_CHAR_ENCODING_ASCII: - check = 0; + res = 0; break; case XML_CHAR_ENCODING_EBCDIC: - handler = xmlDetectEBCDIC(ctxt->input); + res = xmlDetectEBCDIC(ctxt->input, &handler); break; default: - handler = xmlGetCharEncodingHandler(enc); + res = xmlLookupCharEncodingHandler(enc, &handler); break; } - if ((check) && (handler == NULL)) { - const char *name = xmlGetCharEncodingName(enc); + if (res != 0) { + if (res == XML_ERR_UNSUPPORTED_ENCODING) { + const char *name = xmlGetCharEncodingName(enc); - __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "encoding not supported: %s\n", - BAD_CAST (name ? name : ""), NULL); - /* - * TODO: We could recover from errors in external entities - * if we didn't stop the parser. But most callers of this - * function don't check the return value. - */ - xmlStopParser(ctxt); + __xmlErrEncoding(ctxt, res, "encoding not supported: %s\n", + BAD_CAST (name ? name : ""), NULL); + } else { + xmlFatalErr(ctxt, res, NULL); + } return(-1); } @@ -1190,6 +1247,39 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) return(ret); } +/** + * xmlSwitchEncodingName: + * @ctxt: the parser context + * @encoding: the encoding name + * + * Use specified encoding to decode input data. This overrides the + * encoding found in the XML declaration. + * + * This function can also be used to override the encoding of chunks + * passed to xmlParseChunk. + * + * Available since 2.13.0. + * + * Returns 0 in case of success, -1 otherwise + */ +int +xmlSwitchEncodingName(xmlParserCtxtPtr ctxt, const char *encoding) { + xmlCharEncodingHandlerPtr handler; + int res; + + res = xmlOpenCharEncodingHandler(encoding, &handler); + if (res != 0) { + if (res == XML_ERR_UNSUPPORTED_ENCODING) + __xmlErrEncoding(ctxt, res, "Unsupported encoding: %s\n", + (const xmlChar *) encoding, NULL); + else + xmlFatalErr(ctxt, res, NULL); + return(-1); + } + + return(xmlSwitchInputEncoding(ctxt, ctxt->input, handler)); +} + /** * xmlSwitchInputEncoding: * @ctxt: the parser context @@ -1261,12 +1351,17 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, input->consumed += processed; in->raw = in->buffer; in->buffer = xmlBufCreate(); + if (in->buffer == NULL) { + xmlErrMemory(ctxt, NULL); + return(-1); + } in->rawconsumed = processed; nbchars = xmlCharEncInput(in); xmlBufResetInput(in->buffer, input); - if (nbchars < 0) { - /* TODO: This could be an out of memory or an encoding error. */ + if (nbchars == XML_ENC_ERR_MEMORY) { + xmlErrMemory(ctxt, NULL); + } else if (nbchars < 0) { xmlErrInternal(ctxt, "switching encoding: encoder error\n", NULL); @@ -1412,23 +1507,9 @@ xmlDetectEncoding(xmlParserCtxtPtr ctxt) { */ void xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) { - if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = encoding; - if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) && ((ctxt->options & XML_PARSE_IGNORE_ENC) == 0)) { - xmlCharEncodingHandlerPtr handler; - - handler = xmlFindCharEncodingHandler((const char *) encoding); - if (handler == NULL) { - __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "Unsupported encoding: %s\n", - encoding, NULL); - return; - } - - xmlSwitchToEncoding(ctxt, handler); + xmlSwitchEncodingName(ctxt, (const char *) encoding); ctxt->input->flags |= XML_INPUT_USES_ENC_DECL; } else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) { static const char *allowedUTF8[] = { @@ -1474,9 +1555,17 @@ xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) { "Encoding '%s' doesn't match " "auto-detected '%s'\n", encoding, BAD_CAST autoEnc); + xmlFree(encoding); + encoding = xmlStrdup(BAD_CAST autoEnc); + if (encoding == NULL) + xmlErrMemory(ctxt, NULL); } } } + + if (ctxt->encoding != NULL) + xmlFree((xmlChar *) ctxt->encoding); + ctxt->encoding = encoding; } /************************************************************************ @@ -1706,12 +1795,12 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) { buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE); if (buf == NULL) { if (filename == NULL) - __xmlLoaderErr(ctxt, - "failed to load external entity: NULL filename \n", - NULL); + xmlLoaderErr(ctxt, + "failed to load external entity: NULL filename\n", + NULL); else - __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", - (const char *) filename); + xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", + (const char *) filename); return(NULL); } @@ -1765,27 +1854,21 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, { xmlParserInputPtr input; - if(ctxt==NULL) { - xmlErrInternal(NULL, "Got NULL parser context\n", NULL); + if (ctxt == NULL) return(-1); - } xmlInitParser(); if (ctxt->dict == NULL) ctxt->dict = xmlDictCreate(); - if (ctxt->dict == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); + if (ctxt->dict == NULL) return(-1); - } xmlDictSetLimit(ctxt->dict, XML_MAX_DICTIONARY_LIMIT); if (ctxt->sax == NULL) ctxt->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); - if (ctxt->sax == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); + if (ctxt->sax == NULL) return(-1); - } if (sax == NULL) { memset(ctxt->sax, 0, sizeof(xmlSAXHandler)); xmlSAXVersion(ctxt->sax, 2); @@ -1808,13 +1891,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, xmlMalloc(5 * sizeof(xmlParserInputPtr)); ctxt->inputMax = 5; } - if (ctxt->inputTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; + if (ctxt->inputTab == NULL) return(-1); - } while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */ xmlFreeInputStream(input); } @@ -1837,16 +1915,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr)); ctxt->nodeMax = 10; } - if (ctxt->nodeTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; + if (ctxt->nodeTab == NULL) return(-1); - } ctxt->nodeNr = 0; ctxt->node = NULL; @@ -1855,19 +1925,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *)); ctxt->nameMax = 10; } - if (ctxt->nameTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; - ctxt->nameNr = 0; - ctxt->nameMax = 0; - ctxt->name = NULL; + if (ctxt->nameTab == NULL) return(-1); - } ctxt->nameNr = 0; ctxt->name = NULL; @@ -1876,22 +1935,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->spaceTab = (int *) xmlMalloc(10 * sizeof(int)); ctxt->spaceMax = 10; } - if (ctxt->spaceTab == NULL) { - xmlErrMemory(NULL, "cannot initialize parser context\n"); - ctxt->nodeNr = 0; - ctxt->nodeMax = 0; - ctxt->node = NULL; - ctxt->inputNr = 0; - ctxt->inputMax = 0; - ctxt->input = NULL; - ctxt->nameNr = 0; - ctxt->nameMax = 0; - ctxt->name = NULL; - ctxt->spaceNr = 0; - ctxt->spaceMax = 0; - ctxt->space = NULL; + if (ctxt->spaceTab == NULL) return(-1); - } ctxt->spaceNr = 1; ctxt->spaceMax = 10; ctxt->spaceTab[0] = -1; @@ -2092,10 +2137,8 @@ xmlNewSAXParserCtxt(const xmlSAXHandler *sax, void *userData) xmlParserCtxtPtr ctxt; ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt)); - if (ctxt == NULL) { - xmlErrMemory(NULL, "cannot allocate parser context\n"); + if (ctxt == NULL) return(NULL); - } memset(ctxt, 0, sizeof(xmlParserCtxt)); if (xmlInitSAXParserCtxt(ctxt, sax, userData) < 0) { xmlFreeParserCtxt(ctxt); diff --git a/testapi.c b/testapi.c index aa36e5b2..35c74fa6 100644 --- a/testapi.c +++ b/testapi.c @@ -207,12 +207,6 @@ int main(int argc, char **argv) { #include #include -/* - We manually define xmlErrMemory because it's normal declaration - is "hidden" by #ifdef IN_LIBXML -*/ -void xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra); - /* We need some "remote" addresses, but want to avoid getting into name resolution delays, so we use these diff --git a/xmlIO.c b/xmlIO.c index fc3dc6f9..520720bf 100644 --- a/xmlIO.c +++ b/xmlIO.c @@ -414,33 +414,18 @@ xmlIOErr(int code, const char *extra) * Handle a resource access error */ void -__xmlLoaderErr(void *ctx, const char *msg, const char *filename) +xmlLoaderErr(xmlParserCtxtPtr ctxt, const char *msg, const char *filename) { - xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - xmlStructuredErrorFunc schannel = NULL; - xmlGenericErrorFunc channel = NULL; - void *data = NULL; - xmlErrorLevel level = XML_ERR_ERROR; + xmlErrorLevel level; - if ((ctxt != NULL) && (ctxt->disableSAX != 0) && - (ctxt->instate == XML_PARSER_EOF)) - return; - if ((ctxt != NULL) && (ctxt->sax != NULL)) { - if (ctxt->validate) { - channel = ctxt->sax->error; - level = XML_ERR_ERROR; - } else { - channel = ctxt->sax->warning; - level = XML_ERR_WARNING; - } - if (ctxt->sax->initialized == XML_SAX2_MAGIC) - schannel = ctxt->sax->serror; - data = ctxt->userData; - } - __xmlRaiseError(schannel, channel, data, ctxt, NULL, XML_FROM_IO, - XML_IO_LOAD_ERROR, level, NULL, 0, - filename, NULL, NULL, 0, 0, - msg, filename); + if (ctxt->validate) + level = XML_ERR_ERROR; + else + level = XML_ERR_WARNING; + + xmlErrParser(ctxt, NULL, XML_FROM_IO, XML_IO_LOAD_ERROR, level, + (const xmlChar *) filename, NULL, NULL, 0, + msg, filename); } @@ -1018,7 +1003,8 @@ xmlFileFlush (void * context) { * * Write @len bytes from @buffer to the xml buffer * - * Returns the number of bytes written + * Returns the number of bytes written or a negative xmlParserErrors + * value. */ static int xmlBufferWrite (void * context, const char * buffer, int len) { @@ -1026,7 +1012,7 @@ xmlBufferWrite (void * context, const char * buffer, int len) { ret = xmlBufferAdd((xmlBufferPtr) context, (const xmlChar *) buffer, len); if (ret != 0) - return(-1); + return(-XML_ERR_NO_MEMORY); return(len); } #endif @@ -2234,9 +2220,13 @@ xmlRegisterHTTPPostCallbacks( void ) { /** * xmlAllocParserInputBuffer: - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * - * Create a buffered parser input for progressive parsing + * Create a buffered parser input for progressive parsing. + * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. * * Returns the new parser input or NULL */ @@ -2255,7 +2245,13 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) { return(NULL); } xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT); - ret->encoder = xmlGetCharEncodingHandler(enc); + if (enc != XML_CHAR_ENCODING_NONE) { + if (xmlLookupCharEncodingHandler(enc, &ret->encoder) != 0) { + /* We can't handle errors properly here. */ + xmlFreeParserInputBuffer(ret); + return(NULL); + } + } if (ret->encoder != NULL) ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize); else @@ -2689,11 +2685,15 @@ xmlOutputBufferCreateFilename(const char *URI, /** * xmlParserInputBufferCreateFile: * @file: a FILE* - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a buffered parser input for the progressive parsing of a FILE * * buffered C I/O * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. + * * Returns the new parser input or NULL */ xmlParserInputBufferPtr @@ -2777,7 +2777,7 @@ xmlOutputBufferCreateBuffer(xmlBufferPtr buffer, */ const xmlChar * xmlOutputBufferGetContent(xmlOutputBufferPtr out) { - if ((out == NULL) || (out->buffer == NULL)) + if ((out == NULL) || (out->buffer == NULL) || (out->error != 0)) return(NULL); return(xmlBufContent(out->buffer)); @@ -2793,7 +2793,7 @@ xmlOutputBufferGetContent(xmlOutputBufferPtr out) { */ size_t xmlOutputBufferGetSize(xmlOutputBufferPtr out) { - if ((out == NULL) || (out->buffer == NULL)) + if ((out == NULL) || (out->buffer == NULL) || (out->error != 0)) return(0); return(xmlBufUse(out->buffer)); @@ -2805,11 +2805,15 @@ xmlOutputBufferGetSize(xmlOutputBufferPtr out) { /** * xmlParserInputBufferCreateFd: * @fd: a file descriptor number - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a buffered parser input for the progressive parsing for the input * from a file descriptor * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. + * * Returns the new parser input or NULL */ xmlParserInputBufferPtr @@ -2857,11 +2861,15 @@ xmlMemClose(void *vctxt) { * xmlParserInputBufferCreateMem: * @mem: the memory input * @size: the length of the memory block - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a buffered parser input for the progressive parsing for the input * from a memory area. * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. + * * Returns the new parser input or NULL */ xmlParserInputBufferPtr @@ -2999,11 +3007,15 @@ xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) { * @ioread: an I/O read function * @ioclose: an I/O close function * @ioctx: an I/O handler - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) * * Create a buffered parser input for the progressive parsing for the input * from an I/O handler * + * The encoding argument is deprecated and should be set to + * XML_CHAR_ENCODING_NONE. The encoding can be changed with + * xmlSwitchEncoding or xmlSwitchEncodingName later on. + * * Returns the new parser input or NULL */ xmlParserInputBufferPtr @@ -3297,6 +3309,10 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { */ if (out->conv == NULL) { out->conv = xmlBufCreate(); + if (out->conv == NULL) { + out->error = XML_ERR_NO_MEMORY; + return(-1); + } } ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk); if (ret != 0) @@ -3309,11 +3325,8 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { * convert as much as possible to the parser reading buffer. */ ret = xmlCharEncOutput(out, 0); - if ((ret < 0) && (ret != -3)) { - xmlIOErr(XML_IO_ENCODER, NULL); - out->error = XML_IO_ENCODER; + if (ret < 0) return(-1); - } if (out->writecallback) nbchars = xmlBufUse(out->conv); else @@ -3349,8 +3362,10 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { xmlBufShrink(out->buffer, ret); } if (ret < 0) { - xmlIOErr(XML_IO_WRITE, NULL); - out->error = XML_IO_WRITE; + int errNo = (ret == -1) ? XML_IO_WRITE : -ret; + + xmlIOErr(errNo, NULL); + out->error = errNo; return(ret); } if (out->written > INT_MAX - ret) @@ -3502,11 +3517,8 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, * convert as much as possible to the output buffer. */ ret = xmlCharEncOutput(out, 0); - if ((ret < 0) && (ret != -3)) { - xmlIOErr(XML_IO_ENCODER, NULL); - out->error = XML_IO_ENCODER; + if (ret < 0) return(-1); - } if (out->writecallback) nbchars = xmlBufUse(out->conv); else @@ -3543,8 +3555,9 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, xmlBufShrink(out->buffer, ret); } if (ret < 0) { - xmlIOErr(XML_IO_WRITE, NULL); - out->error = XML_IO_WRITE; + int errNo = (ret == -1) ? XML_IO_WRITE : -ret; + xmlIOErr(errNo, NULL); + out->error = errNo; return(ret); } if (out->written > INT_MAX - ret) @@ -3610,11 +3623,8 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) { */ do { nbchars = xmlCharEncOutput(out, 0); - if (nbchars < 0) { - xmlIOErr(XML_IO_ENCODER, NULL); - out->error = XML_IO_ENCODER; + if (nbchars < 0) return(-1); - } } while (nbchars); } @@ -3636,8 +3646,10 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) { xmlBufShrink(out->buffer, ret); } if (ret < 0) { - xmlIOErr(XML_IO_FLUSH, NULL); - out->error = XML_IO_FLUSH; + int errNo = (ret == -1) ? XML_IO_WRITE : -ret; + + xmlIOErr(errNo, NULL); + out->error = errNo; return(ret); } if (out->written > INT_MAX - ret) @@ -3731,10 +3743,10 @@ xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { if (code >= 400) { /* fatal error */ if (ret->filename != NULL) - __xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n", - (const char *) ret->filename); + xmlLoaderErr(ctxt, "failed to load HTTP resource \"%s\"\n", + (const char *) ret->filename); else - __xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL); + xmlLoaderErr(ctxt, "failed to load HTTP resource\n", NULL); xmlFreeInputStream(ret); ret = NULL; } else { @@ -3743,18 +3755,8 @@ xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { if ((xmlStrstr(BAD_CAST mime, BAD_CAST "/xml")) || (xmlStrstr(BAD_CAST mime, BAD_CAST "+xml"))) { encoding = xmlNanoHTTPEncoding(ret->buf->context); - if (encoding != NULL) { - xmlCharEncodingHandlerPtr handler; - - handler = xmlFindCharEncodingHandler(encoding); - if (handler != NULL) { - xmlSwitchInputEncoding(ctxt, ret, handler); - } else { - __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING, - "Unknown encoding %s", - BAD_CAST encoding, NULL); - } - } + if (encoding != NULL) + xmlSwitchEncodingName(ctxt, encoding); #if 0 } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) { #endif @@ -3913,7 +3915,8 @@ xmlDefaultExternalEntityLoader(const char *URL, const char *ID, if (resource == NULL) { if (ID == NULL) ID = "NULL"; - __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID); + if (ctxt != NULL) + xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n", ID); return (NULL); } ret = xmlNewInputFromFile(ctxt, (const char *) resource);