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);