From: Alexandre Julliard julliard@winehq.org
--- dlls/msxml3/domdoc.c | 19 +- dlls/msxml3/main.c | 10 +- dlls/msxml3/msxml_private.h | 2 +- dlls/msxml3/saxreader.c | 9 - dlls/msxml3/schema.c | 4 +- dlls/msxml3/selection.c | 2 +- dlls/msxml3/tests/domdoc.c | 4 +- dlls/msxml3/xslpattern.h | 1 + libs/xml2/HTMLparser.c | 662 +--- libs/xml2/HTMLtree.c | 2 - libs/xml2/SAX.c | 1 - libs/xml2/SAX2.c | 394 +- libs/xml2/buf.c | 81 +- libs/xml2/catalog.c | 1 - libs/xml2/debugXML.c | 2 - libs/xml2/dict.c | 1438 +++----- libs/xml2/encoding.c | 899 ++--- libs/xml2/entities.c | 7 +- libs/xml2/error.c | 9 +- libs/xml2/globals.c | 1067 +++--- libs/xml2/hash.c | 1809 ++++----- libs/xml2/include/libxml/HTMLparser.h | 23 + libs/xml2/include/libxml/SAX.h | 2 - libs/xml2/include/libxml/SAX2.h | 2 - libs/xml2/include/libxml/dict.h | 1 + libs/xml2/include/libxml/encoding.h | 30 +- libs/xml2/include/libxml/entities.h | 4 + libs/xml2/include/libxml/globals.h | 518 +-- libs/xml2/include/libxml/hash.h | 118 +- libs/xml2/include/libxml/nanoftp.h | 4 +- libs/xml2/include/libxml/parser.h | 155 +- libs/xml2/include/libxml/parserInternals.h | 1 + libs/xml2/include/libxml/relaxng.h | 3 +- libs/xml2/include/libxml/schemasInternals.h | 1 + libs/xml2/include/libxml/threads.h | 15 +- libs/xml2/include/libxml/tree.h | 87 +- libs/xml2/include/libxml/uri.h | 3 +- libs/xml2/include/libxml/valid.h | 2 + libs/xml2/include/libxml/xmlIO.h | 78 +- libs/xml2/include/libxml/xmlerror.h | 45 +- libs/xml2/include/libxml/xmlmemory.h | 78 +- libs/xml2/include/libxml/xmlreader.h | 7 +- libs/xml2/include/libxml/xmlregexp.h | 11 +- libs/xml2/include/libxml/xmlsave.h | 11 +- libs/xml2/include/libxml/xmlschemas.h | 3 + libs/xml2/include/libxml/xmlversion.h | 71 +- libs/xml2/include/libxml/xpath.h | 2 +- libs/xml2/include/libxml/xpathInternals.h | 3 +- libs/xml2/include/libxml/xpointer.h | 9 +- libs/xml2/include/private/buf.h | 5 +- libs/xml2/include/private/dict.h | 69 +- libs/xml2/include/private/enc.h | 4 +- libs/xml2/include/private/error.h | 4 +- libs/xml2/include/private/io.h | 3 + libs/xml2/include/private/parser.h | 35 + libs/xml2/include/private/threads.h | 15 - libs/xml2/libxml.h | 8 + libs/xml2/list.c | 2 +- libs/xml2/parser.c | 3650 +++++++++---------- libs/xml2/parserInternals.c | 1282 ++++--- libs/xml2/pattern.c | 77 +- libs/xml2/relaxng.c | 292 -- libs/xml2/threads.c | 665 ++-- libs/xml2/tree.c | 300 +- libs/xml2/uri.c | 1 - libs/xml2/valid.c | 198 +- libs/xml2/xinclude.c | 85 +- libs/xml2/xmlIO.c | 347 +- libs/xml2/xmlmemory.c | 98 +- libs/xml2/xmlreader.c | 118 +- libs/xml2/xmlregexp.c | 706 +--- libs/xml2/xmlsave.c | 61 +- libs/xml2/xmlschemas.c | 456 +-- libs/xml2/xmlschemastypes.c | 23 +- libs/xml2/xmlstring.c | 52 +- libs/xml2/xpath.c | 906 +---- libs/xml2/xpointer.c | 55 - 77 files changed, 6735 insertions(+), 10492 deletions(-)
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 2acbffc0a88..094447a9add 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -49,15 +49,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(msxml);
-/* not defined in older versions */ -#define XML_SAVE_FORMAT 1 -#define XML_SAVE_NO_DECL 2 -#define XML_SAVE_NO_EMPTY 4 -#define XML_SAVE_NO_XHTML 8 -#define XML_SAVE_XHTML 16 -#define XML_SAVE_AS_XML 32 -#define XML_SAVE_AS_HTML 64 - static const WCHAR PropertySelectionLanguageW[] = {'S','e','l','e','c','t','i','o','n','L','a','n','g','u','a','g','e',0}; static const WCHAR PropertySelectionNamespacesW[] = {'S','e','l','e','c','t','i','o','n','N','a','m','e','s','p','a','c','e','s',0}; static const WCHAR PropertyProhibitDTDW[] = {'P','r','o','h','i','b','i','t','D','T','D',0}; @@ -502,13 +493,14 @@ static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...) va_end(ap); }
-static void sax_serror(void* ctx, xmlErrorPtr err) +static void sax_serror(void* ctx, const xmlError* err) { LIBXML2_CALLBACK_SERROR(doparse, err); }
static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding encoding) { + char *ctx_encoding; xmlDocPtr doc = NULL; xmlParserCtxtPtr pctx; static xmlSAXHandler sax_handler = { @@ -573,6 +565,8 @@ static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding pctx->myDoc = NULL; } pctx->sax = NULL; + ctx_encoding = (char *)pctx->encoding; + pctx->encoding = NULL; xmlFreeParserCtxt(pctx);
/* TODO: put this in one of the SAX callbacks */ @@ -589,9 +583,9 @@ static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding sprintf(buff, "version="%s"", doc->version ? (char*)doc->version : "1.0"); xmlNodeAddContent( node, xmlbuff );
- if (doc->encoding) + if (ctx_encoding) { - sprintf(buff, " encoding="%s"", doc->encoding); + sprintf(buff, " encoding="%s"", ctx_encoding); xmlNodeAddContent( node, xmlbuff ); }
@@ -604,6 +598,7 @@ static xmlDocPtr doparse(domdoc* This, char const* ptr, int len, xmlCharEncoding xmldoc_link_xmldecl( doc, node ); }
+ xmlFree( ctx_encoding ); return doc; }
diff --git a/dlls/msxml3/main.c b/dlls/msxml3/main.c index b329420eb66..c92cd49aaf3 100644 --- a/dlls/msxml3/main.c +++ b/dlls/msxml3/main.c @@ -77,7 +77,7 @@ void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "%s", buff); }
-void wineXmlCallbackError(char const* caller, xmlErrorPtr err) +void wineXmlCallbackError(char const* caller, const xmlError* err) { enum __wine_debug_class dbcl;
@@ -167,7 +167,7 @@ static int to_utf8(int cp, unsigned char *out, int *outlen, const unsigned char WCHAR *tmp; int len = 0;
- if (!in || !inlen) goto done; + if (!in || !inlen || !*inlen) goto done;
len = MultiByteToWideChar(cp, 0, (const char *)in, *inlen, NULL, 0); tmp = malloc(len * sizeof(WCHAR)); @@ -187,7 +187,7 @@ static int from_utf8(int cp, unsigned char *out, int *outlen, const unsigned cha WCHAR *tmp; int len = 0;
- if (!in || !inlen) goto done; + if (!in || !inlen || !*inlen) goto done;
len = MultiByteToWideChar(CP_UTF8, 0, (const char *)in, *inlen, NULL, 0); tmp = malloc(len * sizeof(WCHAR)); @@ -365,10 +365,8 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID reserved) case DLL_PROCESS_ATTACH: xmlInitParser();
- /* Set the default indent character to a single tab, - for this thread and as default for new threads */ + /* Set the default indent character to a single tab */ xmlTreeIndentString = "\t"; - xmlThrDefTreeIndentString("\t");
/* Register callbacks for loading XML files */ if(xmlRegisterInputCallbacks(wineXmlMatchCallback, wineXmlOpenCallback, diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 54f54995c76..ea492bc6b36 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -165,7 +165,7 @@ extern MSXML_VERSION xmldoc_version( xmlDocPtr doc ); extern HRESULT XMLElement_create( xmlNodePtr node, LPVOID *ppObj, BOOL own );
extern void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, va_list ap); -extern void wineXmlCallbackError(char const* caller, xmlErrorPtr err); +extern void wineXmlCallbackError(char const* caller, const xmlError* err);
#define LIBXML2_LOG_CALLBACK WINAPIV __WINE_PRINTF_ATTR(2,3)
diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c index 0e886a2d051..b7dde7c9f4d 100644 --- a/dlls/msxml3/saxreader.c +++ b/dlls/msxml3/saxreader.c @@ -2503,18 +2503,9 @@ static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int siz
if (size >= 4) { - const unsigned char *buff = (unsigned char*)buffer; - encoding = xmlDetectCharEncoding((xmlChar*)buffer, 4); enc_name = (xmlChar*)xmlGetCharEncodingName(encoding); TRACE("detected encoding: %s\n", enc_name); - /* skip BOM, parser won't switch encodings and so won't skip it on its own */ - if ((encoding == XML_CHAR_ENCODING_UTF8) && - buff[0] == 0xEF && buff[1] == 0xBB && buff[2] == 0xBF) - { - buffer += 3; - size -= 3; - } }
/* if libxml2 detection failed try to guess */ diff --git a/dlls/msxml3/schema.c b/dlls/msxml3/schema.c index b6b790d9894..bc1e4cd635a 100644 --- a/dlls/msxml3/schema.c +++ b/dlls/msxml3/schema.c @@ -243,7 +243,7 @@ static void LIBXML2_LOG_CALLBACK parser_warning(void* ctx, char const* msg, ...) va_end(ap); }
-static void parser_serror(void* ctx, xmlErrorPtr err) +static void parser_serror(void* ctx, const xmlError* err) { LIBXML2_CALLBACK_SERROR(Schema_parse, err); } @@ -273,7 +273,7 @@ static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, .. va_end(ap); }
-static void validate_serror(void* ctx, xmlErrorPtr err) +static void validate_serror(void* ctx, const xmlError* err) { LIBXML2_CALLBACK_SERROR(Schema_validate_tree, err); } diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c index f94b17379d9..21441f314ce 100644 --- a/dlls/msxml3/selection.c +++ b/dlls/msxml3/selection.c @@ -756,7 +756,7 @@ static void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs) xmlFree(arg2); }
-static void query_serror(void* ctx, xmlErrorPtr err) +static void query_serror(void* ctx, const xmlError* err) { LIBXML2_CALLBACK_SERROR(domselection_create, err); } diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 10be50656d5..96b390ee784 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -11008,8 +11008,8 @@ static void test_load(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IXMLDOMDocument_load(doc, src, &b); - todo_wine ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); - todo_wine ok(b == VARIANT_FALSE, "got %d\n", b); + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_FALSE, "got %d\n", b);
VariantClear(&src);
diff --git a/dlls/msxml3/xslpattern.h b/dlls/msxml3/xslpattern.h index 388b4955029..ddeb81801c0 100644 --- a/dlls/msxml3/xslpattern.h +++ b/dlls/msxml3/xslpattern.h @@ -21,6 +21,7 @@ #ifndef __XSLPATTERN__ #define __XSLPATTERN__
+#include <stdlib.h> #include <libxml/tree.h> #include <libxml/xmlstring.h> #include <libxml/xpath.h> diff --git a/libs/xml2/HTMLparser.c b/libs/xml2/HTMLparser.c index abcdfe2460d..ea6a4f265fd 100644 --- a/libs/xml2/HTMLparser.c +++ b/libs/xml2/HTMLparser.c @@ -14,24 +14,23 @@ #include <ctype.h> #include <stdlib.h>
+#include <libxml/HTMLparser.h> #include <libxml/xmlmemory.h> #include <libxml/tree.h> #include <libxml/parser.h> #include <libxml/parserInternals.h> #include <libxml/xmlerror.h> -#include <libxml/HTMLparser.h> #include <libxml/HTMLtree.h> #include <libxml/entities.h> #include <libxml/encoding.h> -#include <libxml/valid.h> #include <libxml/xmlIO.h> -#include <libxml/globals.h> #include <libxml/uri.h>
#include "private/buf.h" #include "private/enc.h" #include "private/error.h" #include "private/html.h" +#include "private/io.h" #include "private/parser.h" #include "private/tree.h"
@@ -39,9 +38,6 @@ #define HTML_PARSER_BIG_BUFFER_SIZE 1000 #define HTML_PARSER_BUFFER_SIZE 100
-/* #define DEBUG */ -/* #define DEBUG_PUSH */ - static int htmlOmittedDefaultValue = 1;
xmlChar * htmlDecodeEntities(htmlParserCtxtPtr ctxt, int len, @@ -325,7 +321,6 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt) ************/
#define CUR_CHAR(l) htmlCurrentChar(ctxt, &l) -#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
#define COPY_BUF(l,b,i,v) \ if (l == 1) b[i++] = v; \ @@ -350,8 +345,7 @@ htmlFindEncoding(xmlParserCtxtPtr ctxt) { const xmlChar *start, *cur, *end;
if ((ctxt == NULL) || (ctxt->input == NULL) || - (ctxt->input->encoding != NULL) || (ctxt->input->buf == NULL) || - (ctxt->input->buf->encoder != NULL)) + (ctxt->input->flags & XML_INPUT_HAS_ENCODING)) return(NULL); if ((ctxt->input->cur == NULL) || (ctxt->input->end == NULL)) return(NULL); @@ -411,11 +405,13 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { return(ctxt->token); }
- if ((ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) && - (xmlParserGrow(ctxt) < 0)) - return(0); + if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) { + xmlParserGrow(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + return(0); + }
- if (ctxt->charset != XML_CHAR_ENCODING_UTF8) { + if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) { xmlChar * guess; xmlCharEncodingHandlerPtr handler;
@@ -442,9 +438,6 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { if (guess == NULL) { xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1); } else { - if (ctxt->input->encoding != NULL) - xmlFree((xmlChar *) ctxt->input->encoding); - ctxt->input->encoding = guess; handler = xmlFindCharEncodingHandler((const char *) guess); if (handler != NULL) { /* @@ -457,8 +450,9 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, "Unsupported encoding %s", guess, NULL); } + xmlFree(guess); } - ctxt->charset = XML_CHAR_ENCODING_UTF8; + ctxt->input->flags |= XML_INPUT_HAS_ENCODING; }
/* @@ -535,13 +529,6 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { }
encoding_error: - /* - * If we detect an UTF8 error that probably mean that the - * input encoding didn't get properly advertised in the - * declaration header. Report the error and switch the encoding - * to ISO-Latin-1 (if you don't like this policy, just declare the - * encoding !) - */ { char buffer[150];
@@ -557,15 +544,7 @@ encoding_error: BAD_CAST buffer, NULL); }
- /* - * Don't switch encodings twice. Note that if there's an encoder, we - * shouldn't receive invalid UTF-8 anyway. - * - * Note that if ctxt->input->buf == NULL, switching encodings is - * impossible, see Gitlab issue #34. - */ - if ((ctxt->input->buf != NULL) && - (ctxt->input->buf->encoder == NULL)) + if ((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1); *len = 1; return(*ctxt->input->cur); @@ -1553,20 +1532,11 @@ htmlAutoCloseOnEnd(htmlParserCtxtPtr ctxt) static void htmlAutoClose(htmlParserCtxtPtr ctxt, const xmlChar * newtag) { - while ((newtag != NULL) && (ctxt->name != NULL) && - (htmlCheckAutoClose(newtag, ctxt->name))) { - if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) - ctxt->sax->endElement(ctxt->userData, ctxt->name); - htmlnamePop(ctxt); - } - if (newtag == NULL) { - htmlAutoCloseOnEnd(ctxt); + if (newtag == NULL) return; - } - while ((newtag == NULL) && (ctxt->name != NULL) && - ((xmlStrEqual(ctxt->name, BAD_CAST "head")) || - (xmlStrEqual(ctxt->name, BAD_CAST "body")) || - (xmlStrEqual(ctxt->name, BAD_CAST "html")))) { + + while ((ctxt->name != NULL) && + (htmlCheckAutoClose(newtag, ctxt->name))) { if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) ctxt->sax->endElement(ctxt->userData, ctxt->name); htmlnamePop(ctxt); @@ -3779,93 +3749,6 @@ htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) { return(name); }
-/** - * htmlCheckEncodingDirect: - * @ctxt: an HTML parser context - * @attvalue: the attribute value - * - * Checks an attribute value to detect - * the encoding - * If a new encoding is detected the parser is switched to decode - * it and pass UTF8 - */ -static void -htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) { - - if ((ctxt == NULL) || (encoding == NULL) || - (ctxt->options & HTML_PARSE_IGNORE_ENC)) - return; - - /* do not change encoding */ - if (ctxt->input->encoding != NULL) - return; - - if (encoding != NULL) { - xmlCharEncoding enc; - xmlCharEncodingHandlerPtr handler; - - while ((*encoding == ' ') || (*encoding == '\t')) encoding++; - - if (ctxt->input->encoding != NULL) - xmlFree((xmlChar *) ctxt->input->encoding); - ctxt->input->encoding = xmlStrdup(encoding); - - enc = xmlParseCharEncoding((const char *) encoding); - /* - * registered set of known encodings - */ - if (enc != XML_CHAR_ENCODING_ERROR) { - if (((enc == XML_CHAR_ENCODING_UTF16LE) || - (enc == XML_CHAR_ENCODING_UTF16BE) || - (enc == XML_CHAR_ENCODING_UCS4LE) || - (enc == XML_CHAR_ENCODING_UCS4BE)) && - (ctxt->input->buf != NULL) && - (ctxt->input->buf->encoder == NULL)) { - htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, - "htmlCheckEncoding: wrong encoding meta\n", - NULL, NULL); - } else { - xmlSwitchEncoding(ctxt, enc); - } - ctxt->charset = XML_CHAR_ENCODING_UTF8; - } else { - /* - * fallback for unknown encodings - */ - handler = xmlFindCharEncodingHandler((const char *) encoding); - if (handler != NULL) { - xmlSwitchToEncoding(ctxt, handler); - ctxt->charset = XML_CHAR_ENCODING_UTF8; - } else { - htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "htmlCheckEncoding: unknown encoding %s\n", - encoding, NULL); - } - } - - if ((ctxt->input->buf != NULL) && - (ctxt->input->buf->encoder != NULL) && - (ctxt->input->buf->raw != NULL) && - (ctxt->input->buf->buffer != NULL)) { - int nbchars; - size_t processed; - - /* - * convert as much as possible to the parser reading buffer. - */ - processed = ctxt->input->cur - ctxt->input->base; - xmlBufShrink(ctxt->input->buf->buffer, processed); - nbchars = xmlCharEncInput(ctxt->input->buf, 1); - xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input); - if (nbchars < 0) { - htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, - "htmlCheckEncoding: encoder error\n", - NULL, NULL); - } - } - } -} - /** * htmlCheckEncoding: * @ctxt: an HTML parser context @@ -3894,7 +3777,7 @@ htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) { encoding = xmlStrcasestr(attvalue, BAD_CAST"="); if (encoding && *encoding == '=') { encoding ++; - htmlCheckEncodingDirect(ctxt, encoding); + xmlSetDeclaredEncoding(ctxt, xmlStrdup(encoding)); } }
@@ -3923,7 +3806,7 @@ htmlCheckMeta(htmlParserCtxtPtr ctxt, const xmlChar **atts) { && (!xmlStrcasecmp(value, BAD_CAST"Content-Type"))) http = 1; else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"charset"))) - htmlCheckEncodingDirect(ctxt, value); + xmlSetDeclaredEncoding(ctxt, xmlStrdup(value)); else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"content"))) content = value; att = atts[i++]; @@ -4950,8 +4833,6 @@ __htmlParseContent(void *ctxt) {
int htmlParseDocument(htmlParserCtxtPtr ctxt) { - xmlChar start[4]; - xmlCharEncoding enc; xmlDtdPtr dtd;
xmlInitParser(); @@ -4961,29 +4842,22 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) { "htmlParseDocument: context error\n", NULL, NULL); return(XML_ERR_INTERNAL_ERROR); } - GROW; + /* * SAX: beginning of the document processing. */ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
- if ((ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) && - ((ctxt->input->end - ctxt->input->cur) >= 4)) { - /* - * Get the 4 first bytes and decode the charset - * if enc != XML_CHAR_ENCODING_NONE - * plug some encoding conversion routines. - */ - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(&start[0], 4); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } - } + xmlDetectEncoding(ctxt); + + /* + * This is wrong but matches long-standing behavior. In most cases, + * a document starting with an XML declaration will specify UTF-8. + */ + if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) && + (xmlStrncmp(ctxt->input->cur, BAD_CAST "<?xm", 4) == 0)) + xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_UTF8);
/* * Wipe out everything which is before the first '<' @@ -5289,7 +5163,7 @@ htmlCreateMemoryParserCtxt(const char *buffer, int size) {
/** * htmlCreateDocParserCtxt: - * @cur: a pointer to an array of xmlChar + * @str: a pointer to an array of xmlChar * @encoding: a free form C string describing the HTML document encoding, or NULL * * Create a parser context for an HTML document. @@ -5299,25 +5173,41 @@ htmlCreateMemoryParserCtxt(const char *buffer, int size) { * Returns the new parser context or NULL */ static htmlParserCtxtPtr -htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) { - int len; - htmlParserCtxtPtr ctxt; +htmlCreateDocParserCtxt(const xmlChar *str, const char *encoding) { + xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlParserInputBufferPtr buf;
- if (cur == NULL) + if (str == NULL) return(NULL); - len = xmlStrlen(cur); - ctxt = htmlCreateMemoryParserCtxt((char *)cur, len); + + ctxt = htmlNewParserCtxt(); if (ctxt == NULL) return(NULL);
+ buf = xmlParserInputBufferCreateString(str); + if (buf == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + input = xmlNewInputStream(ctxt); + if (input == NULL) { + xmlFreeParserInputBuffer(buf); + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + input->filename = NULL; + input->buf = buf; + xmlBufResetInput(buf->buffer, input); + + inputPush(ctxt, input); + if (encoding != NULL) { xmlCharEncoding enc; xmlCharEncodingHandlerPtr handler;
- if (ctxt->input->encoding != NULL) - xmlFree((xmlChar *) ctxt->input->encoding); - ctxt->input->encoding = xmlStrdup((const xmlChar *) encoding); - enc = xmlParseCharEncoding(encoding); /* * registered set of known encodings @@ -5343,6 +5233,7 @@ htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) { } } } + return(ctxt); }
@@ -5427,18 +5318,6 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first, } ctxt->checkIndex = base; ctxt->endCheckState = quote; -#ifdef DEBUG_PUSH - if (next == 0) - xmlGenericError(xmlGenericErrorContext, - "HPP: lookup '%c' failed\n", first); - else if (third == 0) - xmlGenericError(xmlGenericErrorContext, - "HPP: lookup '%c%c' failed\n", first, next); - else - xmlGenericError(xmlGenericErrorContext, - "HPP: lookup '%c%c%c' failed\n", first, next, - third); -#endif return (-1); }
@@ -5500,59 +5379,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
htmlParserNodeInfo node_info;
-#ifdef DEBUG_PUSH - switch (ctxt->instate) { - case XML_PARSER_EOF: - xmlGenericError(xmlGenericErrorContext, - "HPP: try EOF\n"); break; - case XML_PARSER_START: - xmlGenericError(xmlGenericErrorContext, - "HPP: try START\n"); break; - case XML_PARSER_MISC: - xmlGenericError(xmlGenericErrorContext, - "HPP: try MISC\n");break; - case XML_PARSER_COMMENT: - xmlGenericError(xmlGenericErrorContext, - "HPP: try COMMENT\n");break; - case XML_PARSER_PROLOG: - xmlGenericError(xmlGenericErrorContext, - "HPP: try PROLOG\n");break; - case XML_PARSER_START_TAG: - xmlGenericError(xmlGenericErrorContext, - "HPP: try START_TAG\n");break; - case XML_PARSER_CONTENT: - xmlGenericError(xmlGenericErrorContext, - "HPP: try CONTENT\n");break; - case XML_PARSER_CDATA_SECTION: - xmlGenericError(xmlGenericErrorContext, - "HPP: try CDATA_SECTION\n");break; - case XML_PARSER_END_TAG: - xmlGenericError(xmlGenericErrorContext, - "HPP: try END_TAG\n");break; - case XML_PARSER_ENTITY_DECL: - xmlGenericError(xmlGenericErrorContext, - "HPP: try ENTITY_DECL\n");break; - case XML_PARSER_ENTITY_VALUE: - xmlGenericError(xmlGenericErrorContext, - "HPP: try ENTITY_VALUE\n");break; - case XML_PARSER_ATTRIBUTE_VALUE: - xmlGenericError(xmlGenericErrorContext, - "HPP: try ATTRIBUTE_VALUE\n");break; - case XML_PARSER_DTD: - xmlGenericError(xmlGenericErrorContext, - "HPP: try DTD\n");break; - case XML_PARSER_EPILOG: - xmlGenericError(xmlGenericErrorContext, - "HPP: try EPILOG\n");break; - case XML_PARSER_PI: - xmlGenericError(xmlGenericErrorContext, - "HPP: try PI\n");break; - case XML_PARSER_SYSTEM_LITERAL: - xmlGenericError(xmlGenericErrorContext, - "HPP: try SYSTEM_LITERAL\n");break; - } -#endif - while (1) {
in = ctxt->input; @@ -5590,6 +5416,16 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { */ goto done; case XML_PARSER_START: + /* + * This is wrong but matches long-standing behavior. In most + * cases, a document starting with an XML declaration will + * specify UTF-8. + */ + if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) && + (xmlStrncmp(ctxt->input->cur, BAD_CAST "<?xm", 4) == 0)) { + xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_UTF8); + } + /* * Very first chars read from the document flow. */ @@ -5604,6 +5440,8 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX)) ctxt->sax->startDocument(ctxt->userData); + if (ctxt->instate == XML_PARSER_EOF) + goto done;
cur = in->cur[0]; next = in->cur[1]; @@ -5615,22 +5453,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing internal subset\n"); -#endif htmlParseDocTypeDecl(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_PROLOG; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering PROLOG\n"); -#endif } else { ctxt->instate = XML_PARSER_MISC; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering MISC\n"); -#endif } break; case XML_PARSER_MISC: @@ -5657,21 +5485,17 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (in->cur[2] == '-') && (in->cur[3] == '-')) { if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing Comment\n"); -#endif htmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_MISC; } else if ((cur == '<') && (next == '?')) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing PI\n"); -#endif htmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_MISC; } else if ((cur == '<') && (next == '!') && (UPP(2) == 'D') && (UPP(3) == 'O') && @@ -5681,25 +5505,15 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing internal subset\n"); -#endif htmlParseDocTypeDecl(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_PROLOG; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering PROLOG\n"); -#endif } else if ((cur == '<') && (next == '!') && (avail < 9)) { goto done; } else { ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering START_TAG\n"); -#endif } break; case XML_PARSER_PROLOG: @@ -5713,31 +5527,23 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (in->cur[2] == '-') && (in->cur[3] == '-')) { if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing Comment\n"); -#endif htmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_PROLOG; } else if ((cur == '<') && (next == '?')) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing PI\n"); -#endif htmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_PROLOG; } else if ((cur == '<') && (next == '!') && (avail < 4)) { goto done; } else { ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering START_TAG\n"); -#endif } break; case XML_PARSER_EPILOG: @@ -5756,21 +5562,17 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (in->cur[2] == '-') && (in->cur[3] == '-')) { if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing Comment\n"); -#endif htmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_EPILOG; } else if ((cur == '<') && (next == '?')) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing PI\n"); -#endif htmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_EPILOG; } else if ((cur == '<') && (next == '!') && (avail < 4)) { @@ -5779,10 +5581,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { ctxt->errNo = XML_ERR_DOCUMENT_END; ctxt->wellFormed = 0; ctxt->instate = XML_PARSER_EOF; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering EOF\n"); -#endif if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) ctxt->sax->endDocument(ctxt->userData); goto done; @@ -5812,19 +5610,11 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { cur = in->cur[0]; if (cur != '<') { ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif break; } if (next == '/') { ctxt->instate = XML_PARSER_END_TAG; ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering END_TAG\n"); -#endif break; } if ((!terminate) && @@ -5865,11 +5655,9 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL)) ctxt->sax->endElement(ctxt->userData, name); htmlnamePop(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif break; }
@@ -5891,11 +5679,9 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (ctxt->record_info) htmlNodeInfoPush(ctxt, &node_info);
+ if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif break; }
@@ -5911,11 +5697,9 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if (ctxt->record_info) htmlNodeInfoPush(ctxt, &node_info);
+ if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif break; } case XML_PARSER_CONTENT: { @@ -5987,13 +5771,11 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { } } htmlParseScript(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; if ((cur == '<') && (next == '/')) { ctxt->instate = XML_PARSER_END_TAG; ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering END_TAG\n"); -#endif break; } } else if ((cur == '<') && (next == '!')) { @@ -6017,11 +5799,9 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing Comment\n"); -#endif htmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_CONTENT; } else { if ((!terminate) && @@ -6033,29 +5813,19 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { if ((!terminate) && (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing PI\n"); -#endif htmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; ctxt->instate = XML_PARSER_CONTENT; } else if ((cur == '<') && (next == '/')) { ctxt->instate = XML_PARSER_END_TAG; ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering END_TAG\n"); -#endif break; } else if ((cur == '<') && IS_ASCII_LETTER(next)) { if ((!terminate) && (next == 0)) goto done; ctxt->instate = XML_PARSER_START_TAG; ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering START_TAG\n"); -#endif break; } else if (cur == '<') { if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && @@ -6074,10 +5844,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0)) goto done; ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: Parsing char data\n"); -#endif while ((ctxt->instate != XML_PARSER_EOF) && (cur != '<') && (in->cur < in->end)) { if (cur == '&') { @@ -6098,128 +5864,20 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0)) goto done; htmlParseEndTag(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; if (ctxt->nameNr == 0) { ctxt->instate = XML_PARSER_EPILOG; } else { ctxt->instate = XML_PARSER_CONTENT; } ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif break; - case XML_PARSER_CDATA_SECTION: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == CDATA\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_DTD: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == DTD\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_COMMENT: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == COMMENT\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_PI: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == PI\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_ENTITY_DECL: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == ENTITY_DECL\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_ENTITY_VALUE: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == ENTITY_VALUE\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering DTD\n"); -#endif - break; - case XML_PARSER_ATTRIBUTE_VALUE: + default: htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == ATTRIBUTE_VALUE\n", - NULL, NULL); - ctxt->instate = XML_PARSER_START_TAG; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering START_TAG\n"); -#endif - break; - case XML_PARSER_SYSTEM_LITERAL: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == XML_PARSER_SYSTEM_LITERAL\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_IGNORE: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == XML_PARSER_IGNORE\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_PUBLIC_LITERAL: - htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR, - "HPP: internal error, state == XML_PARSER_LITERAL\n", - NULL, NULL); - ctxt->instate = XML_PARSER_CONTENT; - ctxt->checkIndex = 0; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "HPP: entering CONTENT\n"); -#endif + "HPP: internal error\n", NULL, NULL); + ctxt->instate = XML_PARSER_EOF; break; - } } done: @@ -6245,9 +5903,6 @@ done: BAD_CAST "-//W3C//DTD HTML 4.0 Transitional//EN", BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd"); } -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, "HPP: done %d\n", ret); -#endif return(ret); }
@@ -6272,42 +5927,17 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, } if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) { - size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); - size_t cur = ctxt->input->cur - ctxt->input->base; + size_t pos = ctxt->input->cur - ctxt->input->base; int res;
res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur); + xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - htmlErrMemory(ctxt, NULL); + htmlParseErr(ctxt, ctxt->input->buf->error, + "xmlParserInputBufferPush failed", NULL, NULL); + xmlHaltParser(ctxt); return (ctxt->errNo); } -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size); -#endif - -#if 0 - if ((terminate) || (ctxt->input->buf->buffer->use > 80)) - htmlParseTryOrFinish(ctxt, terminate); -#endif - } else if (ctxt->instate != XML_PARSER_EOF) { - if ((ctxt->input != NULL) && ctxt->input->buf != NULL) { - xmlParserInputBufferPtr in = ctxt->input->buf; - if ((in->encoder != NULL) && (in->buffer != NULL) && - (in->raw != NULL)) { - int nbchars; - size_t base = xmlBufGetInputBase(in->buffer, ctxt->input); - size_t current = ctxt->input->cur - ctxt->input->base; - - nbchars = xmlCharEncInput(in, terminate); - xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current); - if (nbchars < 0) { - htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING, - "encoder error\n", NULL, NULL); - return(XML_ERR_INVALID_ENCODING); - } - } - } } htmlParseTryOrFinish(ctxt, terminate); if (terminate) { @@ -6357,7 +5987,7 @@ htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data,
xmlInitParser();
- buf = xmlAllocParserInputBuffer(enc); + buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); if (buf == NULL) return(NULL);
ctxt = htmlNewSAXParserCtxt(sax, user_data); @@ -6365,8 +5995,6 @@ htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data, xmlFreeParserInputBuffer(buf); return(NULL); } - if(enc==XML_CHAR_ENCODING_UTF8 || buf->encoder) - ctxt->charset=XML_CHAR_ENCODING_UTF8; if (filename == NULL) { ctxt->directory = NULL; } else { @@ -6390,17 +6018,21 @@ htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data,
inputPush(ctxt, inputStream);
+ if (enc != XML_CHAR_ENCODING_NONE) + xmlSwitchEncoding(ctxt, enc); + if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { - size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); - size_t cur = ctxt->input->cur - ctxt->input->base; - - xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + size_t pos = ctxt->input->cur - ctxt->input->base; + int res;
- xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur); -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size); -#endif + res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); + if (res < 0) { + htmlParseErr(ctxt, ctxt->input->buf->error, + "xmlParserInputBufferPush failed\n", NULL, NULL); + xmlHaltParser(ctxt); + } } ctxt->progressive = 1;
@@ -6488,8 +6120,6 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding) htmlParserCtxtPtr ctxt; htmlParserInputPtr inputStream; char *canonicFilename; - /* htmlCharEncoding enc; */ - xmlChar *content, *content_line = (xmlChar *) "charset=";
if (filename == NULL) return(NULL); @@ -6515,17 +6145,12 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding)
/* set encoding */ if (encoding) { - size_t l = strlen(encoding); - - if (l < 1000) { - content = xmlMallocAtomic (xmlStrlen(content_line) + l + 1); - if (content) { - strcpy ((char *)content, (char *)content_line); - strcat ((char *)content, (char *)encoding); - htmlCheckEncoding (ctxt, content); - xmlFree (content); - } - } + xmlCharEncodingHandlerPtr hdlr; + + hdlr = xmlFindCharEncodingHandler(encoding); + if (hdlr != NULL) { + xmlSwitchToEncoding(ctxt, hdlr); + } }
return(ctxt); @@ -6817,7 +6442,6 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt) ctxt->inSubset = 0; ctxt->errNo = XML_ERR_OK; ctxt->depth = 0; - ctxt->charset = XML_CHAR_ENCODING_NONE; ctxt->catalogs = NULL; xmlInitNodeInfoSeq(&ctxt->node_seq);
@@ -6934,9 +6558,6 @@ htmlDoRead(htmlParserCtxtPtr ctxt, const char *URL, const char *encoding, hdlr = xmlFindCharEncodingHandler(encoding); if (hdlr != NULL) { xmlSwitchToEncoding(ctxt, hdlr); - if (ctxt->input->encoding != NULL) - xmlFree((xmlChar *) ctxt->input->encoding); - ctxt->input->encoding = xmlStrdup((xmlChar *)encoding); } } if ((URL != NULL) && (ctxt->input != NULL) && @@ -7120,7 +6741,7 @@ htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, /** * htmlCtxtReadDoc: * @ctxt: an HTML parser context - * @cur: a pointer to a zero terminated string + * @str: a pointer to a zero terminated string * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of htmlParserOption(s) @@ -7131,13 +6752,33 @@ htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, * Returns the resulting document tree */ htmlDocPtr -htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar * cur, +htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar *str, const char *URL, const char *encoding, int options) { - if (cur == NULL) + xmlParserInputBufferPtr input; + xmlParserInputPtr stream; + + if (ctxt == NULL) return (NULL); - return (htmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL, - encoding, options)); + if (str == NULL) + return (NULL); + xmlInitParser(); + + htmlCtxtReset(ctxt); + + input = xmlParserInputBufferCreateString(str); + if (input == NULL) { + return(NULL); + } + + stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); + if (stream == NULL) { + xmlFreeParserInputBuffer(input); + return(NULL); + } + + inputPush(ctxt, stream); + return (htmlDoRead(ctxt, URL, encoding, options, 1)); }
/** @@ -7203,7 +6844,8 @@ htmlCtxtReadMemory(htmlParserCtxtPtr ctxt, const char *buffer, int size,
htmlCtxtReset(ctxt);
- input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); + input = xmlParserInputBufferCreateStatic(buffer, size, + XML_CHAR_ENCODING_NONE); if (input == NULL) { return(NULL); } diff --git a/libs/xml2/HTMLtree.c b/libs/xml2/HTMLtree.c index fa3a0ed38a8..8698f53e821 100644 --- a/libs/xml2/HTMLtree.c +++ b/libs/xml2/HTMLtree.c @@ -19,10 +19,8 @@ #include <libxml/HTMLparser.h> #include <libxml/HTMLtree.h> #include <libxml/entities.h> -#include <libxml/valid.h> #include <libxml/xmlerror.h> #include <libxml/parserInternals.h> -#include <libxml/globals.h> #include <libxml/uri.h>
#include "private/buf.h" diff --git a/libs/xml2/SAX.c b/libs/xml2/SAX.c index d8e972b84c2..7f2f297406c 100644 --- a/libs/xml2/SAX.c +++ b/libs/xml2/SAX.c @@ -25,7 +25,6 @@ #include <libxml/uri.h> #include <libxml/valid.h> #include <libxml/HTMLtree.h> -#include <libxml/globals.h> #include <libxml/SAX2.h>
#ifdef LIBXML_LEGACY_ENABLED diff --git a/libs/xml2/SAX2.c b/libs/xml2/SAX2.c index b6be1a6c488..bb72e1606b8 100644 --- a/libs/xml2/SAX2.c +++ b/libs/xml2/SAX2.c @@ -13,6 +13,7 @@ #include <string.h> #include <limits.h> #include <stddef.h> +#include <libxml/SAX2.h> #include <libxml/xmlmemory.h> #include <libxml/tree.h> #include <libxml/parser.h> @@ -22,19 +23,14 @@ #include <libxml/xmlerror.h> #include <libxml/debugXML.h> #include <libxml/xmlIO.h> -#include <libxml/SAX.h> #include <libxml/uri.h> #include <libxml/valid.h> #include <libxml/HTMLtree.h> -#include <libxml/globals.h>
#include "private/error.h" #include "private/parser.h" #include "private/tree.h"
-/* #define DEBUG_SAX2 */ -/* #define DEBUG_SAX2_TREE */ - /** * TODO: * @@ -331,11 +327,6 @@ xmlSAX2InternalSubset(void *ctx, const xmlChar *name, xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlDtdPtr dtd; if (ctx == NULL) return; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n", - name, ExternalID, SystemID); -#endif
if (ctxt->myDoc == NULL) return; @@ -368,11 +359,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; if (ctx == NULL) return; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n", - name, ExternalID, SystemID); -#endif if (((ExternalID != NULL) || (SystemID != NULL)) && (((ctxt->validate) || (ctxt->loadsubset != 0)) && (ctxt->wellFormed && ctxt->myDoc))) { @@ -384,8 +370,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, int oldinputMax; xmlParserInputPtr *oldinputTab; xmlParserInputPtr input = NULL; - xmlCharEncoding enc; - int oldcharset; const xmlChar *oldencoding; int oldprogressive; unsigned long consumed; @@ -410,7 +394,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, oldinputNr = ctxt->inputNr; oldinputMax = ctxt->inputMax; oldinputTab = ctxt->inputTab; - oldcharset = ctxt->charset; oldencoding = ctxt->encoding; oldprogressive = ctxt->progressive; ctxt->encoding = NULL; @@ -425,7 +408,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, ctxt->inputNr = oldinputNr; ctxt->inputMax = oldinputMax; ctxt->inputTab = oldinputTab; - ctxt->charset = oldcharset; ctxt->encoding = oldencoding; ctxt->progressive = oldprogressive; return; @@ -435,14 +417,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, ctxt->input = NULL; xmlPushInput(ctxt, input);
- /* - * On the fly encoding conversion if needed - */ - if (ctxt->input->length >= 4) { - enc = xmlDetectCharEncoding(ctxt->input->cur, 4); - xmlSwitchEncoding(ctxt, enc); - } - if (input->filename == NULL) input->filename = (char *) xmlCanonicPath(SystemID); input->line = 1; @@ -484,7 +458,6 @@ xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, ctxt->inputNr = oldinputNr; ctxt->inputMax = oldinputMax; ctxt->inputTab = oldinputTab; - ctxt->charset = oldcharset; if ((ctxt->encoding != NULL) && ((ctxt->dict == NULL) || (!xmlDictOwns(ctxt->dict, ctxt->encoding)))) @@ -525,11 +498,6 @@ xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId
URI = xmlBuildURI(systemId, (const xmlChar *) base);
-#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId); -#endif - ret = xmlLoadExternalEntity((const char *) URI, (const char *) publicId, ctxt); if (URI != NULL) @@ -553,10 +521,6 @@ xmlSAX2GetEntity(void *ctx, const xmlChar *name) xmlEntityPtr ret = NULL;
if (ctx == NULL) return(NULL); -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2GetEntity(%s)\n", name); -#endif
if (ctxt->inSubset == 0) { ret = xmlGetPredefinedEntity(name); @@ -603,10 +567,6 @@ xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name) xmlEntityPtr ret;
if (ctx == NULL) return(NULL); -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2GetParameterEntity(%s)\n", name); -#endif
ret = xmlGetParameterEntity(ctxt->myDoc, name); return(ret); @@ -632,11 +592,6 @@ xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type, xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
if (ctx == NULL) return; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n", - name, type, publicId, systemId, content); -#endif if (ctxt->inSubset == 1) { ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content); @@ -709,11 +664,6 @@ xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname, if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return;
-#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n", - elem, fullname, type, def, defaultValue); -#endif if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) && (type != XML_ATTRIBUTE_ID)) { /* @@ -779,11 +729,6 @@ xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type, if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return;
-#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type); -#endif - if (ctxt->inSubset == 1) elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name, (xmlElementTypeVal) type, content); @@ -828,11 +773,6 @@ xmlSAX2NotationDecl(void *ctx, const xmlChar *name, if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return;
-#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId); -#endif - if ((publicId == NULL) && (systemId == NULL)) { xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING, "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", @@ -877,11 +817,6 @@ xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name, xmlEntityPtr ent; xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; if (ctx == NULL) return; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n", - name, publicId, systemId, notationName); -#endif if (ctxt->inSubset == 1) { ent = xmlAddDocEntity(ctxt->myDoc, name, XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, @@ -940,11 +875,6 @@ xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name, void xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED) { - /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2SetDocumentLocator()\n"); -#endif }
/** @@ -961,10 +891,6 @@ xmlSAX2StartDocument(void *ctx)
if (ctx == NULL) return;
-#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2StartDocument()\n"); -#endif if (ctxt->html) { #ifdef LIBXML_HTML_ENABLED if (ctxt->myDoc == NULL) @@ -990,10 +916,6 @@ xmlSAX2StartDocument(void *ctx) if (ctxt->options & XML_PARSE_OLD10) doc->properties |= XML_DOC_OLD10; doc->parseFlags = ctxt->options; - if (ctxt->encoding != NULL) - doc->encoding = xmlStrdup(ctxt->encoding); - else - doc->encoding = NULL; doc->standalone = ctxt->standalone; } else { xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument"); @@ -1022,10 +944,8 @@ void xmlSAX2EndDocument(void *ctx) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2EndDocument()\n"); -#endif + xmlDocPtr doc; + if (ctx == NULL) return; #ifdef LIBXML_VALID_ENABLED if (ctxt->validate && ctxt->wellFormed && @@ -1033,23 +953,15 @@ xmlSAX2EndDocument(void *ctx) ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc); #endif /* LIBXML_VALID_ENABLED */
- /* - * Grab the encoding if it was added on-the-fly - */ - if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) && - (ctxt->myDoc->encoding == NULL)) { - ctxt->myDoc->encoding = ctxt->encoding; - ctxt->encoding = NULL; - } - if ((ctxt->inputTab != NULL) && - (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) && - (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) && - (ctxt->myDoc->encoding == NULL)) { - ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding); - } - if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) && - (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) { - ctxt->myDoc->charset = ctxt->charset; + doc = ctxt->myDoc; + if ((doc != NULL) && (doc->encoding == NULL)) { + const xmlChar *encoding = xmlGetActualEncoding(ctxt); + + if (encoding != NULL) { + doc->encoding = xmlStrdup(encoding); + if (doc->encoding == NULL) + xmlSAX2ErrMemory(ctxt, "xmlSAX2EndDocument"); + } } }
@@ -1612,11 +1524,6 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) int i;
if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return; - parent = ctxt->node; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2StartElement(%s)\n", fullname); -#endif
/* * First check on validity: @@ -1654,14 +1561,6 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement"); return; } - if (ctxt->myDoc->children == NULL) { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name); -#endif - xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); - } else if (parent == NULL) { - parent = ctxt->myDoc->children; - } ctxt->nodemem = -1; if (ctxt->linenumbers) { if (ctxt->input != NULL) { @@ -1672,12 +1571,14 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) } }
+ /* Initialize parent before pushing node */ + parent = ctxt->node; + if (parent == NULL) + parent = (xmlNodePtr) ctxt->myDoc; + /* * We are parsing a new node. */ -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name); -#endif if (nodePush(ctxt, ret) < 0) { xmlUnlinkNode(ret); xmlFreeNode(ret); @@ -1689,22 +1590,7 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) /* * Link the child element */ - if (parent != NULL) { - if (parent->type == XML_ELEMENT_NODE) { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "adding child %s to %s\n", name, parent->name); -#endif - xmlAddChild(parent, ret); - } else { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "adding sibling %s to ", name); - xmlDebugDumpOneNode(stderr, parent, 0); -#endif - xmlAddSibling(parent, ret); - } - } + xmlAddChild(parent, ret);
if (!ctxt->html) { /* @@ -1819,16 +1705,8 @@ void xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; - xmlNodePtr cur;
if (ctx == NULL) return; - cur = ctxt->node; -#ifdef DEBUG_SAX - if (name == NULL) - xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n"); - else - xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name); -#endif
ctxt->nodemem = -1;
@@ -1836,16 +1714,13 @@ xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED) if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc && ctxt->myDoc->intSubset) ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, - cur); + ctxt->node); #endif /* LIBXML_VALID_ENABLED */
/* * end of parsing of this node. */ -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name); -#endif nodePop(ctxt); } #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */ @@ -1921,18 +1796,6 @@ skip: } else ret->content = (xmlChar *) intern;
- if (ctxt->linenumbers) { - if (ctxt->input != NULL) { - if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX) - ret->line = ctxt->input->line; - else { - ret->line = USHRT_MAX; - if (ctxt->options & XML_PARSE_BIG_LINES) - ret->psvi = (void *) (ptrdiff_t) ctxt->input->line; - } - } - } - if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(ret); return(ret); @@ -1982,8 +1845,10 @@ decode: * The default handling is to convert the attribute into an * DOM subtree and past it in a new xmlAttr element added to * the element. + * + * Returns the new attribute or NULL in case of error. */ -static void +static xmlAttrPtr xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, const xmlChar * localname, const xmlChar * prefix, @@ -1997,8 +1862,12 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, /* * Note: if prefix == NULL, the attribute is not in the default namespace */ - if (prefix != NULL) - namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); + if (prefix != NULL) { + namespace = xmlParserNsLookupSax(ctxt, prefix); + if ((namespace == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { + namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); + } + }
/* * allocate the node @@ -2007,42 +1876,37 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, ret = ctxt->freeAttrs; ctxt->freeAttrs = ret->next; ctxt->freeAttrsNr--; - memset(ret, 0, sizeof(xmlAttr)); - ret->type = XML_ATTRIBUTE_NODE; + } else { + ret = xmlMalloc(sizeof(*ret)); + if (ret == NULL) { + xmlSAX2ErrMemory(ctxt, NULL); + return(NULL); + } + }
- ret->parent = ctxt->node; - ret->doc = ctxt->myDoc; - ret->ns = namespace; + memset(ret, 0, sizeof(xmlAttr)); + ret->type = XML_ATTRIBUTE_NODE;
- if (ctxt->dictNames) - ret->name = localname; - else - ret->name = xmlStrdup(localname); + /* + * xmlParseBalancedChunkMemoryRecover had a bug that could result in + * a mismatch between ctxt->node->doc and ctxt->myDoc. We use + * ctxt->node->doc here, but we should somehow make sure that the + * document pointers match. + */
- /* link at the end to preserve order, TODO speed up with a last */ - if (ctxt->node->properties == NULL) { - ctxt->node->properties = ret; - } else { - xmlAttrPtr prev = ctxt->node->properties; + /* assert(ctxt->node->doc == ctxt->myDoc); */
- while (prev->next != NULL) prev = prev->next; - prev->next = ret; - ret->prev = prev; - } + ret->parent = ctxt->node; + ret->doc = ctxt->node->doc; + ret->ns = namespace;
- if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) - xmlRegisterNodeDefaultValue((xmlNodePtr)ret); - } else { - if (ctxt->dictNames) - ret = xmlNewNsPropEatName(ctxt->node, namespace, - (xmlChar *) localname, NULL); - else - ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL); - if (ret == NULL) { - xmlErrMemory(ctxt, "xmlSAX2AttributeNs"); - return; - } - } + if (ctxt->dictNames) + ret->name = localname; + else + ret->name = xmlStrdup(localname); + + if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) + xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { xmlNodePtr tmp; @@ -2174,15 +2038,11 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, * * Open issue: normalization of the value. */ -#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED) -#ifdef LIBXML_VALID_ENABLED if (xmlValidateNCName(content, 1) != 0) { xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, "xml:id : attribute value %s is not an NCName\n", (const char *) content, NULL); } -#endif -#endif xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) { xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret); @@ -2192,6 +2052,8 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, } if (dup != NULL) xmlFree(dup); + + return(ret); }
/** @@ -2231,7 +2093,6 @@ xmlSAX2StartElementNs(void *ctx, int i, j;
if (ctx == NULL) return; - parent = ctxt->node; /* * First check on validity: */ @@ -2309,9 +2170,6 @@ xmlSAX2StartElementNs(void *ctx, } }
- if (parent == NULL) { - xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); - } /* * Build the namespace list */ @@ -2336,6 +2194,9 @@ xmlSAX2StartElementNs(void *ctx, */ continue; } + + xmlParserNsUpdateSax(ctxt, pref, ns); + #ifdef LIBXML_VALID_ENABLED if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && ctxt->myDoc && ctxt->myDoc->intSubset) { @@ -2346,6 +2207,11 @@ xmlSAX2StartElementNs(void *ctx, } ctxt->nodemem = -1;
+ /* Initialize parent before pushing node */ + parent = ctxt->node; + if (parent == NULL) + parent = (xmlNodePtr) ctxt->myDoc; + /* * We are parsing a new node. */ @@ -2358,13 +2224,7 @@ xmlSAX2StartElementNs(void *ctx, /* * Link the child element */ - if (parent != NULL) { - if (parent->type == XML_ELEMENT_NODE) { - xmlAddChild(parent, ret); - } else { - xmlAddSibling(parent, ret); - } - } + xmlAddChild(parent, ret);
/* * Insert the defaulted attributes from the DTD only if requested: @@ -2378,7 +2238,7 @@ xmlSAX2StartElementNs(void *ctx, * Note that, if prefix is NULL, this searches for the default Ns */ if ((URI != NULL) && (ret->ns == NULL)) { - ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix); + ret->ns = xmlParserNsLookupSax(ctxt, prefix); if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix); } @@ -2404,7 +2264,11 @@ xmlSAX2StartElementNs(void *ctx, * process all the other attributes */ if (nb_attributes > 0) { + xmlAttrPtr prev = NULL; + for (j = 0,i = 0;i < nb_attributes;i++,j+=5) { + xmlAttrPtr attr = NULL; + /* * Handle the rare case of an undefined attribute prefix */ @@ -2415,23 +2279,38 @@ xmlSAX2StartElementNs(void *ctx, fullname = xmlDictQLookup(ctxt->dict, attributes[j+1], attributes[j]); if (fullname != NULL) { - xmlSAX2AttributeNs(ctxt, fullname, NULL, - attributes[j+3], attributes[j+4]); - continue; + attr = xmlSAX2AttributeNs(ctxt, fullname, NULL, + attributes[j+3], + attributes[j+4]); + goto have_attr; } } else { lname = xmlBuildQName(attributes[j], attributes[j+1], NULL, 0); if (lname != NULL) { - xmlSAX2AttributeNs(ctxt, lname, NULL, - attributes[j+3], attributes[j+4]); + attr = xmlSAX2AttributeNs(ctxt, lname, NULL, + attributes[j+3], + attributes[j+4]); xmlFree(lname); - continue; + goto have_attr; } } } - xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1], - attributes[j+3], attributes[j+4]); + attr = xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1], + attributes[j+3], attributes[j+4]); +have_attr: + if (attr == NULL) + continue; + + /* link at the end to preserve order */ + if (prev == NULL) { + ctxt->node->properties = attr; + } else { + prev->next = attr; + attr->prev = prev; + } + + prev = attr; } }
@@ -2503,18 +2382,7 @@ xmlSAX2Reference(void *ctx, const xmlChar *name) xmlNodePtr ret;
if (ctx == NULL) return; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2Reference(%s)\n", name); -#endif - if (name[0] == '#') - ret = xmlNewCharRef(ctxt->myDoc, name); - else - ret = xmlNewReference(ctxt->myDoc, name); -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name); -#endif + ret = xmlNewReference(ctxt->myDoc, name); if (xmlAddChild(ctxt->node, ret) == NULL) { xmlFreeNode(ret); } @@ -2536,10 +2404,6 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, xmlNodePtr lastChild;
if (ctxt == NULL) return; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len); -#endif /* * Handle the data if any. If there is no child * add it as content, otherwise if the last child is text, @@ -2547,17 +2411,9 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, */
if (ctxt->node == NULL) { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "add chars: ctxt->node == NULL !\n"); -#endif return; } lastChild = ctxt->node->last; -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "add chars to %s \n", ctxt->node->name); -#endif
/* * Here we needed an accelerator mechanism in case of very large @@ -2656,6 +2512,19 @@ xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len, } } } + + if ((lastChild != NULL) && + (type == XML_TEXT_NODE) && + (ctxt->linenumbers) && + (ctxt->input != NULL)) { + if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX) + lastChild->line = ctxt->input->line; + else { + lastChild->line = USHRT_MAX; + if (ctxt->options & XML_PARSE_BIG_LINES) + lastChild->psvi = (void *) (ptrdiff_t) ctxt->input->line; + } + } }
/** @@ -2684,11 +2553,6 @@ xmlSAX2Characters(void *ctx, const xmlChar *ch, int len) void xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) { - /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len); -#endif }
/** @@ -2709,10 +2573,6 @@ xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
if (ctx == NULL) return; parent = ctxt->node; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, - "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data); -#endif
ret = xmlNewDocPI(ctxt->myDoc, target, data); if (ret == NULL) return; @@ -2733,25 +2593,12 @@ xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target, return; } if (parent == NULL) { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "Setting PI %s as root\n", target); -#endif xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); return; } if (parent->type == XML_ELEMENT_NODE) { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "adding PI %s child to %s\n", target, parent->name); -#endif xmlAddChild(parent, ret); } else { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "adding PI %s sibling to ", target); - xmlDebugDumpOneNode(stderr, parent, 0); -#endif xmlAddSibling(parent, ret); } } @@ -2772,9 +2619,6 @@ xmlSAX2Comment(void *ctx, const xmlChar *value)
if (ctx == NULL) return; parent = ctxt->node; -#ifdef DEBUG_SAX - xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value); -#endif ret = xmlNewDocComment(ctxt->myDoc, value); if (ret == NULL) return; if (ctxt->linenumbers) { @@ -2794,25 +2638,12 @@ xmlSAX2Comment(void *ctx, const xmlChar *value) return; } if (parent == NULL) { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "Setting xmlSAX2Comment as root\n"); -#endif xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); return; } if (parent->type == XML_ELEMENT_NODE) { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "adding xmlSAX2Comment child to %s\n", parent->name); -#endif xmlAddChild(parent, ret); } else { -#ifdef DEBUG_SAX_TREE - xmlGenericError(xmlGenericErrorContext, - "adding xmlSAX2Comment sibling to "); - xmlDebugDumpOneNode(stderr, parent, 0); -#endif xmlAddSibling(parent, ret); } } @@ -2874,20 +2705,23 @@ xmlSAXVersion(xmlSAXHandler *hdlr, int version) { if (hdlr == NULL) return(-1); if (version == 2) { - hdlr->startElement = NULL; - hdlr->endElement = NULL; hdlr->startElementNs = xmlSAX2StartElementNs; hdlr->endElementNs = xmlSAX2EndElementNs; hdlr->serror = NULL; hdlr->initialized = XML_SAX2_MAGIC; #ifdef LIBXML_SAX1_ENABLED } else if (version == 1) { - hdlr->startElement = xmlSAX2StartElement; - hdlr->endElement = xmlSAX2EndElement; hdlr->initialized = 1; #endif /* LIBXML_SAX1_ENABLED */ } else return(-1); +#ifdef LIBXML_SAX1_ENABLED + hdlr->startElement = xmlSAX2StartElement; + hdlr->endElement = xmlSAX2EndElement; +#else + hdlr->startElement = NULL; + hdlr->endElement = NULL; +#endif /* LIBXML_SAX1_ENABLED */ hdlr->internalSubset = xmlSAX2InternalSubset; hdlr->externalSubset = xmlSAX2ExternalSubset; hdlr->isStandalone = xmlSAX2IsStandalone; diff --git a/libs/xml2/buf.c b/libs/xml2/buf.c index f876ea99fa9..469fe64d524 100644 --- a/libs/xml2/buf.c +++ b/libs/xml2/buf.c @@ -20,8 +20,6 @@ #include <ctype.h> #include <stdlib.h>
-#include <libxml/tree.h> -#include <libxml/globals.h> #include <libxml/tree.h> #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
@@ -225,10 +223,6 @@ xmlBufDetach(xmlBufPtr buf) { int xmlBufGetAllocationScheme(xmlBufPtr buf) { if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufGetAllocationScheme: buf == NULL\n"); -#endif return(-1); } return(buf->alloc); @@ -247,10 +241,6 @@ int xmlBufSetAllocationScheme(xmlBufPtr buf, xmlBufferAllocationScheme scheme) { if ((buf == NULL) || (buf->error != 0)) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufSetAllocationScheme: buf == NULL or in error\n"); -#endif return(-1); } if (buf->alloc == XML_BUFFER_ALLOC_IO) @@ -285,10 +275,6 @@ xmlBufSetAllocationScheme(xmlBufPtr buf, void xmlBufFree(xmlBufPtr buf) { if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufFree: buf == NULL\n"); -#endif return; }
@@ -479,17 +465,9 @@ xmlBufDump(FILE *file, xmlBufPtr buf) { size_t ret;
if ((buf == NULL) || (buf->error != 0)) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufDump: buf == NULL or in error\n"); -#endif return(0); } if (buf->content == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufDump: buf->content == NULL\n"); -#endif return(0); } CHECK_COMPAT(buf) @@ -785,10 +763,6 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { CHECK_COMPAT(buf)
if (len < -1) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufAdd: len < 0\n"); -#endif return -1; } if (len == 0) return 0; @@ -882,10 +856,6 @@ xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string) { CHECK_COMPAT(buf) if (xmlStrchr(string, '"')) { if (xmlStrchr(string, ''')) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufWriteQuotedString: string contains quote and double-quotes !\n"); -#endif xmlBufCCat(buf, """); base = cur = string; while(*cur != 0){ @@ -1047,8 +1017,12 @@ xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer) { */ int xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) { - if ((input == NULL) || (buf == NULL) || (buf->error)) + if (input == NULL) + return(-1); + if ((buf == NULL) || (buf->error)) { + input->base = input->cur = input->end = BAD_CAST ""; return(-1); + } CHECK_COMPAT(buf) input->base = input->cur = buf->content; input->end = &buf->content[buf->use]; @@ -1056,39 +1030,10 @@ xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input) { }
/** - * xmlBufGetInputBase: + * xmlBufUpdateInput: * @buf: an xmlBufPtr * @input: an xmlParserInputPtr - * - * Get the base of the @input relative to the beginning of the buffer - * - * Returns the size_t corresponding to the displacement - */ -size_t -xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) { - size_t base; - - if ((input == NULL) || (buf == NULL) || (buf->error)) - return(0); - CHECK_COMPAT(buf) - base = input->base - buf->content; - /* - * We could do some pointer arithmetic checks but that's probably - * sufficient. - */ - if (base > buf->size) { - xmlBufOverflowError(buf, "Input reference outside of the buffer"); - base = 0; - } - return(base); -} - -/** - * xmlBufSetInputBaseCur: - * @buf: an xmlBufPtr - * @input: an xmlParserInputPtr - * @base: the base value relative to the beginning of the buffer - * @cur: the cur value relative to the beginning of the buffer + * @pos: the cur value relative to the beginning of the buffer * * Update the input to use the base and cur relative to the buffer * after a possible reallocation of its content @@ -1096,18 +1041,20 @@ xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) { * Returns -1 in case of error, 0 otherwise */ int -xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input, - size_t base, size_t cur) { +xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos) { if (input == NULL) return(-1); + /* + * TODO: It might be safer to keep using the buffer content if there + * was an error. + */ if ((buf == NULL) || (buf->error)) { input->base = input->cur = input->end = BAD_CAST ""; return(-1); } CHECK_COMPAT(buf) - input->base = &buf->content[base]; - input->cur = input->base + cur; + input->base = buf->content; + input->cur = input->base + pos; input->end = &buf->content[buf->use]; return(0); } - diff --git a/libs/xml2/catalog.c b/libs/xml2/catalog.c index 24a49f3d7fd..945ea2c8776 100644 --- a/libs/xml2/catalog.c +++ b/libs/xml2/catalog.c @@ -36,7 +36,6 @@ #include <libxml/catalog.h> #include <libxml/xmlerror.h> #include <libxml/threads.h> -#include <libxml/globals.h>
#include "private/buf.h" #include "private/error.h" diff --git a/libs/xml2/debugXML.c b/libs/xml2/debugXML.c index 3bb19304ff3..303515ec8c6 100644 --- a/libs/xml2/debugXML.c +++ b/libs/xml2/debugXML.c @@ -18,12 +18,10 @@ #include <libxml/tree.h> #include <libxml/parser.h> #include <libxml/parserInternals.h> -#include <libxml/valid.h> #include <libxml/debugXML.h> #include <libxml/HTMLtree.h> #include <libxml/HTMLparser.h> #include <libxml/xmlerror.h> -#include <libxml/globals.h> #include <libxml/xpathInternals.h> #include <libxml/uri.h> #ifdef LIBXML_SCHEMAS_ENABLED diff --git a/libs/xml2/dict.c b/libs/xml2/dict.c index d7fd1a068a8..217e5607f69 100644 --- a/libs/xml2/dict.c +++ b/libs/xml2/dict.c @@ -20,83 +20,25 @@ #include "libxml.h"
#include <limits.h> -#include <stdlib.h> +#include <string.h> #include <time.h>
#include "private/dict.h" #include "private/threads.h"
-/* - * Following http://www.ocert.org/advisories/ocert-2011-003.html - * it seems that having hash randomization might be a good idea - * when using XML with untrusted data - * Note1: that it works correctly only if compiled with WITH_BIG_KEY - * which is the default. - * Note2: the fast function used for a small dict won't protect very - * well but since the attack is based on growing a very big hash - * list we will use the BigKey algo as soon as the hash size grows - * over MIN_DICT_SIZE so this actually works - */ -#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) -#define DICT_RANDOMIZATION -#endif - -#include <string.h> -#ifdef HAVE_STDINT_H -#include <stdint.h> -#else -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#elif defined(_WIN32) -typedef unsigned __int32 uint32_t; -#endif -#endif -#include <libxml/tree.h> +#include <libxml/parser.h> #include <libxml/dict.h> #include <libxml/xmlmemory.h> -#include <libxml/xmlerror.h> -#include <libxml/globals.h> - -/* #define DEBUG_GROW */ -/* #define DICT_DEBUG_PATTERNS */ - -#define MAX_HASH_LEN 3 -#define MIN_DICT_SIZE 128 -#define MAX_DICT_HASH 8 * 2048 -#define WITH_BIG_KEY - -#ifdef WITH_BIG_KEY -#define xmlDictComputeKey(dict, name, len) \ - (((dict)->size == MIN_DICT_SIZE) ? \ - xmlDictComputeFastKey(name, len, (dict)->seed) : \ - xmlDictComputeBigKey(name, len, (dict)->seed)) - -#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ - (((prefix) == NULL) ? \ - (xmlDictComputeKey(dict, name, len)) : \ - (((dict)->size == MIN_DICT_SIZE) ? \ - xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) : \ - xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed))) - -#else /* !WITH_BIG_KEY */ -#define xmlDictComputeKey(dict, name, len) \ - xmlDictComputeFastKey(name, len, (dict)->seed) -#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ - xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) -#endif /* WITH_BIG_KEY */ +#include <libxml/xmlstring.h>
-/* - * An entry in the dictionary - */ -typedef struct _xmlDictEntry xmlDictEntry; -typedef xmlDictEntry *xmlDictEntryPtr; -struct _xmlDictEntry { - struct _xmlDictEntry *next; - const xmlChar *name; - unsigned int len; - int valid; - unsigned long okey; -}; +#ifndef SIZE_MAX + #define SIZE_MAX ((size_t) -1) +#endif + +#define MAX_FILL_NUM 7 +#define MAX_FILL_DENOM 8 +#define MIN_HASH_SIZE 8 +#define MAX_HASH_SIZE (1u << 31)
typedef struct _xmlDictStrings xmlDictStrings; typedef xmlDictStrings *xmlDictStringsPtr; @@ -108,20 +50,23 @@ struct _xmlDictStrings { size_t nbStrings; xmlChar array[1]; }; + +typedef xmlHashedString xmlDictEntry; + /* * The entire dictionary */ struct _xmlDict { int ref_counter;
- struct _xmlDictEntry *dict; + xmlDictEntry *table; size_t size; unsigned int nbElems; xmlDictStringsPtr strings;
struct _xmlDict *subdict; /* used for randomization */ - int seed; + unsigned seed; /* used to impose a limit on size */ size_t limit; }; @@ -132,60 +77,29 @@ struct _xmlDict { */ static xmlMutex xmlDictMutex;
-#ifdef DICT_RANDOMIZATION -#ifdef HAVE_RAND_R -/* - * Internal data for random function, protected by xmlDictMutex - */ -static unsigned int rand_seed = 0; -#endif -#endif - /** * xmlInitializeDict: * * DEPRECATED: Alias for xmlInitParser. + * + * Returns 0. */ -int xmlInitializeDict(void) { +int +xmlInitializeDict(void) { xmlInitParser(); return(0); }
/** - * __xmlInitializeDict: + * xmlInitDictInternal: * - * This function is not public - * Do the dictionary mutex initialization. + * Initialize mutex. */ -int __xmlInitializeDict(void) { +void +xmlInitDictInternal(void) { xmlInitMutex(&xmlDictMutex); - -#ifdef DICT_RANDOMIZATION -#ifdef HAVE_RAND_R - rand_seed = time(NULL); - rand_r(& rand_seed); -#else - srand(time(NULL)); -#endif -#endif - return(1); }
-#ifdef DICT_RANDOMIZATION -int __xmlRandom(void) { - int ret; - - xmlMutexLock(&xmlDictMutex); -#ifdef HAVE_RAND_R - ret = rand_r(& rand_seed); -#else - ret = rand(); -#endif - xmlMutexUnlock(&xmlDictMutex); - return(ret); -} -#endif - /** * xmlDictCleanup: * @@ -225,9 +139,6 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) { size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ size_t limit = 0;
-#ifdef DICT_DEBUG_PATTERNS - fprintf(stderr, "-"); -#endif pool = dict->strings; while (pool != NULL) { if ((size_t)(pool->end - pool->free) > namelen) @@ -244,10 +155,20 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) { return(NULL); }
- if (size == 0) size = 1000; - else size *= 4; /* exponential growth */ - if (size < 4 * namelen) - size = 4 * namelen; /* just in case ! */ + if (size == 0) { + size = 1000; + } else { + if (size < (SIZE_MAX - sizeof(xmlDictStrings)) / 4) + size *= 4; /* exponential growth */ + else + size = SIZE_MAX - sizeof(xmlDictStrings); + } + if (size / 4 < namelen) { + if ((size_t) namelen + 0 < (SIZE_MAX - sizeof(xmlDictStrings)) / 4) + size = 4 * (size_t) namelen; /* just in case ! */ + else + return(NULL); + } pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); if (pool == NULL) return(NULL); @@ -257,9 +178,6 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) { pool->end = &pool->array[size]; pool->next = dict->strings; dict->strings = pool; -#ifdef DICT_DEBUG_PATTERNS - fprintf(stderr, "+"); -#endif } found_pool: ret = pool->free; @@ -291,11 +209,6 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen, size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ size_t limit = 0;
- if (prefix == NULL) return(xmlDictAddString(dict, name, namelen)); - -#ifdef DICT_DEBUG_PATTERNS - fprintf(stderr, "="); -#endif pool = dict->strings; while (pool != NULL) { if ((size_t)(pool->end - pool->free) > namelen + plen + 1) @@ -325,9 +238,6 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen, pool->end = &pool->array[size]; pool->next = dict->strings; dict->strings = pool; -#ifdef DICT_DEBUG_PATTERNS - fprintf(stderr, "+"); -#endif } found_pool: ret = pool->free; @@ -341,212 +251,6 @@ found_pool: return(ret); }
-#ifdef WITH_BIG_KEY -/* - * xmlDictComputeBigKey: - * - * Calculate a hash key using a good hash function that works well for - * larger hash table sizes. - * - * Hash function by "One-at-a-Time Hash" see - * http://burtleburtle.net/bob/hash/doobs.html - */ - -#ifdef __clang__ -ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") -ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") -#endif -static uint32_t -xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) { - uint32_t hash; - int i; - - if (namelen <= 0 || data == NULL) return(0); - - hash = seed; - - for (i = 0;i < namelen; i++) { - hash += data[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - - return hash; -} - -/* - * xmlDictComputeBigQKey: - * - * Calculate a hash key for two strings using a good hash function - * that works well for larger hash table sizes. - * - * Hash function by "One-at-a-Time Hash" see - * http://burtleburtle.net/bob/hash/doobs.html - * - * Neither of the two strings must be NULL. - */ -#ifdef __clang__ -ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") -ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") -#endif -static unsigned long -xmlDictComputeBigQKey(const xmlChar *prefix, int plen, - const xmlChar *name, int len, int seed) -{ - uint32_t hash; - int i; - - hash = seed; - - for (i = 0;i < plen; i++) { - hash += prefix[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += ':'; - hash += (hash << 10); - hash ^= (hash >> 6); - - for (i = 0;i < len; i++) { - hash += name[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - - return hash; -} -#endif /* WITH_BIG_KEY */ - -/* - * xmlDictComputeFastKey: - * - * Calculate a hash key using a fast hash function that works well - * for low hash table fill. - */ -static unsigned long -xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) { - unsigned long value = seed; - - if ((name == NULL) || (namelen <= 0)) - return(value); - value += *name; - value <<= 5; - if (namelen > 10) { - value += name[namelen - 1]; - namelen = 10; - } - switch (namelen) { - case 10: value += name[9]; - /* Falls through. */ - case 9: value += name[8]; - /* Falls through. */ - case 8: value += name[7]; - /* Falls through. */ - case 7: value += name[6]; - /* Falls through. */ - case 6: value += name[5]; - /* Falls through. */ - case 5: value += name[4]; - /* Falls through. */ - case 4: value += name[3]; - /* Falls through. */ - case 3: value += name[2]; - /* Falls through. */ - case 2: value += name[1]; - /* Falls through. */ - default: break; - } - return(value); -} - -/* - * xmlDictComputeFastQKey: - * - * Calculate a hash key for two strings using a fast hash function - * that works well for low hash table fill. - * - * Neither of the two strings must be NULL. - */ -static unsigned long -xmlDictComputeFastQKey(const xmlChar *prefix, int plen, - const xmlChar *name, int len, int seed) -{ - unsigned long value = seed; - - if (plen == 0) - value += 30 * ':'; - else - value += 30 * (*prefix); - - if (len > 10) { - int offset = len - (plen + 1 + 1); - if (offset < 0) - offset = len - (10 + 1); - value += name[offset]; - len = 10; - if (plen > 10) - plen = 10; - } - switch (plen) { - case 10: value += prefix[9]; - /* Falls through. */ - case 9: value += prefix[8]; - /* Falls through. */ - case 8: value += prefix[7]; - /* Falls through. */ - case 7: value += prefix[6]; - /* Falls through. */ - case 6: value += prefix[5]; - /* Falls through. */ - case 5: value += prefix[4]; - /* Falls through. */ - case 4: value += prefix[3]; - /* Falls through. */ - case 3: value += prefix[2]; - /* Falls through. */ - case 2: value += prefix[1]; - /* Falls through. */ - case 1: value += prefix[0]; - /* Falls through. */ - default: break; - } - len -= plen; - if (len > 0) { - value += ':'; - len--; - } - switch (len) { - case 10: value += name[9]; - /* Falls through. */ - case 9: value += name[8]; - /* Falls through. */ - case 8: value += name[7]; - /* Falls through. */ - case 7: value += name[6]; - /* Falls through. */ - case 6: value += name[5]; - /* Falls through. */ - case 5: value += name[4]; - /* Falls through. */ - case 4: value += name[3]; - /* Falls through. */ - case 3: value += name[2]; - /* Falls through. */ - case 2: value += name[1]; - /* Falls through. */ - case 1: value += name[0]; - /* Falls through. */ - default: break; - } - return(value); -} - /** * xmlDictCreate: * @@ -560,32 +264,22 @@ xmlDictCreate(void) {
xmlInitParser();
-#ifdef DICT_DEBUG_PATTERNS - fprintf(stderr, "C"); -#endif - dict = xmlMalloc(sizeof(xmlDict)); - if (dict) { - dict->ref_counter = 1; - dict->limit = 0; - - dict->size = MIN_DICT_SIZE; - dict->nbElems = 0; - dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry)); - dict->strings = NULL; - dict->subdict = NULL; - if (dict->dict) { - memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry)); -#ifdef DICT_RANDOMIZATION - dict->seed = __xmlRandom(); -#else - dict->seed = 0; + if (dict == NULL) + return(NULL); + dict->ref_counter = 1; + dict->limit = 0; + + dict->size = 0; + dict->nbElems = 0; + dict->table = NULL; + dict->strings = NULL; + dict->subdict = NULL; + dict->seed = xmlRandom(); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + dict->seed = 0; #endif - return(dict); - } - xmlFree(dict); - } - return(NULL); + return(dict); }
/** @@ -604,9 +298,6 @@ xmlDictCreateSub(xmlDictPtr sub) { xmlDictPtr dict = xmlDictCreate();
if ((dict != NULL) && (sub != NULL)) { -#ifdef DICT_DEBUG_PATTERNS - fprintf(stderr, "R"); -#endif dict->seed = sub->seed; dict->subdict = sub; xmlDictReference(dict->subdict); @@ -631,141 +322,6 @@ xmlDictReference(xmlDictPtr dict) { return(0); }
-/** - * xmlDictGrow: - * @dict: the dictionary - * @size: the new size of the dictionary - * - * resize the dictionary - * - * Returns 0 in case of success, -1 in case of failure - */ -static int -xmlDictGrow(xmlDictPtr dict, size_t size) { - unsigned long key, okey; - size_t oldsize, i; - xmlDictEntryPtr iter, next; - struct _xmlDictEntry *olddict; -#ifdef DEBUG_GROW - unsigned long nbElem = 0; -#endif - int ret = 0; - int keep_keys = 1; - - if (dict == NULL) - return(-1); - if (size < 8) - return(-1); - if (size > 8 * 2048) - return(-1); - -#ifdef DICT_DEBUG_PATTERNS - fprintf(stderr, "*"); -#endif - - oldsize = dict->size; - olddict = dict->dict; - if (olddict == NULL) - return(-1); - if (oldsize == MIN_DICT_SIZE) - keep_keys = 0; - - dict->dict = xmlMalloc(size * sizeof(xmlDictEntry)); - if (dict->dict == NULL) { - dict->dict = olddict; - return(-1); - } - memset(dict->dict, 0, size * sizeof(xmlDictEntry)); - dict->size = size; - - /* If the two loops are merged, there would be situations where - a new entry needs to allocated and data copied into it from - the main dict. It is nicer to run through the array twice, first - copying all the elements in the main array (less probability of - allocate) and then the rest, so we only free in the second loop. - */ - for (i = 0; i < oldsize; i++) { - if (olddict[i].valid == 0) - continue; - - if (keep_keys) - okey = olddict[i].okey; - else - okey = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len); - key = okey % dict->size; - - if (dict->dict[key].valid == 0) { - memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry)); - dict->dict[key].next = NULL; - dict->dict[key].okey = okey; - } else { - xmlDictEntryPtr entry; - - entry = xmlMalloc(sizeof(xmlDictEntry)); - if (entry != NULL) { - entry->name = olddict[i].name; - entry->len = olddict[i].len; - entry->okey = okey; - entry->next = dict->dict[key].next; - entry->valid = 1; - dict->dict[key].next = entry; - } else { - /* - * we don't have much ways to alert from here - * result is losing an entry and unicity guarantee - */ - ret = -1; - } - } -#ifdef DEBUG_GROW - nbElem++; -#endif - } - - for (i = 0; i < oldsize; i++) { - iter = olddict[i].next; - while (iter) { - next = iter->next; - - /* - * put back the entry in the new dict - */ - - if (keep_keys) - okey = iter->okey; - else - okey = xmlDictComputeKey(dict, iter->name, iter->len); - key = okey % dict->size; - if (dict->dict[key].valid == 0) { - memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry)); - dict->dict[key].next = NULL; - dict->dict[key].valid = 1; - dict->dict[key].okey = okey; - xmlFree(iter); - } else { - iter->next = dict->dict[key].next; - iter->okey = okey; - dict->dict[key].next = iter; - } - -#ifdef DEBUG_GROW - nbElem++; -#endif - - iter = next; - } - } - - xmlFree(olddict); - -#ifdef DEBUG_GROW - xmlGenericError(xmlGenericErrorContext, - "xmlDictGrow : from %lu to %lu, %u elems\n", oldsize, size, nbElem); -#endif - - return(ret); -} - /** * xmlDictFree: * @dict: the dictionary @@ -775,10 +331,6 @@ xmlDictGrow(xmlDictPtr dict, size_t size) { */ void xmlDictFree(xmlDictPtr dict) { - size_t i; - xmlDictEntryPtr iter; - xmlDictEntryPtr next; - int inside_dict = 0; xmlDictStringsPtr pool, nextp;
if (dict == NULL) @@ -798,22 +350,8 @@ xmlDictFree(xmlDictPtr dict) { xmlDictFree(dict->subdict); }
- if (dict->dict) { - for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) { - iter = &(dict->dict[i]); - if (iter->valid == 0) - continue; - inside_dict = 1; - while (iter) { - next = iter->next; - if (!inside_dict) - xmlFree(iter); - dict->nbElems--; - inside_dict = 0; - iter = next; - } - } - xmlFree(dict->dict); + if (dict->table) { + xmlFree(dict->table); } pool = dict->strings; while (pool != NULL) { @@ -824,357 +362,6 @@ xmlDictFree(xmlDictPtr dict) { xmlFree(dict); }
-/** - * xmlDictLookup: - * @dict: the dictionary - * @name: the name of the userdata - * @len: the length of the name, if -1 it is recomputed - * - * Add the @name to the dictionary @dict if not present. - * - * Returns the internal copy of the name or NULL in case of internal error - */ -const xmlChar * -xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { - unsigned long key, okey, nbi = 0; - xmlDictEntryPtr entry; - xmlDictEntryPtr insert; - const xmlChar *ret; - unsigned int l; - - if ((dict == NULL) || (name == NULL)) - return(NULL); - - if (len < 0) - l = strlen((const char *) name); - else - l = len; - - if (((dict->limit > 0) && (l >= dict->limit)) || - (l > INT_MAX / 2)) - return(NULL); - - /* - * Check for duplicate and insertion location. - */ - okey = xmlDictComputeKey(dict, name, l); - key = okey % dict->size; - if (dict->dict[key].valid == 0) { - insert = NULL; - } else { - for (insert = &(dict->dict[key]); insert->next != NULL; - insert = insert->next) { -#ifdef __GNUC__ - if ((insert->okey == okey) && (insert->len == l)) { - if (!memcmp(insert->name, name, l)) - return(insert->name); - } -#else - if ((insert->okey == okey) && (insert->len == l) && - (!xmlStrncmp(insert->name, name, l))) - return(insert->name); -#endif - nbi++; - } -#ifdef __GNUC__ - if ((insert->okey == okey) && (insert->len == l)) { - if (!memcmp(insert->name, name, l)) - return(insert->name); - } -#else - if ((insert->okey == okey) && (insert->len == l) && - (!xmlStrncmp(insert->name, name, l))) - return(insert->name); -#endif - } - - if (dict->subdict) { - unsigned long skey; - - /* we cannot always reuse the same okey for the subdict */ - if (((dict->size == MIN_DICT_SIZE) && - (dict->subdict->size != MIN_DICT_SIZE)) || - ((dict->size != MIN_DICT_SIZE) && - (dict->subdict->size == MIN_DICT_SIZE))) - skey = xmlDictComputeKey(dict->subdict, name, l); - else - skey = okey; - - key = skey % dict->subdict->size; - if (dict->subdict->dict[key].valid != 0) { - xmlDictEntryPtr tmp; - - for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; - tmp = tmp->next) { -#ifdef __GNUC__ - if ((tmp->okey == skey) && (tmp->len == l)) { - if (!memcmp(tmp->name, name, l)) - return(tmp->name); - } -#else - if ((tmp->okey == skey) && (tmp->len == l) && - (!xmlStrncmp(tmp->name, name, l))) - return(tmp->name); -#endif - nbi++; - } -#ifdef __GNUC__ - if ((tmp->okey == skey) && (tmp->len == l)) { - if (!memcmp(tmp->name, name, l)) - return(tmp->name); - } -#else - if ((tmp->okey == skey) && (tmp->len == l) && - (!xmlStrncmp(tmp->name, name, l))) - return(tmp->name); -#endif - } - key = okey % dict->size; - } - - ret = xmlDictAddString(dict, name, l); - if (ret == NULL) - return(NULL); - if (insert == NULL) { - entry = &(dict->dict[key]); - } else { - entry = xmlMalloc(sizeof(xmlDictEntry)); - if (entry == NULL) - return(NULL); - } - entry->name = ret; - entry->len = l; - entry->next = NULL; - entry->valid = 1; - entry->okey = okey; - - - if (insert != NULL) - insert->next = entry; - - dict->nbElems++; - - if ((nbi > MAX_HASH_LEN) && - (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) { - if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0) - return(NULL); - } - /* Note that entry may have been freed at this point by xmlDictGrow */ - - return(ret); -} - -/** - * xmlDictExists: - * @dict: the dictionary - * @name: the name of the userdata - * @len: the length of the name, if -1 it is recomputed - * - * Check if the @name exists in the dictionary @dict. - * - * Returns the internal copy of the name or NULL if not found. - */ -const xmlChar * -xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { - unsigned long key, okey; - xmlDictEntryPtr insert; - unsigned int l; - - if ((dict == NULL) || (name == NULL)) - return(NULL); - - if (len < 0) - l = strlen((const char *) name); - else - l = len; - if (((dict->limit > 0) && (l >= dict->limit)) || - (l > INT_MAX / 2)) - return(NULL); - - /* - * Check for duplicate and insertion location. - */ - okey = xmlDictComputeKey(dict, name, l); - key = okey % dict->size; - if (dict->dict[key].valid == 0) { - insert = NULL; - } else { - for (insert = &(dict->dict[key]); insert->next != NULL; - insert = insert->next) { -#ifdef __GNUC__ - if ((insert->okey == okey) && (insert->len == l)) { - if (!memcmp(insert->name, name, l)) - return(insert->name); - } -#else - if ((insert->okey == okey) && (insert->len == l) && - (!xmlStrncmp(insert->name, name, l))) - return(insert->name); -#endif - } -#ifdef __GNUC__ - if ((insert->okey == okey) && (insert->len == l)) { - if (!memcmp(insert->name, name, l)) - return(insert->name); - } -#else - if ((insert->okey == okey) && (insert->len == l) && - (!xmlStrncmp(insert->name, name, l))) - return(insert->name); -#endif - } - - if (dict->subdict) { - unsigned long skey; - - /* we cannot always reuse the same okey for the subdict */ - if (((dict->size == MIN_DICT_SIZE) && - (dict->subdict->size != MIN_DICT_SIZE)) || - ((dict->size != MIN_DICT_SIZE) && - (dict->subdict->size == MIN_DICT_SIZE))) - skey = xmlDictComputeKey(dict->subdict, name, l); - else - skey = okey; - - key = skey % dict->subdict->size; - if (dict->subdict->dict[key].valid != 0) { - xmlDictEntryPtr tmp; - - for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; - tmp = tmp->next) { -#ifdef __GNUC__ - if ((tmp->okey == skey) && (tmp->len == l)) { - if (!memcmp(tmp->name, name, l)) - return(tmp->name); - } -#else - if ((tmp->okey == skey) && (tmp->len == l) && - (!xmlStrncmp(tmp->name, name, l))) - return(tmp->name); -#endif - } -#ifdef __GNUC__ - if ((tmp->okey == skey) && (tmp->len == l)) { - if (!memcmp(tmp->name, name, l)) - return(tmp->name); - } -#else - if ((tmp->okey == skey) && (tmp->len == l) && - (!xmlStrncmp(tmp->name, name, l))) - return(tmp->name); -#endif - } - } - - /* not found */ - return(NULL); -} - -/** - * xmlDictQLookup: - * @dict: the dictionary - * @prefix: the prefix - * @name: the name - * - * Add the QName @prefix:@name to the hash @dict if not present. - * - * Returns the internal copy of the QName or NULL in case of internal error - */ -const xmlChar * -xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { - unsigned long okey, key, nbi = 0; - xmlDictEntryPtr entry; - xmlDictEntryPtr insert; - const xmlChar *ret; - unsigned int len, plen, l; - - if ((dict == NULL) || (name == NULL)) - return(NULL); - if (prefix == NULL) - return(xmlDictLookup(dict, name, -1)); - - l = len = strlen((const char *) name); - plen = strlen((const char *) prefix); - len += 1 + plen; - - /* - * Check for duplicate and insertion location. - */ - okey = xmlDictComputeQKey(dict, prefix, plen, name, l); - key = okey % dict->size; - if (dict->dict[key].valid == 0) { - insert = NULL; - } else { - for (insert = &(dict->dict[key]); insert->next != NULL; - insert = insert->next) { - if ((insert->okey == okey) && (insert->len == len) && - (xmlStrQEqual(prefix, name, insert->name))) - return(insert->name); - nbi++; - } - if ((insert->okey == okey) && (insert->len == len) && - (xmlStrQEqual(prefix, name, insert->name))) - return(insert->name); - } - - if (dict->subdict) { - unsigned long skey; - - /* we cannot always reuse the same okey for the subdict */ - if (((dict->size == MIN_DICT_SIZE) && - (dict->subdict->size != MIN_DICT_SIZE)) || - ((dict->size != MIN_DICT_SIZE) && - (dict->subdict->size == MIN_DICT_SIZE))) - skey = xmlDictComputeQKey(dict->subdict, prefix, plen, name, l); - else - skey = okey; - - key = skey % dict->subdict->size; - if (dict->subdict->dict[key].valid != 0) { - xmlDictEntryPtr tmp; - for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; - tmp = tmp->next) { - if ((tmp->okey == skey) && (tmp->len == len) && - (xmlStrQEqual(prefix, name, tmp->name))) - return(tmp->name); - nbi++; - } - if ((tmp->okey == skey) && (tmp->len == len) && - (xmlStrQEqual(prefix, name, tmp->name))) - return(tmp->name); - } - key = okey % dict->size; - } - - ret = xmlDictAddQString(dict, prefix, plen, name, l); - if (ret == NULL) - return(NULL); - if (insert == NULL) { - entry = &(dict->dict[key]); - } else { - entry = xmlMalloc(sizeof(xmlDictEntry)); - if (entry == NULL) - return(NULL); - } - entry->name = ret; - entry->len = len; - entry->next = NULL; - entry->valid = 1; - entry->okey = okey; - - if (insert != NULL) - insert->next = entry; - - dict->nbElems++; - - if ((nbi > MAX_HASH_LEN) && - (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) - xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size); - /* Note that entry may have been freed at this point by xmlDictGrow */ - - return(ret); -} - /** * xmlDictOwns: * @dict: the dictionary @@ -1265,3 +452,520 @@ xmlDictGetUsage(xmlDictPtr dict) { return(limit); }
+/***************************************************************** + * + * The code below was rewritten and is additionally licensed under + * the main license in file 'Copyright'. + * + *****************************************************************/ + +ATTRIBUTE_NO_SANITIZE_INTEGER +static unsigned +xmlDictHashName(unsigned seed, const xmlChar* data, size_t maxLen, + size_t *plen) { + unsigned h1, h2; + size_t i; + + HASH_INIT(h1, h2, seed); + + for (i = 0; i < maxLen && data[i]; i++) { + HASH_UPDATE(h1, h2, data[i]); + } + + HASH_FINISH(h1, h2); + + *plen = i; + return(h2 | MAX_HASH_SIZE); +} + +ATTRIBUTE_NO_SANITIZE_INTEGER +static unsigned +xmlDictHashQName(unsigned seed, const xmlChar *prefix, const xmlChar *name, + size_t *pplen, size_t *plen) { + unsigned h1, h2; + size_t i; + + HASH_INIT(h1, h2, seed); + + for (i = 0; prefix[i] != 0; i++) { + HASH_UPDATE(h1, h2, prefix[i]); + } + *pplen = i; + + HASH_UPDATE(h1, h2, ':'); + + for (i = 0; name[i] != 0; i++) { + HASH_UPDATE(h1, h2, name[i]); + } + *plen = i; + + HASH_FINISH(h1, h2); + + /* + * Always set the upper bit of hash values since 0 means an unoccupied + * bucket. + */ + return(h2 | MAX_HASH_SIZE); +} + +unsigned +xmlDictComputeHash(const xmlDict *dict, const xmlChar *string) { + size_t len; + return(xmlDictHashName(dict->seed, string, SIZE_MAX, &len)); +} + +#define HASH_ROL31(x,n) ((x) << (n) | ((x) & 0x7FFFFFFF) >> (31 - (n))) + +ATTRIBUTE_NO_SANITIZE_INTEGER +unsigned +xmlDictCombineHash(unsigned v1, unsigned v2) { + /* + * The upper bit of hash values is always set, so we have to operate on + * 31-bit hashes here. + */ + v1 ^= v2; + v1 += HASH_ROL31(v2, 5); + + return((v1 & 0xFFFFFFFF) | 0x80000000); +} + +/** + * xmlDictFindEntry: + * @dict: dict + * @prefix: optional QName prefix + * @name: string + * @len: length of string + * @hashValue: valid hash value of string + * @pfound: result of search + * + * Try to find a matching hash table entry. If an entry was found, set + * @found to 1 and return the entry. Otherwise, set @found to 0 and return + * the location where a new entry should be inserted. + */ +ATTRIBUTE_NO_SANITIZE_INTEGER +static xmlDictEntry * +xmlDictFindEntry(const xmlDict *dict, const xmlChar *prefix, + const xmlChar *name, int len, unsigned hashValue, + int *pfound) { + xmlDictEntry *entry; + unsigned mask, pos, displ; + int found = 0; + + mask = dict->size - 1; + pos = hashValue & mask; + entry = &dict->table[pos]; + + if (entry->hashValue != 0) { + /* + * Robin hood hashing: abort if the displacement of the entry + * is smaller than the displacement of the key we look for. + * This also stops at the correct position when inserting. + */ + displ = 0; + + do { + if (entry->hashValue == hashValue) { + if (prefix == NULL) { + /* + * name is not necessarily null-terminated. + */ + if ((strncmp((const char *) entry->name, + (const char *) name, len) == 0) && + (entry->name[len] == 0)) { + found = 1; + break; + } + } else { + if (xmlStrQEqual(prefix, name, entry->name)) { + found = 1; + break; + } + } + } + + displ++; + pos++; + entry++; + if ((pos & mask) == 0) + entry = dict->table; + } while ((entry->hashValue != 0) && + (((pos - entry->hashValue) & mask) >= displ)); + } + + *pfound = found; + return(entry); +} + +/** + * xmlDictGrow: + * @dict: dictionary + * @size: new size of the dictionary + * + * Resize the dictionary hash table. + * + * Returns 0 in case of success, -1 if a memory allocation failed. + */ +static int +xmlDictGrow(xmlDictPtr dict, unsigned size) { + const xmlDictEntry *oldentry, *oldend, *end; + xmlDictEntry *table; + unsigned oldsize, i; + + /* Add 0 to avoid spurious -Wtype-limits warning on 64-bit GCC */ + if ((size_t) size + 0 > SIZE_MAX / sizeof(table[0])) + return(-1); + table = xmlMalloc(size * sizeof(table[0])); + if (table == NULL) + return(-1); + memset(table, 0, size * sizeof(table[0])); + + oldsize = dict->size; + if (oldsize == 0) + goto done; + + oldend = &dict->table[oldsize]; + end = &table[size]; + + /* + * Robin Hood sorting order is maintained if we + * + * - compute dict indices with modulo + * - resize by an integer factor + * - start to copy from the beginning of a probe sequence + */ + oldentry = dict->table; + while (oldentry->hashValue != 0) { + if (++oldentry >= oldend) + oldentry = dict->table; + } + + for (i = 0; i < oldsize; i++) { + if (oldentry->hashValue != 0) { + xmlDictEntry *entry = &table[oldentry->hashValue & (size - 1)]; + + while (entry->hashValue != 0) { + if (++entry >= end) + entry = table; + } + *entry = *oldentry; + } + + if (++oldentry >= oldend) + oldentry = dict->table; + } + + xmlFree(dict->table); + +done: + dict->table = table; + dict->size = size; + + return(0); +} + +/** + * xmlDictLookupInternal: + * @dict: dict + * @prefix: optional QName prefix + * @name: string + * @maybeLen: length of string or -1 if unknown + * @update: whether the string should be added + * + * Internal lookup and update function. + */ +ATTRIBUTE_NO_SANITIZE_INTEGER +static const xmlDictEntry * +xmlDictLookupInternal(xmlDictPtr dict, const xmlChar *prefix, + const xmlChar *name, int maybeLen, int update) { + xmlDictEntry *entry = NULL; + const xmlChar *ret; + unsigned hashValue; + size_t maxLen, len, plen, klen; + int found = 0; + + if ((dict == NULL) || (name == NULL)) + return(NULL); + + maxLen = (maybeLen < 0) ? SIZE_MAX : (size_t) maybeLen; + + if (prefix == NULL) { + hashValue = xmlDictHashName(dict->seed, name, maxLen, &len); + if (len > INT_MAX / 2) + return(NULL); + klen = len; + } else { + hashValue = xmlDictHashQName(dict->seed, prefix, name, &plen, &len); + if ((len > INT_MAX / 2) || (plen >= INT_MAX / 2 - len)) + return(NULL); + klen = plen + 1 + len; + } + + if ((dict->limit > 0) && (klen >= dict->limit)) + return(NULL); + + /* + * Check for an existing entry + */ + if (dict->size > 0) + entry = xmlDictFindEntry(dict, prefix, name, klen, hashValue, &found); + if (found) + return(entry); + + if ((dict->subdict != NULL) && (dict->subdict->size > 0)) { + xmlDictEntry *subEntry; + unsigned subHashValue; + + if (prefix == NULL) + subHashValue = xmlDictHashName(dict->subdict->seed, name, len, + &len); + else + subHashValue = xmlDictHashQName(dict->subdict->seed, prefix, name, + &plen, &len); + subEntry = xmlDictFindEntry(dict->subdict, prefix, name, klen, + subHashValue, &found); + if (found) + return(subEntry); + } + + if (!update) + return(NULL); + + /* + * Grow the hash table if needed + */ + if (dict->nbElems + 1 > dict->size / MAX_FILL_DENOM * MAX_FILL_NUM) { + unsigned newSize, mask, displ, pos; + + if (dict->size == 0) { + newSize = MIN_HASH_SIZE; + } else { + if (dict->size >= MAX_HASH_SIZE) + return(NULL); + newSize = dict->size * 2; + } + if (xmlDictGrow(dict, newSize) != 0) + return(NULL); + + /* + * Find new entry + */ + mask = dict->size - 1; + displ = 0; + pos = hashValue & mask; + entry = &dict->table[pos]; + + while ((entry->hashValue != 0) && + ((pos - entry->hashValue) & mask) >= displ) { + displ++; + pos++; + entry++; + if ((pos & mask) == 0) + entry = dict->table; + } + } + + if (prefix == NULL) + ret = xmlDictAddString(dict, name, len); + else + ret = xmlDictAddQString(dict, prefix, plen, name, len); + if (ret == NULL) + return(NULL); + + /* + * Shift the remainder of the probe sequence to the right + */ + if (entry->hashValue != 0) { + const xmlDictEntry *end = &dict->table[dict->size]; + const xmlDictEntry *cur = entry; + + do { + cur++; + if (cur >= end) + cur = dict->table; + } while (cur->hashValue != 0); + + if (cur < entry) { + /* + * If we traversed the end of the buffer, handle the part + * at the start of the buffer. + */ + memmove(&dict->table[1], dict->table, + (char *) cur - (char *) dict->table); + cur = end - 1; + dict->table[0] = *cur; + } + + memmove(&entry[1], entry, (char *) cur - (char *) entry); + } + + /* + * Populate entry + */ + entry->hashValue = hashValue; + entry->name = ret; + + dict->nbElems++; + + return(entry); +} + +/** + * xmlDictLookup: + * @dict: dictionary + * @name: string key + * @len: length of the key, if -1 it is recomputed + * + * Lookup a string and add it to the dictionary if it wasn't found. + * + * Returns the interned copy of the string or NULL if a memory allocation + * failed. + */ +const xmlChar * +xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { + const xmlDictEntry *entry; + + entry = xmlDictLookupInternal(dict, NULL, name, len, 1); + if (entry == NULL) + return(NULL); + return(entry->name); +} + +/** + * xmlDictLookupHashed: + * @dict: dictionary + * @name: string key + * @len: length of the key, if -1 it is recomputed + * + * Lookup a dictionary entry and add the string to the dictionary if + * it wasn't found. + * + * Returns the dictionary entry. + */ +xmlHashedString +xmlDictLookupHashed(xmlDictPtr dict, const xmlChar *name, int len) { + const xmlDictEntry *entry; + xmlHashedString ret; + + entry = xmlDictLookupInternal(dict, NULL, name, len, 1); + + if (entry == NULL) { + ret.name = NULL; + ret.hashValue = 0; + } else { + ret = *entry; + } + + return(ret); +} + +/** + * xmlDictExists: + * @dict: the dictionary + * @name: the name of the userdata + * @len: the length of the name, if -1 it is recomputed + * + * Check if a string exists in the dictionary. + * + * Returns the internal copy of the name or NULL if not found. + */ +const xmlChar * +xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { + const xmlDictEntry *entry; + + entry = xmlDictLookupInternal(dict, NULL, name, len, 0); + if (entry == NULL) + return(NULL); + return(entry->name); +} + +/** + * xmlDictQLookup: + * @dict: the dictionary + * @prefix: the prefix + * @name: the name + * + * Lookup the QName @prefix:@name and add it to the dictionary if + * it wasn't found. + * + * Returns the interned copy of the string or NULL if a memory allocation + * failed. + */ +const xmlChar * +xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { + const xmlDictEntry *entry; + + entry = xmlDictLookupInternal(dict, prefix, name, -1, 1); + if (entry == NULL) + return(NULL); + return(entry->name); +} + +/* + * Pseudo-random generator + */ + +static xmlMutex xmlRngMutex; + +static unsigned globalRngState[2]; + +#ifdef XML_THREAD_LOCAL +static XML_THREAD_LOCAL int localRngInitialized = 0; +static XML_THREAD_LOCAL unsigned localRngState[2]; +#endif + +ATTRIBUTE_NO_SANITIZE_INTEGER +void +xmlInitRandom(void) { + int var; + + xmlInitMutex(&xmlRngMutex); + + /* TODO: Get seed values from system PRNG */ + + globalRngState[0] = (unsigned) time(NULL) ^ + HASH_ROL((unsigned) (size_t) &xmlInitRandom, 8); + globalRngState[1] = HASH_ROL((unsigned) (size_t) &xmlRngMutex, 16) ^ + HASH_ROL((unsigned) (size_t) &var, 24); +} + +void +xmlCleanupRandom(void) { + xmlCleanupMutex(&xmlRngMutex); +} + +ATTRIBUTE_NO_SANITIZE_INTEGER +static unsigned +xoroshiro64ss(unsigned *s) { + unsigned s0 = s[0]; + unsigned s1 = s[1]; + unsigned result = HASH_ROL(s0 * 0x9E3779BB, 5) * 5; + + s1 ^= s0; + s[0] = HASH_ROL(s0, 26) ^ s1 ^ (s1 << 9); + s[1] = HASH_ROL(s1, 13); + + return(result & 0xFFFFFFFF); +} + +unsigned +xmlRandom(void) { +#ifdef XML_THREAD_LOCAL + if (!localRngInitialized) { + xmlMutexLock(&xmlRngMutex); + localRngState[0] = xoroshiro64ss(globalRngState); + localRngState[1] = xoroshiro64ss(globalRngState); + localRngInitialized = 1; + xmlMutexUnlock(&xmlRngMutex); + } + + return(xoroshiro64ss(localRngState)); +#else + unsigned ret; + + xmlMutexLock(&xmlRngMutex); + ret = xoroshiro64ss(globalRngState); + xmlMutexUnlock(&xmlRngMutex); + + return(ret); +#endif +} diff --git a/libs/xml2/encoding.c b/libs/xml2/encoding.c index 19ced4e4c6f..ba660a43035 100644 --- a/libs/xml2/encoding.c +++ b/libs/xml2/encoding.c @@ -34,10 +34,10 @@
#include <libxml/encoding.h> #include <libxml/xmlmemory.h> +#include <libxml/parser.h> #ifdef LIBXML_HTML_ENABLED #include <libxml/HTMLparser.h> #endif -#include <libxml/globals.h> #include <libxml/xmlerror.h>
#include "private/buf.h" @@ -69,42 +69,8 @@ static xmlCharEncodingAliasPtr xmlCharEncodingAliases = NULL; static int xmlCharEncodingAliasesNb = 0; static int xmlCharEncodingAliasesMax = 0;
-#if defined(LIBXML_ICONV_ENABLED) || defined(LIBXML_ICU_ENABLED) -#if 0 -#define DEBUG_ENCODING /* Define this to get encoding traces */ -#endif -#else -#endif - static int xmlLittleEndian = 1;
-/** - * xmlEncodingErrMemory: - * @extra: extra information - * - * Handle an out of memory condition - */ -static void -xmlEncodingErrMemory(const char *extra) -{ - __xmlSimpleError(XML_FROM_I18N, XML_ERR_NO_MEMORY, NULL, NULL, extra); -} - -/** - * xmlErrEncoding: - * @error: the error number - * @msg: the error message - * - * n encoding error - */ -static void LIBXML_ATTR_FORMAT(2,0) -xmlEncodingErr(xmlParserErrors error, const char *msg, const char *val) -{ - __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, - XML_FROM_I18N, error, XML_ERR_FATAL, - NULL, 0, val, NULL, NULL, 0, 0, msg, val); -} - #ifdef LIBXML_ICU_ENABLED static uconv_t* openIcuConverter(const char* name, int toUnicode) @@ -171,7 +137,9 @@ closeIcuConverter(uconv_t *conv) * * Take a block of ASCII chars in and try to convert it to an UTF-8 * block of chars out. - * Returns 0 if success, or -1 otherwise + * + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of @inlen after return is the number of octets consumed * if the return value is positive, else unpredictable. * The value of @outlen after return is the number of octets produced. @@ -197,7 +165,7 @@ asciiToUTF8(unsigned char* out, int *outlen, } else { *outlen = out - outstart; *inlen = processed - base; - return(-2); + return(XML_ENC_ERR_INPUT); }
processed = (const unsigned char*) in; @@ -218,7 +186,8 @@ asciiToUTF8(unsigned char* out, int *outlen, * Take a block of UTF-8 chars in and try to convert it to an ASCII * block of chars out. * - * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of @inlen after return is the number of octets consumed * if the return value is positive, else unpredictable. * The value of @outlen after return is the number of octets produced. @@ -234,7 +203,8 @@ UTF8Toascii(unsigned char* out, int *outlen, unsigned int c, d; int trailing;
- if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) + return(XML_ENC_ERR_INTERNAL); if (in == NULL) { /* * initialization nothing to do @@ -252,7 +222,7 @@ UTF8Toascii(unsigned char* out, int *outlen, /* trailing byte in leading position */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } else if (d < 0xF8) { c= d & 0x07; trailing= 3; } @@ -260,7 +230,7 @@ UTF8Toascii(unsigned char* out, int *outlen, /* no chance for this in Ascii */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); }
if (inend - in < trailing) { @@ -283,7 +253,7 @@ UTF8Toascii(unsigned char* out, int *outlen, /* no chance for this in Ascii */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } processed = in; } @@ -302,7 +272,9 @@ UTF8Toascii(unsigned char* out, int *outlen, * * Take a block of ISO Latin 1 chars in and try to convert it to an UTF-8 * block of chars out. - * Returns the number of bytes written if success, or -1 otherwise + * + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of @inlen after return is the number of octets consumed * if the return value is positive, else unpredictable. * The value of @outlen after return is the number of octets produced. @@ -317,7 +289,7 @@ isolat1ToUTF8(unsigned char* out, int *outlen, const unsigned char* instop;
if ((out == NULL) || (in == NULL) || (outlen == NULL) || (inlen == NULL)) - return(-1); + return(XML_ENC_ERR_INTERNAL);
outend = out + *outlen; inend = in + (*inlen); @@ -351,7 +323,8 @@ isolat1ToUTF8(unsigned char* out, int *outlen, * * No op copy operation for UTF8 handling. * - * Returns the number of bytes written, or -1 if lack of space. + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of *inlen after return is the number of octets consumed * if the return value is positive, else unpredictable. */ @@ -362,7 +335,7 @@ UTF8ToUTF8(unsigned char* out, int *outlen, int len;
if ((out == NULL) || (outlen == NULL) || (inlenb == NULL)) - return(-1); + return(XML_ENC_ERR_INTERNAL); if (inb == NULL) { /* inb == NULL means output is initialized. */ *outlen = 0; @@ -375,7 +348,7 @@ UTF8ToUTF8(unsigned char* out, int *outlen, len = *outlen; } if (len < 0) - return(-1); + return(XML_ENC_ERR_INTERNAL);
/* * FIXME: Conversion functions must assure valid UTF-8, so we have @@ -401,8 +374,8 @@ UTF8ToUTF8(unsigned char* out, int *outlen, * Take a block of UTF-8 chars in and try to convert it to an ISO Latin 1 * block of chars out. * - * Returns the number of bytes written if success, -2 if the transcoding fails, - or -1 otherwise + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of @inlen after return is the number of octets consumed * if the return value is positive, else unpredictable. * The value of @outlen after return is the number of octets produced. @@ -418,7 +391,8 @@ UTF8Toisolat1(unsigned char* out, int *outlen, unsigned int c, d; int trailing;
- if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) + return(XML_ENC_ERR_INTERNAL); if (in == NULL) { /* * initialization nothing to do @@ -436,7 +410,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen, /* trailing byte in leading position */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } else if (d < 0xF8) { c= d & 0x07; trailing= 3; } @@ -444,7 +418,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen, /* no chance for this in IsoLat1 */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); }
if (inend - in < trailing) { @@ -457,7 +431,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen, if (((d= *in++) & 0xC0) != 0x80) { *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } c <<= 6; c |= d & 0x3F; @@ -472,7 +446,7 @@ UTF8Toisolat1(unsigned char* out, int *outlen, /* no chance for this in IsoLat1 */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } processed = in; } @@ -494,10 +468,10 @@ UTF8Toisolat1(unsigned char* out, int *outlen, * is the same between the native type of this machine and the * inputed one. * - * Returns the number of bytes written, or -1 if lack of space, or -2 - * if the transcoding fails (if *in is not a valid utf16 string) - * The value of *inlen after return is the number of octets consumed - * if the return value is positive, else unpredictable. + * Returns the number of bytes written or an XML_ENC_ERR code. + * + * The value of *inlen after return is the number of octets consumed + * if the return value is positive, else unpredictable. */ static int UTF16LEToUTF8(unsigned char* out, int *outlen, @@ -506,7 +480,7 @@ UTF16LEToUTF8(unsigned char* out, int *outlen, unsigned char* outstart = out; const unsigned char* processed = inb; unsigned char* outend; - unsigned short* in = (unsigned short*) inb; + unsigned short* in = (unsigned short *) (void *) inb; unsigned short* inend; unsigned int c, d, inlen; unsigned char *tmp; @@ -551,7 +525,7 @@ UTF16LEToUTF8(unsigned char* out, int *outlen, else { *outlen = out - outstart; *inlenb = processed - inb; - return(-2); + return(XML_ENC_ERR_INPUT); } }
@@ -586,14 +560,13 @@ UTF16LEToUTF8(unsigned char* out, int *outlen, * Take a block of UTF-8 chars in and try to convert it to an UTF-16LE * block of chars out. * - * Returns the number of bytes written, or -1 if lack of space, or -2 - * if the transcoding failed. + * Returns the number of bytes written or an XML_ENC_ERR code. */ static int UTF8ToUTF16LE(unsigned char* outb, int *outlen, const unsigned char* in, int *inlen) { - unsigned short* out = (unsigned short*) outb; + unsigned short* out = (unsigned short *) (void *) outb; const unsigned char* processed = in; const unsigned char *const instart = in; unsigned short* outstart= out; @@ -605,7 +578,8 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen, unsigned short tmp1, tmp2;
/* UTF16LE encoding has no BOM */ - if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) + return(XML_ENC_ERR_INTERNAL); if (in == NULL) { *outlen = 0; *inlen = 0; @@ -620,7 +594,7 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen, /* trailing byte in leading position */ *outlen = (out - outstart) * 2; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } else if (d < 0xF8) { c= d & 0x07; trailing= 3; } @@ -628,7 +602,7 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen, /* no chance for this in UTF-16 */ *outlen = (out - outstart) * 2; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); }
if (inend - in < trailing) { @@ -695,8 +669,7 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen, * Take a block of UTF-8 chars in and try to convert it to an UTF-16 * block of chars out. * - * Returns the number of bytes written, or -1 if lack of space, or -2 - * if the transcoding failed. + * Returns the number of bytes written or an XML_ENC_ERR code. */ static int UTF8ToUTF16(unsigned char* outb, int *outlen, @@ -711,10 +684,6 @@ UTF8ToUTF16(unsigned char* outb, int *outlen, outb[1] = 0xFE; *outlen = 2; *inlen = 0; -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "Added FFFE Byte Order Mark\n"); -#endif return(2); } *outlen = 0; @@ -737,10 +706,10 @@ UTF8ToUTF16(unsigned char* outb, int *outlen, * is the same between the native type of this machine and the * inputed one. * - * Returns the number of bytes written, or -1 if lack of space, or -2 - * if the transcoding fails (if *in is not a valid utf16 string) + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of *inlen after return is the number of octets consumed - * if the return value is positive, else unpredictable. + * if the return value is positive, else unpredictable. */ static int UTF16BEToUTF8(unsigned char* out, int *outlen, @@ -749,7 +718,7 @@ UTF16BEToUTF8(unsigned char* out, int *outlen, unsigned char* outstart = out; const unsigned char* processed = inb; unsigned char* outend; - unsigned short* in = (unsigned short*) inb; + unsigned short* in = (unsigned short *) (void *) inb; unsigned short* inend; unsigned int c, d, inlen; unsigned char *tmp; @@ -794,7 +763,7 @@ UTF16BEToUTF8(unsigned char* out, int *outlen, else { *outlen = out - outstart; *inlenb = processed - inb; - return(-2); + return(XML_ENC_ERR_INPUT); } }
@@ -829,14 +798,13 @@ UTF16BEToUTF8(unsigned char* out, int *outlen, * Take a block of UTF-8 chars in and try to convert it to an UTF-16BE * block of chars out. * - * Returns the number of byte written, or -1 by lack of space, or -2 - * if the transcoding failed. + * Returns the number of bytes written or an XML_ENC_ERR code. */ static int UTF8ToUTF16BE(unsigned char* outb, int *outlen, const unsigned char* in, int *inlen) { - unsigned short* out = (unsigned short*) outb; + unsigned short* out = (unsigned short *) (void *) outb; const unsigned char* processed = in; const unsigned char *const instart = in; unsigned short* outstart= out; @@ -848,7 +816,8 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen, unsigned short tmp1, tmp2;
/* UTF-16BE has no BOM */ - if ((outb == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1); + if ((outb == NULL) || (outlen == NULL) || (inlen == NULL)) + return(XML_ENC_ERR_INTERNAL); if (in == NULL) { *outlen = 0; *inlen = 0; @@ -863,7 +832,7 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen, /* trailing byte in leading position */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; } else if (d < 0xF0) { c= d & 0x0F; trailing= 2; } else if (d < 0xF8) { c= d & 0x07; trailing= 3; } @@ -871,7 +840,7 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen, /* no chance for this in UTF-16 */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); }
if (inend - in < trailing) { @@ -1072,6 +1041,7 @@ int xmlAddEncodingAlias(const char *name, const char *alias) { int i; char upper[100]; + char *nameCopy, *aliasCopy;
if ((name == NULL) || (alias == NULL)) return(-1); @@ -1082,19 +1052,21 @@ xmlAddEncodingAlias(const char *name, const char *alias) { } upper[i] = 0;
- if (xmlCharEncodingAliases == NULL) { - xmlCharEncodingAliasesNb = 0; - xmlCharEncodingAliasesMax = 20; - xmlCharEncodingAliases = (xmlCharEncodingAliasPtr) - xmlMalloc(xmlCharEncodingAliasesMax * sizeof(xmlCharEncodingAlias)); - if (xmlCharEncodingAliases == NULL) - return(-1); - } else if (xmlCharEncodingAliasesNb >= xmlCharEncodingAliasesMax) { - xmlCharEncodingAliasesMax *= 2; - xmlCharEncodingAliases = (xmlCharEncodingAliasPtr) - xmlRealloc(xmlCharEncodingAliases, - xmlCharEncodingAliasesMax * sizeof(xmlCharEncodingAlias)); + if (xmlCharEncodingAliasesNb >= xmlCharEncodingAliasesMax) { + xmlCharEncodingAliasPtr tmp; + size_t newSize = xmlCharEncodingAliasesMax ? + xmlCharEncodingAliasesMax * 2 : + 20; + + tmp = (xmlCharEncodingAliasPtr) + xmlRealloc(xmlCharEncodingAliases, + newSize * sizeof(xmlCharEncodingAlias)); + if (tmp == NULL) + return(-1); + xmlCharEncodingAliases = tmp; + xmlCharEncodingAliasesMax = newSize; } + /* * Walk down the list looking for a definition of the alias */ @@ -1103,16 +1075,27 @@ xmlAddEncodingAlias(const char *name, const char *alias) { /* * Replace the definition. */ + nameCopy = xmlMemStrdup(name); + if (nameCopy == NULL) + return(-1); xmlFree((char *) xmlCharEncodingAliases[i].name); - xmlCharEncodingAliases[i].name = xmlMemStrdup(name); + xmlCharEncodingAliases[i].name = nameCopy; return(0); } } /* * Add the definition */ - xmlCharEncodingAliases[xmlCharEncodingAliasesNb].name = xmlMemStrdup(name); - xmlCharEncodingAliases[xmlCharEncodingAliasesNb].alias = xmlMemStrdup(upper); + nameCopy = xmlMemStrdup(name); + if (nameCopy == NULL) + return(-1); + aliasCopy = xmlMemStrdup(upper); + if (aliasCopy == NULL) { + xmlFree(nameCopy); + return(-1); + } + xmlCharEncodingAliases[xmlCharEncodingAliasesNb].name = nameCopy; + xmlCharEncodingAliases[xmlCharEncodingAliasesNb].alias = aliasCopy; xmlCharEncodingAliasesNb++; return(0); } @@ -1228,9 +1211,6 @@ xmlParseCharEncoding(const char* name) if (!strcmp(upper, "SHIFT_JIS")) return(XML_CHAR_ENCODING_SHIFT_JIS); if (!strcmp(upper, "EUC-JP")) return(XML_CHAR_ENCODING_EUC_JP);
-#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, "Unknown encoding %s\n", name); -#endif return(XML_CHAR_ENCODING_ERROR); }
@@ -1430,21 +1410,16 @@ xmlNewCharEncodingHandler(const char *name, /* * Keep only the uppercase version of the encoding. */ - if (name == NULL) { - xmlEncodingErr(XML_I18N_NO_NAME, - "xmlNewCharEncodingHandler : no name !\n", NULL); + if (name == NULL) return(NULL); - } for (i = 0;i < 499;i++) { upper[i] = (char) toupper((unsigned char) name[i]); if (upper[i] == 0) break; } upper[i] = 0; up = xmlMemStrdup(upper); - if (up == NULL) { - xmlEncodingErrMemory("xmlNewCharEncodingHandler : out of memory !\n"); + if (up == NULL) return(NULL); - }
/* * allocate and fill-up an handler block. @@ -1453,7 +1428,6 @@ xmlNewCharEncodingHandler(const char *name, xmlMalloc(sizeof(xmlCharEncodingHandler)); if (handler == NULL) { xmlFree(up); - xmlEncodingErrMemory("xmlNewCharEncodingHandler : out of memory !\n"); return(NULL); } memset(handler, 0, sizeof(xmlCharEncodingHandler)); @@ -1474,10 +1448,6 @@ xmlNewCharEncodingHandler(const char *name, * registers and returns the handler. */ xmlRegisterCharEncodingHandler(handler); -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "Registered encoding handler for %s\n", name); -#endif return(handler); }
@@ -1502,11 +1472,7 @@ xmlInitEncodingInternal(void) { unsigned char *ptr = (unsigned char *) &tst;
if (*ptr == 0x12) xmlLittleEndian = 0; - else if (*ptr == 0x34) xmlLittleEndian = 1; - else { - xmlEncodingErr(XML_ERR_INTERNAL_ERROR, - "Odd problem at endianness detection\n", NULL); - } + else xmlLittleEndian = 1; }
/** @@ -1547,25 +1513,16 @@ xmlCleanupCharEncodingHandlers(void) { */ void xmlRegisterCharEncodingHandler(xmlCharEncodingHandlerPtr handler) { - if (handler == NULL) { - xmlEncodingErr(XML_I18N_NO_HANDLER, - "xmlRegisterCharEncodingHandler: NULL handler\n", NULL); + if (handler == NULL) return; - } if (handlers == NULL) { handlers = xmlMalloc(MAX_ENCODING_HANDLERS * sizeof(handlers[0])); - if (handlers == NULL) { - xmlEncodingErrMemory("allocating handler table"); + if (handlers == NULL) goto free_handler; - } }
- if (nbCharEncodingHandler >= MAX_ENCODING_HANDLERS) { - xmlEncodingErr(XML_I18N_EXCESS_HANDLER, - "xmlRegisterCharEncodingHandler: Too many handler registered, see %s\n", - "MAX_ENCODING_HANDLERS"); + if (nbCharEncodingHandler >= MAX_ENCODING_HANDLERS) goto free_handler; - } handlers[nbCharEncodingHandler++] = handler; return;
@@ -1704,10 +1661,6 @@ xmlGetCharEncodingHandler(xmlCharEncoding enc) { break; }
-#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "No handler found for encoding %d\n", enc); -#endif return(NULL); }
@@ -1764,10 +1717,6 @@ xmlFindCharEncodingHandler(const char *name) { if (handlers != NULL) { for (i = 0;i < nbCharEncodingHandler; i++) { if (!strcmp(upper, handlers[i]->name)) { -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "Found registered handler for encoding %s\n", name); -#endif return(handlers[i]); } } @@ -1803,14 +1752,8 @@ xmlFindCharEncodingHandler(const char *name) { enc->output = NULL; enc->iconv_in = icv_in; enc->iconv_out = icv_out; -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "Found iconv handler for encoding %s\n", name); -#endif return enc; } else if ((icv_in != (iconv_t) -1) || icv_out != (iconv_t) -1) { - xmlEncodingErr(XML_ERR_INTERNAL_ERROR, - "iconv : problems with filters for '%s'\n", name); if (icv_in != (iconv_t) -1) iconv_close(icv_in); else @@ -1841,24 +1784,13 @@ xmlFindCharEncodingHandler(const char *name) { encu->output = NULL; encu->uconv_in = ucv_in; encu->uconv_out = ucv_out; -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "Found ICU converter handler for encoding %s\n", name); -#endif return encu; } else if (ucv_in != NULL || ucv_out != NULL) { closeIcuConverter(ucv_in); closeIcuConverter(ucv_out); - xmlEncodingErr(XML_ERR_INTERNAL_ERROR, - "ICU converter : problems with filters for '%s'\n", name); } #endif /* LIBXML_ICU_ENABLED */
-#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "No handler found for encoding %s\n", name); -#endif - /* * Fallback using the canonical names */ @@ -1890,11 +1822,7 @@ xmlFindCharEncodingHandler(const char *name) { * @in: a pointer to an array of input bytes * @inlen: the length of @in * - * Returns 0 if success, or - * -1 by lack of space, or - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or - * -3 if there the last byte can't form a single output char. + * Returns an XML_ENC_ERR code. * * The value of @inlen after return is the number of octets consumed * as the return value is positive, else unpredictable. @@ -1910,7 +1838,7 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) { if (outlen != NULL) *outlen = 0; - return(-1); + return(XML_ENC_ERR_INTERNAL); } icv_inlen = *inlen; icv_outlen = *outlen; @@ -1920,27 +1848,16 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen, ret = iconv(cd, (void *) &icv_in, &icv_inlen, &icv_out, &icv_outlen); *inlen -= icv_inlen; *outlen -= icv_outlen; - if ((icv_inlen != 0) || (ret == (size_t) -1)) { -#ifdef EILSEQ - if (errno == EILSEQ) { - return -2; - } else -#endif -#ifdef E2BIG - if (errno == E2BIG) { - return -1; - } else -#endif -#ifdef EINVAL - if (errno == EINVAL) { - return -3; - } else -#endif - { - return -3; - } + if (ret == (size_t) -1) { + if (errno == EILSEQ) + return(XML_ENC_ERR_INPUT); + if (errno == E2BIG) + return(XML_ENC_ERR_SPACE); + if (errno == EINVAL) + return(XML_ENC_ERR_PARTIAL); + return(XML_ENC_ERR_INTERNAL); } - return 0; + return(XML_ENC_ERR_SUCCESS); } #endif /* LIBXML_ICONV_ENABLED */
@@ -1959,13 +1876,8 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen, * @outlen: the length of @out * @in: a pointer to an array of input bytes * @inlen: the length of @in - * @flush: if true, indicates end of input * - * Returns 0 if success, or - * -1 by lack of space, or - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or - * -3 if there the last byte can't form a single output char. + * Returns an XML_ENC_ERR code. * * The value of @inlen after return is the number of octets consumed * as the return value is positive, else unpredictable. @@ -1973,16 +1885,30 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen, */ static int xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen, - const unsigned char *in, int *inlen, int flush) { + const unsigned char *in, int *inlen) { const char *ucv_in = (const char *) in; char *ucv_out = (char *) out; UErrorCode err = U_ZERO_ERROR;
if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) { if (outlen != NULL) *outlen = 0; - return(-1); + return(XML_ENC_ERR_INTERNAL); }
+ /* + * Note that the ICU API is stateful. It can always consume a certain + * amount of input even if the output buffer would overflow. The + * remaining input must be processed by calling ucnv_convertEx with a + * possibly empty input buffer. + * + * ucnv_convertEx is always called with reset and flush set to 0, + * so we don't mess up the state. This should never generate + * U_TRUNCATED_CHAR_FOUND errors. + * + * This also means that ICU xmlCharEncodingHandlers should never be + * reused. It would be a lot nicer if there was a way to emulate the + * stateless iconv API. + */ if (toUnicode) { /* encoding => UTF-16 => UTF-8 */ ucnv_convertEx(cd->utf8, cd->uconv, &ucv_out, ucv_out + *outlen, @@ -1998,13 +1924,14 @@ xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen, } *inlen = ucv_in - (const char*) in; *outlen = ucv_out - (char *) out; - if (U_SUCCESS(err)) - return 0; + if (U_SUCCESS(err)) { + return(XML_ENC_ERR_SUCCESS); + } if (err == U_BUFFER_OVERFLOW_ERROR) - return -1; + return(XML_ENC_ERR_SPACE); if (err == U_INVALID_CHAR_FOUND || err == U_ILLEGAL_CHAR_FOUND) - return -2; - return -3; + return(XML_ENC_ERR_INPUT); + return(XML_ENC_ERR_PARTIAL); } #endif /* LIBXML_ICU_ENABLED */
@@ -2014,6 +1941,34 @@ xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen, * * ************************************************************************/
+/** + * xmlEncConvertError: + * @code: XML_ENC_ERR code + * + * Convert XML_ENC_ERR to libxml2 error codes. + */ +static int +xmlEncConvertError(int code) { + int ret; + + switch (code) { + case XML_ENC_ERR_SUCCESS: + ret = XML_ERR_OK; + break; + case XML_ENC_ERR_INPUT: + ret = XML_ERR_INVALID_ENCODING; + break; + case XML_ENC_ERR_MEMORY: + ret = XML_ERR_NO_MEMORY; + break; + default: + ret = XML_ERR_INTERNAL_ERROR; + break; + } + + return(ret); +} + /** * xmlEncInputChunk: * @handler: encoding handler @@ -2021,28 +1976,35 @@ xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen, * @outlen: the length of @out * @in: a pointer to an array of input bytes * @inlen: the length of @in - * @flush: flush (ICU-related) - * - * Returns 0 if success, or - * -1 by lack of space, or - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or - * -3 if there the last byte can't form a single output char. * * The value of @inlen after return is the number of octets consumed * as the return value is 0, else unpredictable. * The value of @outlen after return is the number of octets produced. + * + * Returns an XML_ENC_ERR code. */ int xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out, - int *outlen, const unsigned char *in, int *inlen, int flush) { + int *outlen, const unsigned char *in, int *inlen) { int ret; - (void)flush;
if (handler->input != NULL) { + int oldinlen = *inlen; + ret = handler->input(out, outlen, in, inlen); - if (ret > 0) - ret = 0; + if (ret >= 0) { + /* + * The built-in converters don't signal XML_ENC_ERR_SPACE. + */ + if (*inlen < oldinlen) { + if (*outlen > 0) + ret = XML_ENC_ERR_SPACE; + else + ret = XML_ENC_ERR_PARTIAL; + } else { + ret = XML_ENC_ERR_SUCCESS; + } + } } #ifdef LIBXML_ICONV_ENABLED else if (handler->iconv_in != NULL) { @@ -2051,16 +2013,19 @@ xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out, #endif /* LIBXML_ICONV_ENABLED */ #ifdef LIBXML_ICU_ENABLED else if (handler->uconv_in != NULL) { - ret = xmlUconvWrapper(handler->uconv_in, 1, out, outlen, in, inlen, - flush); + ret = xmlUconvWrapper(handler->uconv_in, 1, out, outlen, in, inlen); } #endif /* LIBXML_ICU_ENABLED */ else { *outlen = 0; *inlen = 0; - ret = -2; + ret = XML_ENC_ERR_INTERNAL; }
+ /* Ignore partial errors when reading. */ + if (ret == XML_ENC_ERR_PARTIAL) + ret = XML_ENC_ERR_SUCCESS; + return(ret); }
@@ -2072,12 +2037,7 @@ xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out, * @in: a pointer to an array of input bytes * @inlen: the length of @in * - * Returns 0 if success, or - * -1 by lack of space, or - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or - * -3 if there the last byte can't form a single output char. - * -4 if no output function was found. + * Returns an XML_ENC_ERR code. * * The value of @inlen after return is the number of octets consumed * as the return value is 0, else unpredictable. @@ -2089,9 +2049,22 @@ xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out, int ret;
if (handler->output != NULL) { + int oldinlen = *inlen; + ret = handler->output(out, outlen, in, inlen); - if (ret > 0) - ret = 0; + if (ret >= 0) { + /* + * The built-in converters don't signal XML_ENC_ERR_SPACE. + */ + if (*inlen < oldinlen) { + if (*outlen > 0) + ret = XML_ENC_ERR_SPACE; + else + ret = XML_ENC_ERR_PARTIAL; + } else { + ret = XML_ENC_ERR_SUCCESS; + } + } } #ifdef LIBXML_ICONV_ENABLED else if (handler->iconv_out != NULL) { @@ -2100,26 +2073,31 @@ xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out, #endif /* LIBXML_ICONV_ENABLED */ #ifdef LIBXML_ICU_ENABLED else if (handler->uconv_out != NULL) { - ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen, - 1); + ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen); } #endif /* LIBXML_ICU_ENABLED */ else { *outlen = 0; *inlen = 0; - ret = -4; + ret = XML_ENC_ERR_INTERNAL; }
+ /* We shouldn't generate partial sequences when writing. */ + if (ret == XML_ENC_ERR_PARTIAL) + ret = XML_ENC_ERR_INTERNAL; + return(ret); }
/** * xmlCharEncFirstLine: - * @handler: char encoding transformation data structure + * @handler: char encoding transformation data structure * @out: an xmlBuffer for the output. * @in: an xmlBuffer for the input * * DEPERECATED: Don't use. + * + * Returns the number of bytes written or an XML_ENC_ERR code. */ int xmlCharEncFirstLine(xmlCharEncodingHandler *handler, xmlBufferPtr out, @@ -2130,96 +2108,74 @@ xmlCharEncFirstLine(xmlCharEncodingHandler *handler, xmlBufferPtr out, /** * xmlCharEncInput: * @input: a parser input buffer - * @flush: try to flush all the raw buffer * * Generic front-end for the encoding handler on parser input * - * Returns the number of byte written if success, or - * -1 general error - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or + * Returns the number of bytes written or an XML_ENC_ERR code. */ int -xmlCharEncInput(xmlParserInputBufferPtr input, int flush) +xmlCharEncInput(xmlParserInputBufferPtr input) { int ret; - size_t written; + size_t avail; size_t toconv; int c_in; int c_out; xmlBufPtr in; xmlBufPtr out; + const xmlChar *inData; + size_t inTotal = 0;
if ((input == NULL) || (input->encoder == NULL) || (input->buffer == NULL) || (input->raw == NULL)) - return (-1); + return(XML_ENC_ERR_INTERNAL); out = input->buffer; in = input->raw;
toconv = xmlBufUse(in); if (toconv == 0) return (0); - if ((toconv > 64 * 1024) && (flush == 0)) - toconv = 64 * 1024; - written = xmlBufAvail(out); - if (toconv * 2 >= written) { - if (xmlBufGrow(out, toconv * 2) < 0) - return (-1); - written = xmlBufAvail(out); - } - if ((written > 128 * 1024) && (flush == 0)) - written = 128 * 1024; - - c_in = toconv; - c_out = written; - ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out, - xmlBufContent(in), &c_in, flush); - xmlBufShrink(in, c_in); - xmlBufAddLen(out, c_out); - if (ret == -1) - ret = -3; - - switch (ret) { - case 0: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of input\n", - c_in, c_out); -#endif - break; - case -1: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of input, %d left\n", - c_in, c_out, (int)xmlBufUse(in)); -#endif - break; - case -3: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of input, %d left\n", - c_in, c_out, (int)xmlBufUse(in)); -#endif - break; - case -2: { - char buf[50]; - const xmlChar *content = xmlBufContent(in); - - snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X", - content[0], content[1], - content[2], content[3]); - buf[49] = 0; - xmlEncodingErr(XML_I18N_CONV_FAILED, - "input conversion failed due to input error, bytes %s\n", - buf); + inData = xmlBufContent(in); + inTotal = 0; + + do { + c_in = toconv > INT_MAX / 2 ? INT_MAX / 2 : toconv; + + avail = xmlBufAvail(out); + if (avail > INT_MAX) + avail = INT_MAX; + if (avail < 4096) { + if (xmlBufGrow(out, 4096) < 0) { + input->error = XML_ERR_NO_MEMORY; + return(XML_ENC_ERR_MEMORY); + } + avail = xmlBufAvail(out); } + + c_in = toconv; + c_out = avail; + ret = xmlEncInputChunk(input->encoder, xmlBufEnd(out), &c_out, + inData, &c_in); + inTotal += c_in; + inData += c_in; + toconv -= c_in; + xmlBufAddLen(out, c_out); + } while (ret == XML_ENC_ERR_SPACE); + + xmlBufShrink(in, inTotal); + + if (input->rawconsumed > ULONG_MAX - (unsigned long)c_in) + input->rawconsumed = ULONG_MAX; + else + input->rawconsumed += c_in; + + if ((c_out == 0) && (ret != 0)) { + if (input->error == 0) + input->error = xmlEncConvertError(ret); + return(ret); } - /* - * Ignore when input buffer is not on a boundary - */ - if (ret == -3) - ret = 0; - return (c_out? c_out : ret); + + return (c_out); }
/** @@ -2230,10 +2186,7 @@ xmlCharEncInput(xmlParserInputBufferPtr input, int flush) * * Generic front-end for the encoding handler input function * - * Returns the number of byte written if success, or - * -1 general error - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or + * Returns the number of bytes written or an XML_ENC_ERR code. */ int xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out, @@ -2244,11 +2197,11 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out, int toconv;
if (handler == NULL) - return (-1); + return(XML_ENC_ERR_INTERNAL); if (out == NULL) - return (-1); + return(XML_ENC_ERR_INTERNAL); if (in == NULL) - return (-1); + return(XML_ENC_ERR_INTERNAL);
toconv = in->use; if (toconv == 0) @@ -2259,52 +2212,11 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out, written = out->size - out->use - 1; } ret = xmlEncInputChunk(handler, &out->content[out->use], &written, - in->content, &toconv, 1); + in->content, &toconv); xmlBufferShrink(in, toconv); out->use += written; out->content[out->use] = 0; - if (ret == -1) - ret = -3; - - switch (ret) { - case 0: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of input\n", - toconv, written); -#endif - break; - case -1: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of input, %d left\n", - toconv, written, in->use); -#endif - break; - case -3: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of input, %d left\n", - toconv, written, in->use); -#endif - break; - case -2: { - char buf[50]; - - snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X", - in->content[0], in->content[1], - in->content[2], in->content[3]); - buf[49] = 0; - xmlEncodingErr(XML_I18N_CONV_FAILED, - "input conversion failed due to input error, bytes %s\n", - buf); - } - } - /* - * Ignore when input buffer is not on a boundary - */ - if (ret == -3) - ret = 0; + return (written? written : ret); }
@@ -2321,10 +2233,7 @@ xmlCharEncInFunc(xmlCharEncodingHandler * handler, xmlBufferPtr out, * In case of UTF8 sequence conversion errors for the given encoder, * the content will be automatically remapped to a CharRef sequence. * - * Returns the number of byte written if success, or - * -1 general error - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or + * Returns the number of bytes written or an XML_ENC_ERR code. */ int xmlCharEncOutput(xmlOutputBufferPtr output, int init) @@ -2340,7 +2249,7 @@ xmlCharEncOutput(xmlOutputBufferPtr output, int init)
if ((output == NULL) || (output->encoder == NULL) || (output->buffer == NULL) || (output->conv == NULL)) - return (-1); + return(XML_ENC_ERR_INTERNAL); out = output->conv; in = output->buffer;
@@ -2358,10 +2267,6 @@ retry: xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out, NULL, &c_in); xmlBufAddLen(out, c_out); -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "initialized encoder\n"); -#endif return(c_out); }
@@ -2369,8 +2274,6 @@ retry: * Conversion itself. */ toconv = xmlBufUse(in); - if (toconv == 0) - return (writtentot); if (toconv > 64 * 1024) toconv = 64 * 1024; if (toconv * 4 >= written) { @@ -2387,94 +2290,54 @@ retry: xmlBufShrink(in, c_in); xmlBufAddLen(out, c_out); writtentot += c_out; - if (ret == -1) { - if (c_out > 0) { - /* Can be a limitation of iconv or uconv */ - goto retry; - } - ret = -3; - } + + if (ret == XML_ENC_ERR_SPACE) + goto retry;
/* * Attempt to handle error cases */ - switch (ret) { - case 0: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of output\n", - c_in, c_out); -#endif - break; - case -1: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "output conversion failed by lack of space\n"); -#endif - break; - case -3: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of output %d left\n", - c_in, c_out, (int) xmlBufUse(in)); -#endif - break; - case -4: - xmlEncodingErr(XML_I18N_NO_OUTPUT, - "xmlCharEncOutFunc: no output function !\n", NULL); - ret = -1; - break; - case -2: { - xmlChar charref[20]; - int len = xmlBufUse(in); - xmlChar *content = xmlBufContent(in); - int cur, charrefLen; - - cur = xmlGetUTF8Char(content, &len); - if (cur <= 0) - break; + if (ret == XML_ENC_ERR_INPUT) { + xmlChar charref[20]; + int len = xmlBufUse(in); + xmlChar *content = xmlBufContent(in); + int cur, charrefLen;
-#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "handling output conversion error\n"); - xmlGenericError(xmlGenericErrorContext, - "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - content[0], content[1], - content[2], content[3]); -#endif - /* - * Removes the UTF8 sequence, and replace it by a charref - * and continue the transcoding phase, hoping the error - * did not mangle the encoder state. - */ - charrefLen = snprintf((char *) &charref[0], sizeof(charref), - "&#%d;", cur); - xmlBufShrink(in, len); - xmlBufGrow(out, charrefLen * 4); - c_out = xmlBufAvail(out); - c_in = charrefLen; - ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out, - charref, &c_in); - - if ((ret < 0) || (c_in != charrefLen)) { - char buf[50]; - - snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X", - content[0], content[1], - content[2], content[3]); - buf[49] = 0; - xmlEncodingErr(XML_I18N_CONV_FAILED, - "output conversion failed due to conv error, bytes %s\n", - buf); - content[0] = ' '; - break; - } + cur = xmlGetUTF8Char(content, &len); + if (cur <= 0) + goto error;
- xmlBufAddLen(out, c_out); - writtentot += c_out; - goto retry; - } + /* + * Removes the UTF8 sequence, and replace it by a charref + * and continue the transcoding phase, hoping the error + * did not mangle the encoder state. + */ + charrefLen = snprintf((char *) &charref[0], sizeof(charref), + "&#%d;", cur); + xmlBufShrink(in, len); + xmlBufGrow(out, charrefLen * 4); + c_out = xmlBufAvail(out); + c_in = charrefLen; + ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out, + charref, &c_in); + if ((ret < 0) || (c_in != charrefLen)) { + ret = XML_ENC_ERR_INTERNAL; + goto error; + } + + xmlBufAddLen(out, c_out); + writtentot += c_out; + goto retry; } - return(writtentot ? writtentot : ret); + +error: + if ((writtentot <= 0) && (ret != 0)) { + if (output->error == 0) + output->error = xmlEncConvertError(ret); + return(ret); + } + + return(writtentot); } #endif
@@ -2491,10 +2354,7 @@ retry: * In case of UTF8 sequence conversion errors for the given encoder, * the content will be automatically remapped to a CharRef sequence. * - * Returns the number of byte written if success, or - * -1 general error - * -2 if the transcoding fails (for *in is not valid utf8 string or - * the result of transformation can't fit into the encoding we want), or + * Returns the number of bytes written or an XML_ENC_ERR code. */ int xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out, @@ -2504,8 +2364,8 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out, int writtentot = 0; int toconv;
- if (handler == NULL) return(-1); - if (out == NULL) return(-1); + if (handler == NULL) return(XML_ENC_ERR_INTERNAL); + if (out == NULL) return(XML_ENC_ERR_INTERNAL);
retry:
@@ -2524,10 +2384,6 @@ retry: NULL, &toconv); out->use += written; out->content[out->use] = 0; -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "initialized encoder\n"); -#endif return(0); }
@@ -2535,8 +2391,6 @@ retry: * Conversion itself. */ toconv = in->use; - if (toconv == 0) - return(0); if (toconv * 4 >= written) { xmlBufferGrow(out, toconv * 4); written = out->size - out->use - 1; @@ -2547,93 +2401,43 @@ retry: out->use += written; writtentot += written; out->content[out->use] = 0; - if (ret == -1) { - if (written > 0) { - /* Can be a limitation of iconv or uconv */ - goto retry; - } - ret = -3; - } + + if (ret == XML_ENC_ERR_SPACE) + goto retry;
/* * Attempt to handle error cases */ - switch (ret) { - case 0: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "converted %d bytes to %d bytes of output\n", - toconv, written); -#endif - break; - case -1: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "output conversion failed by lack of space\n"); -#endif - break; - case -3: -#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext,"converted %d bytes to %d bytes of output %d left\n", - toconv, written, in->use); -#endif - break; - case -4: - xmlEncodingErr(XML_I18N_NO_OUTPUT, - "xmlCharEncOutFunc: no output function !\n", NULL); - ret = -1; - break; - case -2: { - xmlChar charref[20]; - int len = in->use; - const xmlChar *utf = (const xmlChar *) in->content; - int cur, charrefLen; - - cur = xmlGetUTF8Char(utf, &len); - if (cur <= 0) - break; + if (ret == XML_ENC_ERR_INPUT) { + xmlChar charref[20]; + int len = in->use; + const xmlChar *utf = (const xmlChar *) in->content; + int cur, charrefLen;
-#ifdef DEBUG_ENCODING - xmlGenericError(xmlGenericErrorContext, - "handling output conversion error\n"); - xmlGenericError(xmlGenericErrorContext, - "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - in->content[0], in->content[1], - in->content[2], in->content[3]); -#endif - /* - * Removes the UTF8 sequence, and replace it by a charref - * and continue the transcoding phase, hoping the error - * did not mangle the encoder state. - */ - charrefLen = snprintf((char *) &charref[0], sizeof(charref), - "&#%d;", cur); - xmlBufferShrink(in, len); - xmlBufferGrow(out, charrefLen * 4); - written = out->size - out->use - 1; - toconv = charrefLen; - ret = xmlEncOutputChunk(handler, &out->content[out->use], &written, - charref, &toconv); - - if ((ret < 0) || (toconv != charrefLen)) { - char buf[50]; - - snprintf(&buf[0], 49, "0x%02X 0x%02X 0x%02X 0x%02X", - in->content[0], in->content[1], - in->content[2], in->content[3]); - buf[49] = 0; - xmlEncodingErr(XML_I18N_CONV_FAILED, - "output conversion failed due to conv error, bytes %s\n", - buf); - in->content[0] = ' '; - break; - } + cur = xmlGetUTF8Char(utf, &len); + if (cur <= 0) + return(ret);
- out->use += written; - writtentot += written; - out->content[out->use] = 0; - goto retry; - } + /* + * Removes the UTF8 sequence, and replace it by a charref + * and continue the transcoding phase, hoping the error + * did not mangle the encoder state. + */ + charrefLen = snprintf((char *) &charref[0], sizeof(charref), + "&#%d;", cur); + xmlBufferShrink(in, len); + xmlBufferGrow(out, charrefLen * 4); + written = out->size - out->use - 1; + toconv = charrefLen; + ret = xmlEncOutputChunk(handler, &out->content[out->use], &written, + charref, &toconv); + if ((ret < 0) || (toconv != charrefLen)) + return(XML_ENC_ERR_INTERNAL); + + out->use += written; + writtentot += written; + out->content[out->use] = 0; + goto retry; } return(writtentot ? writtentot : ret); } @@ -2704,14 +2508,6 @@ xmlCharEncCloseFunc(xmlCharEncodingHandler *handler) { handler->name = NULL; xmlFree(handler); } -#ifdef DEBUG_ENCODING - if (ret) - xmlGenericError(xmlGenericErrorContext, - "failed to close the encoding handler\n"); - else - xmlGenericError(xmlGenericErrorContext, - "closed the encoding handler\n"); -#endif
return(ret); } @@ -2757,15 +2553,11 @@ xmlByteConsumed(xmlParserCtxtPtr ctxt) { written = 32000; ret = xmlEncOutputChunk(handler, &convbuf[0], &written, cur, &toconv); - if (ret < 0) { - if (written > 0) - ret = -2; - else - return(-1); - } + if ((ret != XML_ENC_ERR_SUCCESS) && (ret != XML_ENC_ERR_SPACE)) + return(-1); unused += written; cur += toconv; - } while (ret == -2); + } while (ret == XML_ENC_ERR_SPACE); } if (in->buf->rawconsumed < unused) return(-1); @@ -2788,9 +2580,10 @@ xmlByteConsumed(xmlParserCtxtPtr ctxt) { * Take a block of UTF-8 chars in and try to convert it to an ISO 8859-* * block of chars out. * - * Returns 0 if success, -2 if the transcoding fails, or -1 otherwise + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of @inlen after return is the number of octets consumed - * as the return value is positive, else unpredictable. + * as the return value is positive, else unpredictable. * The value of @outlen after return is the number of octets consumed. */ static int @@ -2804,7 +2597,7 @@ UTF8ToISO8859x(unsigned char* out, int *outlen,
if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (xlattable == NULL)) - return(-1); + return(XML_ENC_ERR_INTERNAL); if (in == NULL) { /* * initialization nothing to do @@ -2822,21 +2615,21 @@ UTF8ToISO8859x(unsigned char* out, int *outlen, /* trailing byte in leading position */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } else if (d < 0xE0) { unsigned char c; if (!(in < inend)) { /* trailing byte not in input buffer */ *outlen = out - outstart; *inlen = processed - instart; - return(-3); + return(XML_ENC_ERR_PARTIAL); } c = *in++; if ((c & 0xC0) != 0x80) { /* not a trailing byte */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } c = c & 0x3F; d = d & 0x1F; @@ -2845,7 +2638,7 @@ UTF8ToISO8859x(unsigned char* out, int *outlen, /* not in character set */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } *out++ = d; } else if (d < 0xF0) { @@ -2855,21 +2648,21 @@ UTF8ToISO8859x(unsigned char* out, int *outlen, /* trailing bytes not in input buffer */ *outlen = out - outstart; *inlen = processed - instart; - return(-3); + return(XML_ENC_ERR_PARTIAL); } c1 = *in++; if ((c1 & 0xC0) != 0x80) { /* not a trailing byte (c1) */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } c2 = *in++; if ((c2 & 0xC0) != 0x80) { /* not a trailing byte (c2) */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } c1 = c1 & 0x3F; c2 = c2 & 0x3F; @@ -2880,14 +2673,14 @@ UTF8ToISO8859x(unsigned char* out, int *outlen, /* not in character set */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } *out++ = d; } else { /* cannot transcode >= U+010000 */ *outlen = out - outstart; *inlen = processed - instart; - return(-2); + return(XML_ENC_ERR_INPUT); } processed = in; } @@ -2905,7 +2698,9 @@ UTF8ToISO8859x(unsigned char* out, int *outlen, * * Take a block of ISO 8859-* chars in and try to convert it to an UTF-8 * block of chars out. - * Returns 0 if success, or -1 otherwise + * + * Returns the number of bytes written or an XML_ENC_ERR code. + * * The value of @inlen after return is the number of octets consumed * The value of @outlen after return is the number of octets produced. */ @@ -2922,7 +2717,7 @@ ISO8859xToUTF8(unsigned char* out, int *outlen,
if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL) || (unicodetable == NULL)) - return(-1); + return(XML_ENC_ERR_INTERNAL); outend = out + *outlen; inend = in + *inlen; instop = inend; @@ -2934,7 +2729,7 @@ ISO8859xToUTF8(unsigned char* out, int *outlen, /* undefined code point */ *outlen = out - outstart; *inlen = in - instart; - return (-1); + return(XML_ENC_ERR_INPUT); } if (c < 0x800) { *out++ = ((c >> 6) & 0x1F) | 0xC0; diff --git a/libs/xml2/entities.c b/libs/xml2/entities.c index 52eb9d5bdbc..aec51441476 100644 --- a/libs/xml2/entities.c +++ b/libs/xml2/entities.c @@ -23,7 +23,6 @@ #include <libxml/parser.h> #include <libxml/parserInternals.h> #include <libxml/xmlerror.h> -#include <libxml/globals.h> #include <libxml/dict.h>
#include "private/entities.h" @@ -114,7 +113,7 @@ xmlEntitiesWarn(xmlParserErrors code, const char *msg, const xmlChar *str1) /* * xmlFreeEntity : clean-up an entity record. */ -static void +void xmlFreeEntity(xmlEntityPtr entity) { xmlDictPtr dict = NULL; @@ -718,8 +717,6 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) { (((cur[0] & 0xF8) == 0xF8))) { xmlEntitiesErr(XML_CHECK_NOT_UTF8, "xmlEncodeEntities: input not UTF-8"); - if (doc != NULL) - doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1"); snprintf(buf, sizeof(buf), "&#%d;", *cur); buf[sizeof(buf) - 1] = 0; ptr = buf; @@ -751,8 +748,6 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) { if ((l == 1) || (!IS_CHAR(val))) { xmlEntitiesErr(XML_ERR_INVALID_CHAR, "xmlEncodeEntities: char out of range\n"); - if (doc != NULL) - doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1"); snprintf(buf, sizeof(buf), "&#%d;", *cur); buf[sizeof(buf) - 1] = 0; ptr = buf; diff --git a/libs/xml2/error.c b/libs/xml2/error.c index f4f3cf2039f..746b73716bc 100644 --- a/libs/xml2/error.c +++ b/libs/xml2/error.c @@ -14,7 +14,6 @@ #include <libxml/parser.h> #include <libxml/xmlerror.h> #include <libxml/xmlmemory.h> -#include <libxml/globals.h>
#include "private/error.h"
@@ -881,9 +880,9 @@ xmlParserValidityWarning(void *ctx, const char *msg, ...) * Get the last global error registered. This is per thread if compiled * with thread support. * - * Returns NULL if no error occurred or a pointer to the error + * Returns a pointer to the error */ -xmlErrorPtr +const xmlError * xmlGetLastError(void) { if (xmlLastError.code == XML_ERR_OK) @@ -940,7 +939,7 @@ xmlResetLastError(void) * * Returns NULL if no error occurred or a pointer to the error */ -xmlErrorPtr +const xmlError * xmlCtxtGetLastError(void *ctx) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; @@ -982,7 +981,7 @@ xmlCtxtResetLastError(void *ctx) * Returns 0 in case of success and -1 in case of error. */ int -xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) { +xmlCopyError(const xmlError *from, xmlErrorPtr to) { char *message, *file, *str1, *str2, *str3;
if ((from == NULL) || (to == NULL)) diff --git a/libs/xml2/globals.c b/libs/xml2/globals.c index 46035519d51..6193f388cbb 100644 --- a/libs/xml2/globals.c +++ b/libs/xml2/globals.c @@ -2,9 +2,6 @@ * globals.c: definition and handling of the set of global variables * of the library * - * The bottom of this file is automatically generated by build_glob.py - * based on the description file global.data - * * See Copyright for the status of this software. * * Gary Pennington Gary.Pennington@uk.sun.com @@ -14,51 +11,152 @@ #define IN_LIBXML #include "libxml.h"
+#include <stdio.h> #include <stdlib.h> #include <string.h>
+#define XML_GLOBALS_NO_REDEFINITION #include <libxml/globals.h> +#include <libxml/xmlerror.h> #include <libxml/xmlmemory.h> +#include <libxml/xmlIO.h> +#include <libxml/HTMLparser.h> +#include <libxml/parser.h> #include <libxml/threads.h> +#include <libxml/tree.h> +#include <libxml/SAX.h> +#include <libxml/SAX2.h>
#include "private/error.h" #include "private/globals.h" #include "private/threads.h" #include "private/tree.h"
-/* #define DEBUG_GLOBALS */ +/* + * Thread-local storage emulation. + * + * This works by replacing a global variable + * + * extern xmlError xmlLastError; + * + * with a macro that calls a function returning a pointer to the global in + * thread-local storage: + * + * xmlError *__xmlLastError(void); + * #define xmlError (*__xmlLastError()); + * + * The code can operate in a multitude of ways depending on the environment. + * First we support POSIX and Windows threads. Then we support both thread-local + * storage provided by the compiler and older methods like thread-specific data + * (pthreads) or TlsAlloc (Windows). + * + * To clean up thread-local storage, we use thread-specific data on POSIX. + * On Windows, we either use DllMain when compiling a DLL or a registered wait + * function for static builds. + */
/* * Helpful Macro */ #ifdef LIBXML_THREAD_ENABLED -#define IS_MAIN_THREAD (xmlIsMainThread()) +#define IS_MAIN_THREAD (xmlIsMainThreadInternal()) #else #define IS_MAIN_THREAD 1 #endif
+#define XML_DECLARE_MEMBER(name, type, attrs) \ + type gs_##name; + +struct _xmlGlobalState { + int initialized; + +#if defined(HAVE_WIN32_THREADS) && \ + defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) + void *threadHandle; + void *waitHandle; +#endif + +#define XML_OP XML_DECLARE_MEMBER +XML_GLOBALS_ALLOC +XML_GLOBALS_ERROR +XML_GLOBALS_HTML +XML_GLOBALS_IO +XML_GLOBALS_PARSER +XML_GLOBALS_TREE +#undef XML_OP +}; + +static int parserInitialized; + /* * Mutex to protect "ForNewThreads" variables */ static xmlMutex xmlThrDefMutex;
-/** - * xmlInitGlobals: +#ifdef LIBXML_THREAD_ENABLED + +/* + * On Darwin, thread-local storage destructors seem to be run before + * pthread thread-specific data destructors. This causes ASan to + * report a use-after-free. * - * DEPRECATED: Alias for xmlInitParser. + * On Windows, we can't use TLS in static builds. The RegisterWait + * callback would run after TLS was deallocated. */ -void xmlInitGlobals(void) { - xmlInitParser(); -} +#if defined(XML_THREAD_LOCAL) && \ + !defined(__APPLE__) && \ + (!defined(HAVE_WIN32_THREADS) || \ + !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) +#define USE_TLS +#endif
-/** - * xmlInitGlobalsInternal: - * - * Additional initialisation for multi-threading +#ifdef USE_TLS +static XML_THREAD_LOCAL xmlGlobalState globalState; +#endif + +#ifdef HAVE_POSIX_THREADS + +/* + * Weak symbol hack, see threads.c */ -void xmlInitGlobalsInternal(void) { - xmlInitMutex(&xmlThrDefMutex); -} +#if defined(__GNUC__) && \ + defined(__GLIBC__) && \ + __GLIBC__ * 100 + __GLIBC_MINOR__ < 234 + +#pragma weak pthread_getspecific +#pragma weak pthread_setspecific +#pragma weak pthread_key_create +#pragma weak pthread_key_delete +#pragma weak pthread_equal +#pragma weak pthread_self + +#define XML_PTHREAD_WEAK + +static int libxml_is_threaded = -1; + +#endif + +/* + * On POSIX, we need thread-specific data even with thread-local storage + * to destroy indirect references from global state (xmlLastError) at + * thread exit. + */ +static pthread_key_t globalkey; +static pthread_t mainthread; + +#elif defined HAVE_WIN32_THREADS + +#ifndef USE_TLS +static DWORD globalkey = TLS_OUT_OF_INDEXES; +#endif +static DWORD mainthread; + +#endif /* HAVE_WIN32_THREADS */ + +static void +xmlFreeGlobalState(void *state); + +#endif /* LIBXML_THREAD_ENABLED */
/************************************************************************ * * @@ -69,13 +167,8 @@ void xmlInitGlobalsInternal(void) { /* * Memory allocation routines */ -#undef xmlFree -#undef xmlMalloc -#undef xmlMallocAtomic -#undef xmlMemStrdup -#undef xmlRealloc
-#if defined(DEBUG_MEMORY_LOCATION) || defined(DEBUG_MEMORY) +#if defined(DEBUG_MEMORY_LOCATION) xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree; xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc; xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc; @@ -140,46 +233,7 @@ xmlPosixStrdup(const char *cur) { * Returns the copy of the string or NULL in case of error */ xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup; -#endif /* DEBUG_MEMORY_LOCATION || DEBUG_MEMORY */ - -#include <libxml/threads.h> -#include <libxml/globals.h> -#include <libxml/SAX.h> - -#undef htmlDefaultSAXHandler -#undef oldXMLWDcompatibility -#undef xmlBufferAllocScheme -#undef xmlDefaultBufferSize -#undef xmlDefaultSAXHandler -#undef xmlDefaultSAXLocator -#undef xmlDoValidityCheckingDefaultValue -#undef xmlGenericError -#undef xmlStructuredError -#undef xmlGenericErrorContext -#undef xmlStructuredErrorContext -#undef xmlGetWarningsDefaultValue -#undef xmlIndentTreeOutput -#undef xmlTreeIndentString -#undef xmlKeepBlanksDefaultValue -#undef xmlLineNumbersDefaultValue -#undef xmlLoadExtDtdDefaultValue -#undef xmlParserDebugEntities -#undef xmlParserVersion -#undef xmlPedanticParserDefaultValue -#undef xmlSaveNoEmptyTags -#undef xmlSubstituteEntitiesDefaultValue -#undef xmlRegisterNodeDefaultValue -#undef xmlDeregisterNodeDefaultValue -#undef xmlLastError - -#undef xmlParserInputBufferCreateFilenameValue -#undef xmlOutputBufferCreateFilenameValue -/** - * xmlParserVersion: - * - * Constant string describing the internal version of the library - */ -const char *xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA; +#endif /* DEBUG_MEMORY_LOCATION */
/** * xmlBufferAllocScheme: @@ -364,6 +418,7 @@ void *xmlStructuredErrorContext = NULL; static void *xmlStructuredErrorContextThrDef = NULL; xmlError xmlLastError;
+#ifdef LIBXML_OUTPUT_ENABLED /* * output defaults */ @@ -394,6 +449,7 @@ static const char *xmlTreeIndentStringThrDef = " "; */ int xmlSaveNoEmptyTags = 0; static int xmlSaveNoEmptyTagsThrDef = 0; +#endif /* LIBXML_OUTPUT_ENABLED */
#ifdef LIBXML_SAX1_ENABLED /** @@ -492,77 +548,54 @@ xmlSAXHandlerV1 htmlDefaultSAXHandler = { }; #endif /* LIBXML_HTML_ENABLED */
+/************************************************************************ + * * + * Per thread global state handling * + * * + ************************************************************************/ + /** - * xmlInitializeGlobalState: - * @gs: a pointer to a newly allocated global state + * xmlInitGlobals: * - * xmlInitializeGlobalState() initialize a global state with all the - * default values of the library. + * DEPRECATED: Alias for xmlInitParser. */ -void -xmlInitializeGlobalState(xmlGlobalStatePtr gs) -{ -#ifdef DEBUG_GLOBALS - fprintf(stderr, "Initializing globals at %p for thread %d\n", - (void *) gs, xmlGetThreadId()); -#endif +void xmlInitGlobals(void) { + xmlInitParser(); +}
- xmlMutexLock(&xmlThrDefMutex); +/** + * xmlInitGlobalsInternal: + * + * Additional initialisation for multi-threading + */ +void xmlInitGlobalsInternal(void) { + xmlInitMutex(&xmlThrDefMutex);
-#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED) - inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler); +#ifdef HAVE_POSIX_THREADS +#ifdef XML_PTHREAD_WEAK + if (libxml_is_threaded == -1) + libxml_is_threaded = + (pthread_getspecific != NULL) && + (pthread_setspecific != NULL) && + (pthread_key_create != NULL) && + (pthread_key_delete != NULL) && + /* + * pthread_equal can be inline, resuting in -Waddress warnings. + * Let's assume it's available if all the other functions are. + */ + /* (pthread_equal != NULL) && */ + (pthread_self != NULL); + if (libxml_is_threaded == 0) + return; +#endif /* XML_PTHREAD_WEAK */ + pthread_key_create(&globalkey, xmlFreeGlobalState); + mainthread = pthread_self(); +#elif defined(HAVE_WIN32_THREADS) +#ifndef USE_TLS + globalkey = TlsAlloc(); #endif - - gs->oldXMLWDcompatibility = 0; - gs->xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef; - gs->xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef; -#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED) - initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1); -#endif /* LIBXML_SAX1_ENABLED */ - gs->xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId; - gs->xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId; - gs->xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber; - gs->xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber; - gs->xmlDoValidityCheckingDefaultValue = - xmlDoValidityCheckingDefaultValueThrDef; -#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY) - gs->xmlFree = (xmlFreeFunc) xmlMemFree; - gs->xmlMalloc = (xmlMallocFunc) xmlMemMalloc; - gs->xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc; - gs->xmlRealloc = (xmlReallocFunc) xmlMemRealloc; - gs->xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup; -#else - gs->xmlFree = (xmlFreeFunc) free; - gs->xmlMalloc = (xmlMallocFunc) malloc; - gs->xmlMallocAtomic = (xmlMallocFunc) malloc; - gs->xmlRealloc = (xmlReallocFunc) realloc; - gs->xmlMemStrdup = (xmlStrdupFunc) xmlStrdup; + mainthread = GetCurrentThreadId(); #endif - gs->xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef; - gs->xmlIndentTreeOutput = xmlIndentTreeOutputThrDef; - gs->xmlTreeIndentString = xmlTreeIndentStringThrDef; - gs->xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef; - gs->xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef; - gs->xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef; - gs->xmlParserDebugEntities = xmlParserDebugEntitiesThrDef; - gs->xmlParserVersion = LIBXML_VERSION_STRING; - gs->xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef; - gs->xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef; - gs->xmlSubstituteEntitiesDefaultValue = - xmlSubstituteEntitiesDefaultValueThrDef; - - gs->xmlGenericError = xmlGenericErrorThrDef; - gs->xmlStructuredError = xmlStructuredErrorThrDef; - gs->xmlGenericErrorContext = xmlGenericErrorContextThrDef; - gs->xmlStructuredErrorContext = xmlStructuredErrorContextThrDef; - gs->xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef; - gs->xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef; - - gs->xmlParserInputBufferCreateFilenameValue = xmlParserInputBufferCreateFilenameValueThrDef; - gs->xmlOutputBufferCreateFilenameValue = xmlOutputBufferCreateFilenameValueThrDef; - memset(&gs->xmlLastError, 0, sizeof(xmlError)); - - xmlMutexUnlock(&xmlThrDefMutex); }
/** @@ -585,225 +618,411 @@ void xmlCleanupGlobalsInternal(void) { xmlResetError(&xmlLastError);
xmlCleanupMutex(&xmlThrDefMutex); - __xmlGlobalInitMutexDestroy(); -}
-void -xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) { - xmlMutexLock(&xmlThrDefMutex); - xmlGenericErrorContextThrDef = ctx; - if (handler != NULL) - xmlGenericErrorThrDef = handler; - else - xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc; - xmlMutexUnlock(&xmlThrDefMutex); +#ifdef HAVE_POSIX_THREADS +#ifdef XML_PTHREAD_WEAK + if (libxml_is_threaded == 0) + return; +#endif /* XML_PTHREAD_WEAK */ + pthread_key_delete(globalkey); +#elif defined(HAVE_WIN32_THREADS) +#ifndef USE_TLS + if (globalkey != TLS_OUT_OF_INDEXES) { + TlsFree(globalkey); + globalkey = TLS_OUT_OF_INDEXES; + } +#endif +#endif + + parserInitialized = 0; }
+/** + * xmlInitializeGlobalState: + * @gs: a pointer to a newly allocated global state + * + * DEPRECATED: No-op. + */ void -xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) { - xmlMutexLock(&xmlThrDefMutex); - xmlStructuredErrorContextThrDef = ctx; - xmlStructuredErrorThrDef = handler; - xmlMutexUnlock(&xmlThrDefMutex); +xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED) +{ }
/** - * xmlRegisterNodeDefault: - * @func: function pointer to the new RegisterNodeFunc + * xmlGetGlobalState: * - * Registers a callback for node creation + * DEPRECATED * - * Returns the old value of the registration function + * Returns NULL. */ -xmlRegisterNodeFunc -xmlRegisterNodeDefault(xmlRegisterNodeFunc func) +xmlGlobalStatePtr +xmlGetGlobalState(void) { - xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue; - - __xmlRegisterCallbacks = 1; - xmlRegisterNodeDefaultValue = func; - return(old); + return(NULL); }
-xmlRegisterNodeFunc -xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func) -{ - xmlRegisterNodeFunc old; - - xmlMutexLock(&xmlThrDefMutex); - old = xmlRegisterNodeDefaultValueThrDef; - - __xmlRegisterCallbacks = 1; - xmlRegisterNodeDefaultValueThrDef = func; - xmlMutexUnlock(&xmlThrDefMutex); - - return(old); +static int +xmlIsMainThreadInternal(void) { + if (parserInitialized == 0) { + xmlInitParser(); + parserInitialized = 1; + } + +#ifdef HAVE_POSIX_THREADS +#ifdef XML_PTHREAD_WEAK + if (libxml_is_threaded == 0) + return (1); +#endif + return (pthread_equal(mainthread, pthread_self())); +#elif defined HAVE_WIN32_THREADS + return (mainthread == GetCurrentThreadId()); +#else + return (1); +#endif }
/** - * xmlDeregisterNodeDefault: - * @func: function pointer to the new DeregisterNodeFunc + * xmlIsMainThread: + * + * DEPRECATED: Internal function, do not use. * - * Registers a callback for node destruction + * Check whether the current thread is the main thread. * - * Returns the previous value of the deregistration function + * Returns 1 if the current thread is the main thread, 0 otherwise */ -xmlDeregisterNodeFunc -xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func) -{ - xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue; - - __xmlRegisterCallbacks = 1; - xmlDeregisterNodeDefaultValue = func; - return(old); +int +xmlIsMainThread(void) { + return(xmlIsMainThreadInternal()); }
-xmlDeregisterNodeFunc -xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func) -{ - xmlDeregisterNodeFunc old; +#ifdef LIBXML_THREAD_ENABLED
- xmlMutexLock(&xmlThrDefMutex); - old = xmlDeregisterNodeDefaultValueThrDef; +static void +xmlFreeGlobalState(void *state) +{ + xmlGlobalState *gs = (xmlGlobalState *) state; + + /* + * Free any memory allocated in the thread's xmlLastError. If it + * weren't for this indirect allocation, we wouldn't need + * a destructor with thread-local storage at all! + * + * It would be nice if we could make xmlLastError a special error + * type which uses statically allocated, fixed-size buffers. + * But the xmlError struct is fully public and widely used, + * so changes are dangerous. + */ + xmlResetError(&(gs->gs_xmlLastError)); +#ifndef USE_TLS + free(state); +#endif +}
- __xmlRegisterCallbacks = 1; - xmlDeregisterNodeDefaultValueThrDef = func; - xmlMutexUnlock(&xmlThrDefMutex); +#if defined(HAVE_WIN32_THREADS) && \ + defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) +static void WINAPI +xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) { + xmlGlobalStatePtr gs = ctxt;
- return(old); + UnregisterWait(gs->waitHandle); + CloseHandle(gs->threadHandle); + xmlFreeGlobalState(gs); }
-xmlParserInputBufferCreateFilenameFunc -xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func) -{ - xmlParserInputBufferCreateFilenameFunc old; +static int +xmlRegisterGlobalStateDtor(xmlGlobalState *gs) { + void *processHandle = GetCurrentProcess(); + void *threadHandle; + void *waitHandle; + + if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle, + &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) { + return(-1); + } + + if (RegisterWaitForSingleObject(&waitHandle, threadHandle, + xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) { + CloseHandle(threadHandle); + return(-1); + } + + gs->threadHandle = threadHandle; + gs->waitHandle = waitHandle; + return(0); +} +#endif /* LIBXML_STATIC */
+static void +xmlInitGlobalState(xmlGlobalStatePtr gs) { xmlMutexLock(&xmlThrDefMutex); - old = xmlParserInputBufferCreateFilenameValueThrDef; - if (old == NULL) { - old = __xmlParserInputBufferCreateFilename; - } - - xmlParserInputBufferCreateFilenameValueThrDef = func; - xmlMutexUnlock(&xmlThrDefMutex);
- return(old); -} - -xmlOutputBufferCreateFilenameFunc -xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func) -{ - xmlOutputBufferCreateFilenameFunc old; +#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED) + inithtmlDefaultSAXHandler(&gs->gs_htmlDefaultSAXHandler); +#endif
- xmlMutexLock(&xmlThrDefMutex); - old = xmlOutputBufferCreateFilenameValueThrDef; + gs->gs_oldXMLWDcompatibility = 0; + gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef; + gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef; +#if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED) + initxmlDefaultSAXHandler(&gs->gs_xmlDefaultSAXHandler, 1); +#endif /* LIBXML_SAX1_ENABLED */ + gs->gs_xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId; + gs->gs_xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId; + gs->gs_xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber; + gs->gs_xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber; + gs->gs_xmlDoValidityCheckingDefaultValue = + xmlDoValidityCheckingDefaultValueThrDef; +#ifdef LIBXML_THREAD_ALLOC_ENABLED +#ifdef DEBUG_MEMORY_LOCATION + gs->gs_xmlFree = xmlMemFree; + gs->gs_xmlMalloc = xmlMemMalloc; + gs->gs_xmlMallocAtomic = xmlMemMalloc; + gs->gs_xmlRealloc = xmlMemRealloc; + gs->gs_xmlMemStrdup = xmlMemoryStrdup; +#else + gs->gs_xmlFree = free; + gs->gs_xmlMalloc = malloc; + gs->gs_xmlMallocAtomic = malloc; + gs->gs_xmlRealloc = realloc; + gs->gs_xmlMemStrdup = xmlPosixStrdup; +#endif +#endif + gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef; #ifdef LIBXML_OUTPUT_ENABLED - if (old == NULL) { - old = __xmlOutputBufferCreateFilename; - } + gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef; + gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef; + gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef; #endif - xmlOutputBufferCreateFilenameValueThrDef = func; - xmlMutexUnlock(&xmlThrDefMutex); + gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef; + gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef; + gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef; + gs->gs_xmlParserDebugEntities = xmlParserDebugEntitiesThrDef; + gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef; + gs->gs_xmlSubstituteEntitiesDefaultValue = + xmlSubstituteEntitiesDefaultValueThrDef;
- return(old); -} + gs->gs_xmlGenericError = xmlGenericErrorThrDef; + gs->gs_xmlStructuredError = xmlStructuredErrorThrDef; + gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef; + gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef; + gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef; + gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
-#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED) -#undef htmlDefaultSAXHandler -xmlSAXHandlerV1 * -__htmlDefaultSAXHandler(void) { - if (IS_MAIN_THREAD) - return (&htmlDefaultSAXHandler); - else - return (&xmlGetGlobalState()->htmlDefaultSAXHandler); -} + gs->gs_xmlParserInputBufferCreateFilenameValue = + xmlParserInputBufferCreateFilenameValueThrDef; + gs->gs_xmlOutputBufferCreateFilenameValue = + xmlOutputBufferCreateFilenameValueThrDef; + memset(&gs->gs_xmlLastError, 0, sizeof(xmlError)); + + xmlMutexUnlock(&xmlThrDefMutex); + +#ifdef HAVE_POSIX_THREADS + pthread_setspecific(globalkey, gs); +#elif defined HAVE_WIN32_THREADS +#ifndef USE_TLS + TlsSetValue(globalkey, gs); +#endif +#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) + xmlRegisterGlobalStateDtor(gs); +#endif #endif
-#undef xmlLastError -xmlError * -__xmlLastError(void) { - if (IS_MAIN_THREAD) - return (&xmlLastError); - else - return (&xmlGetGlobalState()->xmlLastError); + gs->initialized = 1; }
-/* - * The following memory routines were apparently lost at some point, - * and were re-inserted at this point on June 10, 2004. Hope it's - * the right place for them :-) +#ifndef USE_TLS +/** + * xmlNewGlobalState: + * + * xmlNewGlobalState() allocates a global state. This structure is used to + * hold all data for use by a thread when supporting backwards compatibility + * of libxml2 to pre-thread-safe behaviour. + * + * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error */ -#if defined(LIBXML_THREAD_ALLOC_ENABLED) && defined(LIBXML_THREAD_ENABLED) -#undef xmlMalloc -xmlMallocFunc * -__xmlMalloc(void){ - if (IS_MAIN_THREAD) - return (&xmlMalloc); - else - return (&xmlGetGlobalState()->xmlMalloc); +static xmlGlobalStatePtr +xmlNewGlobalState(int allowFailure) +{ + xmlGlobalState *gs; + + gs = malloc(sizeof(xmlGlobalState)); + if (gs == NULL) { + if (allowFailure) + return(NULL); + + /* + * If an application didn't call xmlCheckThreadLocalStorage to make + * sure that global state could be allocated, it's too late to + * handle the error. + */ + fprintf(stderr, "libxml2: Failed to allocate globals for thread\n" + "libxml2: See xmlCheckThreadLocalStorage\n"); + abort(); + } + + memset(gs, 0, sizeof(xmlGlobalState)); + xmlInitGlobalState(gs); + return (gs); } +#endif
-#undef xmlMallocAtomic -xmlMallocFunc * -__xmlMallocAtomic(void){ - if (IS_MAIN_THREAD) - return (&xmlMallocAtomic); - else - return (&xmlGetGlobalState()->xmlMallocAtomic); -} +static xmlGlobalStatePtr +xmlGetThreadLocalStorage(int allowFailure) { + xmlGlobalState *gs; + + (void) allowFailure; + +#ifdef USE_TLS + gs = &globalState; + if (gs->initialized == 0) + xmlInitGlobalState(gs); +#elif defined(HAVE_POSIX_THREADS) + gs = (xmlGlobalState *) pthread_getspecific(globalkey); + if (gs == NULL) + gs = xmlNewGlobalState(allowFailure); +#elif defined(HAVE_WIN32_THREADS) + gs = (xmlGlobalState *) TlsGetValue(globalkey); + if (gs == NULL) + gs = xmlNewGlobalState(allowFailure); +#else + gs = NULL; +#endif
-#undef xmlRealloc -xmlReallocFunc * -__xmlRealloc(void){ - if (IS_MAIN_THREAD) - return (&xmlRealloc); - else - return (&xmlGetGlobalState()->xmlRealloc); + return(gs); }
-#undef xmlFree -xmlFreeFunc * -__xmlFree(void){ - if (IS_MAIN_THREAD) - return (&xmlFree); - else - return (&xmlGetGlobalState()->xmlFree); -} +/* Define thread-local storage accessors with macro magic */
-xmlStrdupFunc * -__xmlMemStrdup(void){ - if (IS_MAIN_THREAD) - return (&xmlMemStrdup); - else - return (&xmlGetGlobalState()->xmlMemStrdup); +#define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \ + type *__##name(void) { \ + if (IS_MAIN_THREAD) \ + return (&name); \ + else \ + return (&xmlGetThreadLocalStorage(0)->gs_##name); \ + } + +#define XML_OP XML_DEFINE_GLOBAL_WRAPPER +XML_GLOBALS_ALLOC +XML_GLOBALS_ERROR +XML_GLOBALS_HTML +XML_GLOBALS_IO +XML_GLOBALS_PARSER +XML_GLOBALS_TREE +#undef XML_OP + +/* For backward compatibility */ + +const char *const * +__xmlParserVersion(void) { + return &xmlParserVersion; }
-#endif +#endif /* LIBXML_THREAD_ENABLED */
-/* - * Everything starting from the line below is - * Automatically generated by build_glob.py. - * Do not modify the previous line. +/** + * xmlCheckThreadLocalStorage: + * + * Check whether thread-local storage could be allocated. + * + * In cross-platform code running in multithreaded environments, this + * function should be called once in each thread before calling other + * library functions to make sure that thread-local storage was + * allocated properly. + * + * Returns 0 on success or -1 if a memory allocation failed. A failed + * allocation signals a typically fatal and irrecoverable out-of-memory + * situation. Don't call any library functions in this case. + * + * This function never fails if the library is compiled with support + * for thread-local storage. + * + * This function never fails for the "main" thread which is the first + * thread calling xmlInitParser. + * + * Available since v2.12.0. */ +int +xmlCheckThreadLocalStorage(void) { +#if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS) + if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL)) + return(-1); +#endif + return(0); +}
+/** + * DllMain: + * @hinstDLL: handle to DLL instance + * @fdwReason: Reason code for entry + * @lpvReserved: generic pointer (depends upon reason code) + * + * Entry point for Windows library. It is being used to free thread-specific + * storage. + * + * Returns TRUE always + */ +#if defined(HAVE_WIN32_THREADS) && \ + (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) +#if defined(LIBXML_STATIC_FOR_DLL) +int +xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason, + ATTRIBUTE_UNUSED void *lpvReserved) +#else +/* declare to avoid "no previous prototype for 'DllMain'" warning */ +/* Note that we do NOT want to include this function declaration in + a public header because it's meant to be called by Windows itself, + not a program that uses this library. This also has to be exported. */ + +XMLPUBFUN BOOL WINAPI +DllMain (HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved); + +BOOL WINAPI +DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason, + ATTRIBUTE_UNUSED LPVOID lpvReserved) +#endif +{ + switch (fdwReason) { + case DLL_THREAD_DETACH: +#ifdef USE_TLS + xmlFreeGlobalState(&globalState); +#else + if (globalkey != TLS_OUT_OF_INDEXES) { + xmlGlobalState *globalval; + + globalval = (xmlGlobalState *) TlsGetValue(globalkey); + if (globalval) { + xmlFreeGlobalState(globalval); + TlsSetValue(globalkey, NULL); + } + } +#endif + break; + } + return TRUE; +} +#endif
-#undef oldXMLWDcompatibility -int * -__oldXMLWDcompatibility(void) { - if (IS_MAIN_THREAD) - return (&oldXMLWDcompatibility); +void +xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) { + xmlMutexLock(&xmlThrDefMutex); + xmlGenericErrorContextThrDef = ctx; + if (handler != NULL) + xmlGenericErrorThrDef = handler; else - return (&xmlGetGlobalState()->oldXMLWDcompatibility); + xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc; + xmlMutexUnlock(&xmlThrDefMutex); }
-#undef xmlBufferAllocScheme -xmlBufferAllocationScheme * -__xmlBufferAllocScheme(void) { - if (IS_MAIN_THREAD) - return (&xmlBufferAllocScheme); - else - return (&xmlGetGlobalState()->xmlBufferAllocScheme); +void +xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) { + xmlMutexLock(&xmlThrDefMutex); + xmlStructuredErrorContextThrDef = ctx; + xmlStructuredErrorThrDef = handler; + xmlMutexUnlock(&xmlThrDefMutex); } + xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) { xmlBufferAllocationScheme ret; xmlMutexLock(&xmlThrDefMutex); @@ -813,14 +1032,6 @@ xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v return ret; }
-#undef xmlDefaultBufferSize -int * -__xmlDefaultBufferSize(void) { - if (IS_MAIN_THREAD) - return (&xmlDefaultBufferSize); - else - return (&xmlGetGlobalState()->xmlDefaultBufferSize); -} int xmlThrDefDefaultBufferSize(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -830,34 +1041,6 @@ int xmlThrDefDefaultBufferSize(int v) { return ret; }
-#ifdef LIBXML_SAX1_ENABLED -#undef xmlDefaultSAXHandler -xmlSAXHandlerV1 * -__xmlDefaultSAXHandler(void) { - if (IS_MAIN_THREAD) - return (&xmlDefaultSAXHandler); - else - return (&xmlGetGlobalState()->xmlDefaultSAXHandler); -} -#endif /* LIBXML_SAX1_ENABLED */ - -#undef xmlDefaultSAXLocator -xmlSAXLocator * -__xmlDefaultSAXLocator(void) { - if (IS_MAIN_THREAD) - return (&xmlDefaultSAXLocator); - else - return (&xmlGetGlobalState()->xmlDefaultSAXLocator); -} - -#undef xmlDoValidityCheckingDefaultValue -int * -__xmlDoValidityCheckingDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlDoValidityCheckingDefaultValue); - else - return (&xmlGetGlobalState()->xmlDoValidityCheckingDefaultValue); -} int xmlThrDefDoValidityCheckingDefaultValue(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -867,50 +1050,6 @@ int xmlThrDefDoValidityCheckingDefaultValue(int v) { return ret; }
-#undef xmlGenericError -xmlGenericErrorFunc * -__xmlGenericError(void) { - if (IS_MAIN_THREAD) - return (&xmlGenericError); - else - return (&xmlGetGlobalState()->xmlGenericError); -} - -#undef xmlStructuredError -xmlStructuredErrorFunc * -__xmlStructuredError(void) { - if (IS_MAIN_THREAD) - return (&xmlStructuredError); - else - return (&xmlGetGlobalState()->xmlStructuredError); -} - -#undef xmlGenericErrorContext -void * * -__xmlGenericErrorContext(void) { - if (IS_MAIN_THREAD) - return (&xmlGenericErrorContext); - else - return (&xmlGetGlobalState()->xmlGenericErrorContext); -} - -#undef xmlStructuredErrorContext -void * * -__xmlStructuredErrorContext(void) { - if (IS_MAIN_THREAD) - return (&xmlStructuredErrorContext); - else - return (&xmlGetGlobalState()->xmlStructuredErrorContext); -} - -#undef xmlGetWarningsDefaultValue -int * -__xmlGetWarningsDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlGetWarningsDefaultValue); - else - return (&xmlGetGlobalState()->xmlGetWarningsDefaultValue); -} int xmlThrDefGetWarningsDefaultValue(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -920,14 +1059,7 @@ int xmlThrDefGetWarningsDefaultValue(int v) { return ret; }
-#undef xmlIndentTreeOutput -int * -__xmlIndentTreeOutput(void) { - if (IS_MAIN_THREAD) - return (&xmlIndentTreeOutput); - else - return (&xmlGetGlobalState()->xmlIndentTreeOutput); -} +#ifdef LIBXML_OUTPUT_ENABLED int xmlThrDefIndentTreeOutput(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -937,14 +1069,6 @@ int xmlThrDefIndentTreeOutput(int v) { return ret; }
-#undef xmlTreeIndentString -const char * * -__xmlTreeIndentString(void) { - if (IS_MAIN_THREAD) - return (&xmlTreeIndentString); - else - return (&xmlGetGlobalState()->xmlTreeIndentString); -} const char * xmlThrDefTreeIndentString(const char * v) { const char * ret; xmlMutexLock(&xmlThrDefMutex); @@ -954,14 +1078,16 @@ const char * xmlThrDefTreeIndentString(const char * v) { return ret; }
-#undef xmlKeepBlanksDefaultValue -int * -__xmlKeepBlanksDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlKeepBlanksDefaultValue); - else - return (&xmlGetGlobalState()->xmlKeepBlanksDefaultValue); +int xmlThrDefSaveNoEmptyTags(int v) { + int ret; + xmlMutexLock(&xmlThrDefMutex); + ret = xmlSaveNoEmptyTagsThrDef; + xmlSaveNoEmptyTagsThrDef = v; + xmlMutexUnlock(&xmlThrDefMutex); + return ret; } +#endif + int xmlThrDefKeepBlanksDefaultValue(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -971,14 +1097,6 @@ int xmlThrDefKeepBlanksDefaultValue(int v) { return ret; }
-#undef xmlLineNumbersDefaultValue -int * -__xmlLineNumbersDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlLineNumbersDefaultValue); - else - return (&xmlGetGlobalState()->xmlLineNumbersDefaultValue); -} int xmlThrDefLineNumbersDefaultValue(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -988,14 +1106,6 @@ int xmlThrDefLineNumbersDefaultValue(int v) { return ret; }
-#undef xmlLoadExtDtdDefaultValue -int * -__xmlLoadExtDtdDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlLoadExtDtdDefaultValue); - else - return (&xmlGetGlobalState()->xmlLoadExtDtdDefaultValue); -} int xmlThrDefLoadExtDtdDefaultValue(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -1005,14 +1115,6 @@ int xmlThrDefLoadExtDtdDefaultValue(int v) { return ret; }
-#undef xmlParserDebugEntities -int * -__xmlParserDebugEntities(void) { - if (IS_MAIN_THREAD) - return (&xmlParserDebugEntities); - else - return (&xmlGetGlobalState()->xmlParserDebugEntities); -} int xmlThrDefParserDebugEntities(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -1022,23 +1124,6 @@ int xmlThrDefParserDebugEntities(int v) { return ret; }
-#undef xmlParserVersion -const char * * -__xmlParserVersion(void) { - if (IS_MAIN_THREAD) - return (&xmlParserVersion); - else - return (&xmlGetGlobalState()->xmlParserVersion); -} - -#undef xmlPedanticParserDefaultValue -int * -__xmlPedanticParserDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlPedanticParserDefaultValue); - else - return (&xmlGetGlobalState()->xmlPedanticParserDefaultValue); -} int xmlThrDefPedanticParserDefaultValue(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -1048,31 +1133,6 @@ int xmlThrDefPedanticParserDefaultValue(int v) { return ret; }
-#undef xmlSaveNoEmptyTags -int * -__xmlSaveNoEmptyTags(void) { - if (IS_MAIN_THREAD) - return (&xmlSaveNoEmptyTags); - else - return (&xmlGetGlobalState()->xmlSaveNoEmptyTags); -} -int xmlThrDefSaveNoEmptyTags(int v) { - int ret; - xmlMutexLock(&xmlThrDefMutex); - ret = xmlSaveNoEmptyTagsThrDef; - xmlSaveNoEmptyTagsThrDef = v; - xmlMutexUnlock(&xmlThrDefMutex); - return ret; -} - -#undef xmlSubstituteEntitiesDefaultValue -int * -__xmlSubstituteEntitiesDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlSubstituteEntitiesDefaultValue); - else - return (&xmlGetGlobalState()->xmlSubstituteEntitiesDefaultValue); -} int xmlThrDefSubstituteEntitiesDefaultValue(int v) { int ret; xmlMutexLock(&xmlThrDefMutex); @@ -1082,38 +1142,67 @@ int xmlThrDefSubstituteEntitiesDefaultValue(int v) { return ret; }
-#undef xmlRegisterNodeDefaultValue -xmlRegisterNodeFunc * -__xmlRegisterNodeDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlRegisterNodeDefaultValue); - else - return (&xmlGetGlobalState()->xmlRegisterNodeDefaultValue); +xmlRegisterNodeFunc +xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func) +{ + xmlRegisterNodeFunc old; + + xmlMutexLock(&xmlThrDefMutex); + old = xmlRegisterNodeDefaultValueThrDef; + + __xmlRegisterCallbacks = 1; + xmlRegisterNodeDefaultValueThrDef = func; + xmlMutexUnlock(&xmlThrDefMutex); + + return(old); }
-#undef xmlDeregisterNodeDefaultValue -xmlDeregisterNodeFunc * -__xmlDeregisterNodeDefaultValue(void) { - if (IS_MAIN_THREAD) - return (&xmlDeregisterNodeDefaultValue); - else - return (&xmlGetGlobalState()->xmlDeregisterNodeDefaultValue); +xmlDeregisterNodeFunc +xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func) +{ + xmlDeregisterNodeFunc old; + + xmlMutexLock(&xmlThrDefMutex); + old = xmlDeregisterNodeDefaultValueThrDef; + + __xmlRegisterCallbacks = 1; + xmlDeregisterNodeDefaultValueThrDef = func; + xmlMutexUnlock(&xmlThrDefMutex); + + return(old); }
-#undef xmlParserInputBufferCreateFilenameValue -xmlParserInputBufferCreateFilenameFunc * -__xmlParserInputBufferCreateFilenameValue(void) { - if (IS_MAIN_THREAD) - return (&xmlParserInputBufferCreateFilenameValue); - else - return (&xmlGetGlobalState()->xmlParserInputBufferCreateFilenameValue); +xmlParserInputBufferCreateFilenameFunc +xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func) +{ + xmlParserInputBufferCreateFilenameFunc old; + + xmlMutexLock(&xmlThrDefMutex); + old = xmlParserInputBufferCreateFilenameValueThrDef; + if (old == NULL) { + old = __xmlParserInputBufferCreateFilename; + } + + xmlParserInputBufferCreateFilenameValueThrDef = func; + xmlMutexUnlock(&xmlThrDefMutex); + + return(old); }
-#undef xmlOutputBufferCreateFilenameValue -xmlOutputBufferCreateFilenameFunc * -__xmlOutputBufferCreateFilenameValue(void) { - if (IS_MAIN_THREAD) - return (&xmlOutputBufferCreateFilenameValue); - else - return (&xmlGetGlobalState()->xmlOutputBufferCreateFilenameValue); +xmlOutputBufferCreateFilenameFunc +xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func) +{ + xmlOutputBufferCreateFilenameFunc old; + + xmlMutexLock(&xmlThrDefMutex); + old = xmlOutputBufferCreateFilenameValueThrDef; +#ifdef LIBXML_OUTPUT_ENABLED + if (old == NULL) { + old = __xmlOutputBufferCreateFilename; + } +#endif + xmlOutputBufferCreateFilenameValueThrDef = func; + xmlMutexUnlock(&xmlThrDefMutex); + + return(old); } diff --git a/libs/xml2/hash.c b/libs/xml2/hash.c index cbcc42935d2..183a6f93895 100644 --- a/libs/xml2/hash.c +++ b/libs/xml2/hash.c @@ -1,206 +1,197 @@ /* - * hash.c: chained hash tables + * hash.c: hash tables * - * Reference: Your favorite introductory book on algorithms + * Hash table with open addressing, linear probing and + * Robin Hood reordering. * - * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - * Author: breese@users.sourceforge.net + * See Copyright for the status of this software. */
#define IN_LIBXML #include "libxml.h"
#include <string.h> -#include <stdlib.h> -#include <time.h> - -/* - * Following http://www.ocert.org/advisories/ocert-2011-003.html - * it seems that having hash randomization might be a good idea - * when using XML with untrusted data - */ -#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) -#define HASH_RANDOMIZATION -#endif +#include <limits.h>
#include <libxml/parser.h> #include <libxml/hash.h> +#include <libxml/dict.h> #include <libxml/xmlmemory.h> -#include <libxml/xmlerror.h> -#include <libxml/globals.h> +#include <libxml/xmlstring.h>
#include "private/dict.h"
-#define MAX_HASH_LEN 8 +#ifndef SIZE_MAX + #define SIZE_MAX ((size_t) -1) +#endif
-/* #define DEBUG_GROW */ +#define MAX_FILL_NUM 7 +#define MAX_FILL_DENOM 8 +#define MIN_HASH_SIZE 8 +#define MAX_HASH_SIZE (1u << 31)
/* * A single entry in the hash table */ -typedef struct _xmlHashEntry xmlHashEntry; -typedef xmlHashEntry *xmlHashEntryPtr; -struct _xmlHashEntry { - struct _xmlHashEntry *next; - xmlChar *name; - xmlChar *name2; - xmlChar *name3; +typedef struct { + unsigned hashValue; /* 0 means unoccupied, occupied entries have the + * MAX_HASH_SIZE bit set to 1 */ + xmlChar *key; + xmlChar *key2; /* TODO: Don't allocate possibly empty keys */ + xmlChar *key3; void *payload; - int valid; -}; +} xmlHashEntry;
/* * The entire hash table */ struct _xmlHashTable { - struct _xmlHashEntry *table; - int size; - int nbElems; + xmlHashEntry *table; + unsigned size; /* power of two */ + unsigned nbElems; xmlDictPtr dict; -#ifdef HASH_RANDOMIZATION - int random_seed; -#endif + unsigned randomSeed; };
-/* - * xmlHashComputeKey: - * Calculate the hash key - */ -#ifdef __clang__ -ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") -ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") -#endif -static unsigned long -xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3) { - unsigned long value = 0L; - unsigned long ch; - -#ifdef HASH_RANDOMIZATION - value = table->random_seed; -#endif - if (name != NULL) { - value += 30 * (*name); - while ((ch = *name++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } +static int +xmlHashGrow(xmlHashTablePtr hash, unsigned size); + +ATTRIBUTE_NO_SANITIZE_INTEGER +static unsigned +xmlHashValue(unsigned seed, const xmlChar *key, const xmlChar *key2, + const xmlChar *key3, size_t *lengths) { + unsigned h1, h2; + size_t i; + + HASH_INIT(h1, h2, seed); + + for (i = 0; key[i] != 0; i++) { + HASH_UPDATE(h1, h2, key[i]); } - value = value ^ ((value << 5) + (value >> 3)); - if (name2 != NULL) { - while ((ch = *name2++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } + if (lengths) + lengths[0] = i; + + HASH_UPDATE(h1, h2, 0); + + if (key2 != NULL) { + for (i = 0; key2[i] != 0; i++) { + HASH_UPDATE(h1, h2, key2[i]); + } + if (lengths) + lengths[1] = i; } - value = value ^ ((value << 5) + (value >> 3)); - if (name3 != NULL) { - while ((ch = *name3++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } + + HASH_UPDATE(h1, h2, 0); + + if (key3 != NULL) { + for (i = 0; key3[i] != 0; i++) { + HASH_UPDATE(h1, h2, key3[i]); + } + if (lengths) + lengths[2] = i; } - return (value % table->size); + + HASH_FINISH(h1, h2); + + return(h2); }
-#ifdef __clang__ -ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") -ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") -#endif -static unsigned long -xmlHashComputeQKey(xmlHashTablePtr table, - const xmlChar *prefix, const xmlChar *name, - const xmlChar *prefix2, const xmlChar *name2, - const xmlChar *prefix3, const xmlChar *name3) { - unsigned long value = 0L; - unsigned long ch; - -#ifdef HASH_RANDOMIZATION - value = table->random_seed; -#endif - if (prefix != NULL) - value += 30 * (*prefix); - else - value += 30 * (*name); +ATTRIBUTE_NO_SANITIZE_INTEGER +static unsigned +xmlHashQNameValue(unsigned seed, + const xmlChar *prefix, const xmlChar *name, + const xmlChar *prefix2, const xmlChar *name2, + const xmlChar *prefix3, const xmlChar *name3) { + unsigned h1, h2, ch; + + HASH_INIT(h1, h2, seed);
if (prefix != NULL) { - while ((ch = *prefix++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } - value = value ^ ((value << 5) + (value >> 3) + ':'); + while ((ch = *prefix++) != 0) { + HASH_UPDATE(h1, h2, ch); + } + HASH_UPDATE(h1, h2, ':'); } if (name != NULL) { - while ((ch = *name++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } + while ((ch = *name++) != 0) { + HASH_UPDATE(h1, h2, ch); + } } - value = value ^ ((value << 5) + (value >> 3)); + HASH_UPDATE(h1, h2, 0); if (prefix2 != NULL) { - while ((ch = *prefix2++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } - value = value ^ ((value << 5) + (value >> 3) + ':'); + while ((ch = *prefix2++) != 0) { + HASH_UPDATE(h1, h2, ch); + } + HASH_UPDATE(h1, h2, ':'); } if (name2 != NULL) { - while ((ch = *name2++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } + while ((ch = *name2++) != 0) { + HASH_UPDATE(h1, h2, ch); + } } - value = value ^ ((value << 5) + (value >> 3)); + HASH_UPDATE(h1, h2, 0); if (prefix3 != NULL) { - while ((ch = *prefix3++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } - value = value ^ ((value << 5) + (value >> 3) + ':'); + while ((ch = *prefix3++) != 0) { + HASH_UPDATE(h1, h2, ch); + } + HASH_UPDATE(h1, h2, ':'); } if (name3 != NULL) { - while ((ch = *name3++) != 0) { - value = value ^ ((value << 5) + (value >> 3) + ch); - } + while ((ch = *name3++) != 0) { + HASH_UPDATE(h1, h2, ch); + } } - return (value % table->size); + + HASH_FINISH(h1, h2); + + return(h2); }
/** * xmlHashCreate: - * @size: the size of the hash table + * @size: initial size of the hash table * - * Create a new xmlHashTablePtr. + * Create a new hash table. Set size to zero if the number of entries + * can't be estimated. * - * Returns the newly created object, or NULL if an error occurred. + * Returns the newly created object, or NULL if a memory allocation failed. */ xmlHashTablePtr xmlHashCreate(int size) { - xmlHashTablePtr table; + xmlHashTablePtr hash;
xmlInitParser();
- if (size <= 0) - size = 256; - - table = xmlMalloc(sizeof(xmlHashTable)); - if (table) { - table->dict = NULL; - table->size = size; - table->nbElems = 0; - table->table = xmlMalloc(size * sizeof(xmlHashEntry)); - if (table->table) { - memset(table->table, 0, size * sizeof(xmlHashEntry)); -#ifdef HASH_RANDOMIZATION - table->random_seed = __xmlRandom(); + hash = xmlMalloc(sizeof(*hash)); + if (hash == NULL) + return(NULL); + hash->dict = NULL; + hash->size = 0; + hash->table = NULL; + hash->nbElems = 0; + hash->randomSeed = xmlRandom(); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + hash->randomSeed = 0; #endif - return(table); + + /* + * Unless a larger size is passed, the backing table is created + * lazily with MIN_HASH_SIZE capacity. In practice, there are many + * hash tables which are never filled. + */ + if (size > MIN_HASH_SIZE) { + unsigned newSize = MIN_HASH_SIZE * 2; + + while ((newSize < (unsigned) size) && (newSize < MAX_HASH_SIZE)) + newSize *= 2; + + if (xmlHashGrow(hash, newSize) != 0) { + xmlFree(hash); + return(NULL); } - xmlFree(table); } - return(NULL); + + return(hash); }
/** @@ -208,984 +199,1016 @@ xmlHashCreate(int size) { * @size: the size of the hash table * @dict: a dictionary to use for the hash * - * Create a new xmlHashTablePtr which will use @dict as the internal dictionary + * Create a new hash table backed by a dictionary. This can reduce + * resource usage considerably if most keys passed to API functions + * originate from this dictionary. * - * Returns the newly created object, or NULL if an error occurred. + * Returns the newly created object, or NULL if a memory allocation failed. */ xmlHashTablePtr xmlHashCreateDict(int size, xmlDictPtr dict) { - xmlHashTablePtr table; + xmlHashTablePtr hash;
- table = xmlHashCreate(size); - if (table != NULL) { - table->dict = dict; - xmlDictReference(dict); + hash = xmlHashCreate(size); + if (hash != NULL) { + hash->dict = dict; + xmlDictReference(dict); } - return(table); + return(hash); +} + +/** + * xmlHashFree: + * @hash: hash table + * @dealloc: deallocator function or NULL + * + * Free the hash and its contents. The payload is deallocated with + * @dealloc if provided. + */ +void +xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc) { + if (hash == NULL) + return; + + if (hash->table) { + const xmlHashEntry *end = &hash->table[hash->size]; + const xmlHashEntry *entry; + + for (entry = hash->table; entry < end; entry++) { + if (entry->hashValue == 0) + continue; + if ((dealloc != NULL) && (entry->payload != NULL)) + dealloc(entry->payload, entry->key); + if (hash->dict == NULL) { + if (entry->key) + xmlFree(entry->key); + if (entry->key2) + xmlFree(entry->key2); + if (entry->key3) + xmlFree(entry->key3); + } + } + + xmlFree(hash->table); + } + + if (hash->dict) + xmlDictFree(hash->dict); + + xmlFree(hash); +} + +/** + * xmlFastStrEqual: + * @s1: string + * @s2: string + * + * Compare two strings for equality, allowing NULL values. + */ +static int +xmlFastStrEqual(const xmlChar *s1, const xmlChar *s2) { + if (s1 == NULL) + return(s2 == NULL); + else + return((s2 != NULL) && + (strcmp((const char *) s1, (const char *) s2) == 0)); +} + +/** + * xmlHashFindEntry: + * @hash: hash table, non-NULL, size > 0 + * @key: first string key, non-NULL + * @key2: second string key + * @key3: third string key + * @hashValue: valid hash value of keys + * @pfound: result of search + * + * Try to find a matching hash table entry. If an entry was found, set + * @found to 1 and return the entry. Otherwise, set @found to 0 and return + * the location where a new entry should be inserted. + */ +ATTRIBUTE_NO_SANITIZE_INTEGER +static xmlHashEntry * +xmlHashFindEntry(const xmlHashTable *hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + unsigned hashValue, int *pfound) { + xmlHashEntry *entry; + unsigned mask, pos, displ; + int found = 0; + + mask = hash->size - 1; + pos = hashValue & mask; + entry = &hash->table[pos]; + + if (entry->hashValue != 0) { + /* + * Robin hood hashing: abort if the displacement of the entry + * is smaller than the displacement of the key we look for. + * This also stops at the correct position when inserting. + */ + displ = 0; + hashValue |= MAX_HASH_SIZE; + + do { + if (entry->hashValue == hashValue) { + if (hash->dict) { + if ((entry->key == key) && + (entry->key2 == key2) && + (entry->key3 == key3)) { + found = 1; + break; + } + } + if ((strcmp((const char *) entry->key, + (const char *) key) == 0) && + (xmlFastStrEqual(entry->key2, key2)) && + (xmlFastStrEqual(entry->key3, key3))) { + found = 1; + break; + } + } + + displ++; + pos++; + entry++; + if ((pos & mask) == 0) + entry = hash->table; + } while ((entry->hashValue != 0) && + (((pos - entry->hashValue) & mask) >= displ)); + } + + *pfound = found; + return(entry); }
/** * xmlHashGrow: - * @table: the hash table - * @size: the new size of the hash table + * @hash: hash table + * @size: new size of the hash table * - * resize the hash table + * Resize the hash table. * - * Returns 0 in case of success, -1 in case of failure + * Returns 0 in case of success, -1 if a memory allocation failed. */ static int -xmlHashGrow(xmlHashTablePtr table, int size) { - unsigned long key; - int oldsize, i; - xmlHashEntryPtr iter, next; - struct _xmlHashEntry *oldtable; -#ifdef DEBUG_GROW - unsigned long nbElem = 0; -#endif +xmlHashGrow(xmlHashTablePtr hash, unsigned size) { + const xmlHashEntry *oldentry, *oldend, *end; + xmlHashEntry *table; + unsigned oldsize, i;
+ /* Add 0 to avoid spurious -Wtype-limits warning on 64-bit GCC */ + if ((size_t) size + 0 > SIZE_MAX / sizeof(table[0])) + return(-1); + table = xmlMalloc(size * sizeof(table[0])); if (table == NULL) - return(-1); - if (size < 8) return(-1); - if (size > 8 * 2048) - return(-1); + memset(table, 0, size * sizeof(table[0]));
- oldsize = table->size; - oldtable = table->table; - if (oldtable == NULL) - return(-1); + oldsize = hash->size; + if (oldsize == 0) + goto done;
- table->table = xmlMalloc(size * sizeof(xmlHashEntry)); - if (table->table == NULL) { - table->table = oldtable; - return(-1); - } - memset(table->table, 0, size * sizeof(xmlHashEntry)); - table->size = size; - - /* If the two loops are merged, there would be situations where - a new entry needs to allocated and data copied into it from - the main table. So instead, we run through the array twice, first - copying all the elements in the main array (where we can't get - conflicts) and then the rest, so we only free (and don't allocate) - */ - for (i = 0; i < oldsize; i++) { - if (oldtable[i].valid == 0) - continue; - key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2, - oldtable[i].name3); - memcpy(&(table->table[key]), &(oldtable[i]), sizeof(xmlHashEntry)); - table->table[key].next = NULL; + oldend = &hash->table[oldsize]; + end = &table[size]; + + /* + * Robin Hood sorting order is maintained if we + * + * - compute hash indices with modulo + * - resize by an integer factor + * - start to copy from the beginning of a probe sequence + */ + oldentry = hash->table; + while (oldentry->hashValue != 0) { + if (++oldentry >= oldend) + oldentry = hash->table; }
for (i = 0; i < oldsize; i++) { - iter = oldtable[i].next; - while (iter) { - next = iter->next; - - /* - * put back the entry in the new table - */ - - key = xmlHashComputeKey(table, iter->name, iter->name2, - iter->name3); - if (table->table[key].valid == 0) { - memcpy(&(table->table[key]), iter, sizeof(xmlHashEntry)); - table->table[key].next = NULL; - xmlFree(iter); - } else { - iter->next = table->table[key].next; - table->table[key].next = iter; - } - -#ifdef DEBUG_GROW - nbElem++; -#endif + if (oldentry->hashValue != 0) { + xmlHashEntry *entry = &table[oldentry->hashValue & (size - 1)];
- iter = next; - } + while (entry->hashValue != 0) { + if (++entry >= end) + entry = table; + } + *entry = *oldentry; + } + + if (++oldentry >= oldend) + oldentry = hash->table; }
- xmlFree(oldtable); + xmlFree(hash->table);
-#ifdef DEBUG_GROW - xmlGenericError(xmlGenericErrorContext, - "xmlHashGrow : from %d to %d, %d elems\n", oldsize, size, nbElem); -#endif +done: + hash->table = table; + hash->size = size;
return(0); }
/** - * xmlHashFree: - * @table: the hash table - * @f: the deallocator function for items in the hash + * xmlHashUpdateInternal: + * @hash: hash table + * @key: first string key + * @key2: second string key + * @key3: third string key + * @payload: pointer to the payload + * @dealloc: deallocator function for replaced item or NULL + * @update: whether existing entries should be updated * - * Free the hash @table and its contents. The userdata is - * deallocated with @f if provided. + * Internal function to add or update hash entries. */ -void -xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f) { - int i; - xmlHashEntryPtr iter; - xmlHashEntryPtr next; - int inside_table = 0; - int nbElems; +ATTRIBUTE_NO_SANITIZE_INTEGER +static int +xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + void *payload, xmlHashDeallocator dealloc, int update) { + xmlChar *copy, *copy2, *copy3; + xmlHashEntry *entry = NULL; + size_t lengths[3]; + unsigned hashValue; + int found = 0; + + if ((hash == NULL) || (key == NULL)) + return(-1);
- if (table == NULL) - return; - if (table->table) { - nbElems = table->nbElems; - for(i = 0; (i < table->size) && (nbElems > 0); i++) { - iter = &(table->table[i]); - if (iter->valid == 0) - continue; - inside_table = 1; - while (iter) { - next = iter->next; - if ((f != NULL) && (iter->payload != NULL)) - f(iter->payload, iter->name); - if (table->dict == NULL) { - if (iter->name) - xmlFree(iter->name); - if (iter->name2) - xmlFree(iter->name2); - if (iter->name3) - xmlFree(iter->name3); - } - iter->payload = NULL; - if (!inside_table) - xmlFree(iter); - nbElems--; - inside_table = 0; - iter = next; - } - } - xmlFree(table->table); + /* + * Check for an existing entry + */ + hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, lengths); + if (hash->size > 0) + entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found); + if (found) { + if (update) { + if (dealloc) + dealloc(entry->payload, entry->key); + entry->payload = payload; + return(0); + } else { + /* + * xmlHashAddEntry found an existing entry. + * + * TODO: We should return a different error code here to + * distinguish from malloc failures. + */ + return(-1); + } + } + + /* + * Grow the hash table if needed + */ + if (hash->nbElems + 1 > hash->size / MAX_FILL_DENOM * MAX_FILL_NUM) { + unsigned newSize, mask, displ, pos; + + if (hash->size == 0) { + newSize = MIN_HASH_SIZE; + } else { + /* This guarantees that nbElems < INT_MAX */ + if (hash->size >= MAX_HASH_SIZE) + return(-1); + newSize = hash->size * 2; + } + if (xmlHashGrow(hash, newSize) != 0) + return(-1); + + /* + * Find new entry + */ + mask = hash->size - 1; + displ = 0; + pos = hashValue & mask; + entry = &hash->table[pos]; + + if (entry->hashValue != 0) { + do { + displ++; + pos++; + entry++; + if ((pos & mask) == 0) + entry = hash->table; + } while ((entry->hashValue != 0) && + ((pos - entry->hashValue) & mask) >= displ); + } } - if (table->dict) - xmlDictFree(table->dict); - xmlFree(table); + + /* + * Copy keys + */ + if (hash->dict != NULL) { + if (xmlDictOwns(hash->dict, key)) { + copy = (xmlChar *) key; + } else { + copy = (xmlChar *) xmlDictLookup(hash->dict, key, -1); + if (copy == NULL) + return(-1); + } + + if ((key2 == NULL) || (xmlDictOwns(hash->dict, key2))) { + copy2 = (xmlChar *) key2; + } else { + copy2 = (xmlChar *) xmlDictLookup(hash->dict, key2, -1); + if (copy2 == NULL) + return(-1); + } + if ((key3 == NULL) || (xmlDictOwns(hash->dict, key3))) { + copy3 = (xmlChar *) key3; + } else { + copy3 = (xmlChar *) xmlDictLookup(hash->dict, key3, -1); + if (copy3 == NULL) + return(-1); + } + } else { + copy = xmlMalloc(lengths[0] + 1); + if (copy == NULL) + return(-1); + memcpy(copy, key, lengths[0] + 1); + + if (key2 != NULL) { + copy2 = xmlMalloc(lengths[1] + 1); + if (copy2 == NULL) { + xmlFree(copy); + return(-1); + } + memcpy(copy2, key2, lengths[1] + 1); + } else { + copy2 = NULL; + } + + if (key3 != NULL) { + copy3 = xmlMalloc(lengths[2] + 1); + if (copy3 == NULL) { + xmlFree(copy); + xmlFree(copy2); + return(-1); + } + memcpy(copy3, key3, lengths[2] + 1); + } else { + copy3 = NULL; + } + } + + /* + * Shift the remainder of the probe sequence to the right + */ + if (entry->hashValue != 0) { + const xmlHashEntry *end = &hash->table[hash->size]; + const xmlHashEntry *cur = entry; + + do { + cur++; + if (cur >= end) + cur = hash->table; + } while (cur->hashValue != 0); + + if (cur < entry) { + /* + * If we traversed the end of the buffer, handle the part + * at the start of the buffer. + */ + memmove(&hash->table[1], hash->table, + (char *) cur - (char *) hash->table); + cur = end - 1; + hash->table[0] = *cur; + } + + memmove(&entry[1], entry, (char *) cur - (char *) entry); + } + + /* + * Populate entry + */ + entry->key = copy; + entry->key2 = copy2; + entry->key3 = copy3; + entry->payload = payload; + /* OR with MAX_HASH_SIZE to make sure that the value is non-zero */ + entry->hashValue = hashValue | MAX_HASH_SIZE; + + hash->nbElems++; + + return(0); }
/** * xmlHashDefaultDeallocator: - * @entry: the hash table entry - * @name: the entry's name + * @entry: hash table entry + * @key: the entry's string key * * Free a hash table entry with xmlFree. */ void -xmlHashDefaultDeallocator(void *entry, const xmlChar *name ATTRIBUTE_UNUSED) { +xmlHashDefaultDeallocator(void *entry, const xmlChar *key ATTRIBUTE_UNUSED) { xmlFree(entry); }
/** * xmlHashAddEntry: - * @table: the hash table - * @name: the name of the userdata - * @userdata: a pointer to the userdata + * @hash: hash table + * @key: string key + * @payload: pointer to the payload * - * Add the @userdata to the hash @table. This can later be retrieved - * by using the @name. Duplicate names generate errors. + * Add a hash table entry. If an entry with this key already exists, + * payload will not be updated and -1 is returned. This return value + * can't be distinguished from out-of-memory errors, so this function + * should be used with care. * - * Returns 0 the addition succeeded and -1 in case of error. + * Returns 0 on success and -1 in case of error. */ int -xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata) { - return(xmlHashAddEntry3(table, name, NULL, NULL, userdata)); +xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload) { + return(xmlHashUpdateInternal(hash, key, NULL, NULL, payload, NULL, 0)); }
/** * xmlHashAddEntry2: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata - * @userdata: a pointer to the userdata + * @hash: hash table + * @key: first string key + * @key2: second string key + * @payload: pointer to the payload * - * Add the @userdata to the hash @table. This can later be retrieved - * by using the (@name, @name2) tuple. Duplicate tuples generate errors. + * Add a hash table entry with two strings as key. * - * Returns 0 the addition succeeded and -1 in case of error. + * See xmlHashAddEntry. + * + * Returns 0 on success and -1 in case of error. */ int -xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, void *userdata) { - return(xmlHashAddEntry3(table, name, name2, NULL, userdata)); +xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, void *payload) { + return(xmlHashUpdateInternal(hash, key, key2, NULL, payload, NULL, 0)); }
/** - * xmlHashUpdateEntry: - * @table: the hash table - * @name: the name of the userdata - * @userdata: a pointer to the userdata - * @f: the deallocator function for replaced item (if any) + * xmlHashAddEntry3: + * @hash: hash table + * @key: first string key + * @key2: second string key + * @key3: third string key + * @payload: pointer to the payload * - * Add the @userdata to the hash @table. This can later be retrieved - * by using the @name. Existing entry for this @name will be removed - * and freed with @f if found. + * Add a hash table entry with three strings as key. * - * Returns 0 the addition succeeded and -1 in case of error. + * See xmlHashAddEntry. + * + * Returns 0 on success and -1 in case of error. */ int -xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name, - void *userdata, xmlHashDeallocator f) { - return(xmlHashUpdateEntry3(table, name, NULL, NULL, userdata, f)); +xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + void *payload) { + return(xmlHashUpdateInternal(hash, key, key2, key3, payload, NULL, 0)); }
/** - * xmlHashUpdateEntry2: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata - * @userdata: a pointer to the userdata - * @f: the deallocator function for replaced item (if any) + * xmlHashUpdateEntry: + * @hash: hash table + * @key: string key + * @payload: pointer to the payload + * @dealloc: deallocator function for replaced item or NULL * - * Add the @userdata to the hash @table. This can later be retrieved - * by using the (@name, @name2) tuple. Existing entry for this tuple will - * be removed and freed with @f if found. + * Add a hash table entry. If an entry with this key already exists, + * the old payload will be freed and updated with the new value. * - * Returns 0 the addition succeeded and -1 in case of error. + * Returns 0 in case of success, -1 if a memory allocation failed. */ int -xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, void *userdata, - xmlHashDeallocator f) { - return(xmlHashUpdateEntry3(table, name, name2, NULL, userdata, f)); +xmlHashUpdateEntry(xmlHashTablePtr hash, const xmlChar *key, + void *payload, xmlHashDeallocator dealloc) { + return(xmlHashUpdateInternal(hash, key, NULL, NULL, payload, + dealloc, 1)); }
/** - * xmlHashLookup: - * @table: the hash table - * @name: the name of the userdata + * xmlHashUpdateEntry2: + * @hash: hash table + * @key: first string key + * @key2: second string key + * @payload: pointer to the payload + * @dealloc: deallocator function for replaced item or NULL + * + * Add a hash table entry with two strings as key. * - * Find the userdata specified by the @name. + * See xmlHashUpdateEntry. * - * Returns the pointer to the userdata + * Returns 0 on success and -1 in case of error. */ -void * -xmlHashLookup(xmlHashTablePtr table, const xmlChar *name) { - return(xmlHashLookup3(table, name, NULL, NULL)); +int +xmlHashUpdateEntry2(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, void *payload, + xmlHashDeallocator dealloc) { + return(xmlHashUpdateInternal(hash, key, key2, NULL, payload, + dealloc, 1)); }
/** - * xmlHashLookup2: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata + * xmlHashUpdateEntry3: + * @hash: hash table + * @key: first string key + * @key2: second string key + * @key3: third string key + * @payload: pointer to the payload + * @dealloc: deallocator function for replaced item or NULL + * + * Add a hash table entry with three strings as key. * - * Find the userdata specified by the (@name, @name2) tuple. + * See xmlHashUpdateEntry. * - * Returns the pointer to the userdata + * Returns 0 on success and -1 in case of error. */ -void * -xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2) { - return(xmlHashLookup3(table, name, name2, NULL)); +int +xmlHashUpdateEntry3(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + void *payload, xmlHashDeallocator dealloc) { + return(xmlHashUpdateInternal(hash, key, key2, key3, payload, + dealloc, 1)); }
/** - * xmlHashQLookup: - * @table: the hash table - * @prefix: the prefix of the userdata - * @name: the name of the userdata + * xmlHashLookup: + * @hash: hash table + * @key: string key * - * Find the userdata specified by the QName @prefix:@name/@name. + * Find the entry specified by @key. * - * Returns the pointer to the userdata + * Returns a pointer to the payload or NULL if no entry was found. */ void * -xmlHashQLookup(xmlHashTablePtr table, const xmlChar *prefix, - const xmlChar *name) { - return(xmlHashQLookup3(table, prefix, name, NULL, NULL, NULL, NULL)); +xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key) { + return(xmlHashLookup3(hash, key, NULL, NULL)); }
/** - * xmlHashQLookup2: - * @table: the hash table - * @prefix: the prefix of the userdata - * @name: the name of the userdata - * @prefix2: the second prefix of the userdata - * @name2: a second name of the userdata + * xmlHashLookup2: + * @hash: hash table + * @key: first string key + * @key2: second string key * - * Find the userdata specified by the QNames tuple + * Find the payload specified by the (@key, @key2) tuple. * - * Returns the pointer to the userdata + * Returns a pointer to the payload or NULL if no entry was found. */ void * -xmlHashQLookup2(xmlHashTablePtr table, const xmlChar *prefix, - const xmlChar *name, const xmlChar *prefix2, - const xmlChar *name2) { - return(xmlHashQLookup3(table, prefix, name, prefix2, name2, NULL, NULL)); +xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2) { + return(xmlHashLookup3(hash, key, key2, NULL)); }
/** - * xmlHashAddEntry3: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata - * @name3: a third name of the userdata - * @userdata: a pointer to the userdata + * xmlHashQLookup: + * @hash: hash table + * @prefix: prefix of the string key + * @name: local name of the string key * - * Add the @userdata to the hash @table. This can later be retrieved - * by using the tuple (@name, @name2, @name3). Duplicate entries generate - * errors. + * Find the payload specified by the QName @prefix:@name or @name. * - * Returns 0 the addition succeeded and -1 in case of error. + * Returns a pointer to the payload or NULL if no entry was found. */ -int -xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3, - void *userdata) { - unsigned long key, len = 0; - xmlHashEntryPtr entry; - xmlHashEntryPtr insert; - - if ((table == NULL) || (name == NULL)) - return(-1); - - /* - * If using a dict internalize if needed - */ - if (table->dict) { - if (!xmlDictOwns(table->dict, name)) { - name = xmlDictLookup(table->dict, name, -1); - if (name == NULL) - return(-1); - } - if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) { - name2 = xmlDictLookup(table->dict, name2, -1); - if (name2 == NULL) - return(-1); - } - if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) { - name3 = xmlDictLookup(table->dict, name3, -1); - if (name3 == NULL) - return(-1); - } - } - - /* - * Check for duplicate and insertion location. - */ - key = xmlHashComputeKey(table, name, name2, name3); - if (table->table[key].valid == 0) { - insert = NULL; - } else { - if (table->dict) { - for (insert = &(table->table[key]); insert->next != NULL; - insert = insert->next) { - if ((insert->name == name) && - (insert->name2 == name2) && - (insert->name3 == name3)) - return(-1); - len++; - } - if ((insert->name == name) && - (insert->name2 == name2) && - (insert->name3 == name3)) - return(-1); - } else { - for (insert = &(table->table[key]); insert->next != NULL; - insert = insert->next) { - if ((xmlStrEqual(insert->name, name)) && - (xmlStrEqual(insert->name2, name2)) && - (xmlStrEqual(insert->name3, name3))) - return(-1); - len++; - } - if ((xmlStrEqual(insert->name, name)) && - (xmlStrEqual(insert->name2, name2)) && - (xmlStrEqual(insert->name3, name3))) - return(-1); - } - } - - if (insert == NULL) { - entry = &(table->table[key]); - } else { - entry = xmlMalloc(sizeof(xmlHashEntry)); - if (entry == NULL) - return(-1); - } - - if (table->dict != NULL) { - entry->name = (xmlChar *) name; - entry->name2 = (xmlChar *) name2; - entry->name3 = (xmlChar *) name3; - } else { - entry->name = xmlStrdup(name); - if (entry->name == NULL) { - entry->name2 = NULL; - goto error; - } - if (name2 == NULL) { - entry->name2 = NULL; - } else { - entry->name2 = xmlStrdup(name2); - if (entry->name2 == NULL) - goto error; - } - if (name3 == NULL) { - entry->name3 = NULL; - } else { - entry->name3 = xmlStrdup(name3); - if (entry->name3 == NULL) - goto error; - } - } - entry->payload = userdata; - entry->next = NULL; - entry->valid = 1; - - - if (insert != NULL) - insert->next = entry; - - table->nbElems++; - - if (len > MAX_HASH_LEN) - xmlHashGrow(table, MAX_HASH_LEN * table->size); - - return(0); - -error: - xmlFree(entry->name2); - xmlFree(entry->name); - if (insert != NULL) - xmlFree(entry); - return(-1); +void * +xmlHashQLookup(xmlHashTablePtr hash, const xmlChar *prefix, + const xmlChar *name) { + return(xmlHashQLookup3(hash, prefix, name, NULL, NULL, NULL, NULL)); }
/** - * xmlHashUpdateEntry3: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata - * @name3: a third name of the userdata - * @userdata: a pointer to the userdata - * @f: the deallocator function for replaced item (if any) + * xmlHashQLookup2: + * @hash: hash table + * @prefix: first prefix + * @name: first local name + * @prefix2: second prefix + * @name2: second local name * - * Add the @userdata to the hash @table. This can later be retrieved - * by using the tuple (@name, @name2, @name3). Existing entry for this tuple - * will be removed and freed with @f if found. + * Find the payload specified by the QNames tuple. * - * Returns 0 the addition succeeded and -1 in case of error. + * Returns a pointer to the payload or NULL if no entry was found. */ -int -xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3, - void *userdata, xmlHashDeallocator f) { - unsigned long key; - xmlHashEntryPtr entry; - xmlHashEntryPtr insert; - - if ((table == NULL) || name == NULL) - return(-1); - - /* - * If using a dict internalize if needed - */ - if (table->dict) { - if (!xmlDictOwns(table->dict, name)) { - name = xmlDictLookup(table->dict, name, -1); - if (name == NULL) - return(-1); - } - if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) { - name2 = xmlDictLookup(table->dict, name2, -1); - if (name2 == NULL) - return(-1); - } - if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) { - name3 = xmlDictLookup(table->dict, name3, -1); - if (name3 == NULL) - return(-1); - } - } - - /* - * Check for duplicate and insertion location. - */ - key = xmlHashComputeKey(table, name, name2, name3); - if (table->table[key].valid == 0) { - insert = NULL; - } else { - if (table ->dict) { - for (insert = &(table->table[key]); insert->next != NULL; - insert = insert->next) { - if ((insert->name == name) && - (insert->name2 == name2) && - (insert->name3 == name3)) { - if (f) - f(insert->payload, insert->name); - insert->payload = userdata; - return(0); - } - } - if ((insert->name == name) && - (insert->name2 == name2) && - (insert->name3 == name3)) { - if (f) - f(insert->payload, insert->name); - insert->payload = userdata; - return(0); - } - } else { - for (insert = &(table->table[key]); insert->next != NULL; - insert = insert->next) { - if ((xmlStrEqual(insert->name, name)) && - (xmlStrEqual(insert->name2, name2)) && - (xmlStrEqual(insert->name3, name3))) { - if (f) - f(insert->payload, insert->name); - insert->payload = userdata; - return(0); - } - } - if ((xmlStrEqual(insert->name, name)) && - (xmlStrEqual(insert->name2, name2)) && - (xmlStrEqual(insert->name3, name3))) { - if (f) - f(insert->payload, insert->name); - insert->payload = userdata; - return(0); - } - } - } - - if (insert == NULL) { - entry = &(table->table[key]); - } else { - entry = xmlMalloc(sizeof(xmlHashEntry)); - if (entry == NULL) - return(-1); - } - - if (table->dict != NULL) { - entry->name = (xmlChar *) name; - entry->name2 = (xmlChar *) name2; - entry->name3 = (xmlChar *) name3; - } else { - entry->name = xmlStrdup(name); - if (entry->name == NULL) { - entry->name2 = NULL; - goto error; - } - if (name2 == NULL) { - entry->name2 = NULL; - } else { - entry->name2 = xmlStrdup(name2); - if (entry->name2 == NULL) - goto error; - } - if (name3 == NULL) { - entry->name3 = NULL; - } else { - entry->name3 = xmlStrdup(name3); - if (entry->name3 == NULL) - goto error; - } - } - entry->payload = userdata; - entry->next = NULL; - entry->valid = 1; - table->nbElems++; - - - if (insert != NULL) { - insert->next = entry; - } - return(0); - -error: - xmlFree(entry->name2); - xmlFree(entry->name); - if (insert != NULL) - xmlFree(entry); - return(-1); +void * +xmlHashQLookup2(xmlHashTablePtr hash, const xmlChar *prefix, + const xmlChar *name, const xmlChar *prefix2, + const xmlChar *name2) { + return(xmlHashQLookup3(hash, prefix, name, prefix2, name2, NULL, NULL)); }
/** * xmlHashLookup3: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata - * @name3: a third name of the userdata + * @hash: hash table + * @key: first string key + * @key2: second string key + * @key3: third string key * - * Find the userdata specified by the (@name, @name2, @name3) tuple. + * Find the payload specified by the (@key, @key2, @key3) tuple. * - * Returns the a pointer to the userdata + * Returns a pointer to the payload or NULL if no entry was found. */ void * -xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3) { - unsigned long key; - xmlHashEntryPtr entry; +xmlHashLookup3(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3) { + const xmlHashEntry *entry; + unsigned hashValue; + int found;
- if (table == NULL) - return(NULL); - if (name == NULL) - return(NULL); - key = xmlHashComputeKey(table, name, name2, name3); - if (table->table[key].valid == 0) - return(NULL); - if (table->dict) { - for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { - if ((entry->name == name) && - (entry->name2 == name2) && - (entry->name3 == name3)) - return(entry->payload); - } - } - for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { - if ((xmlStrEqual(entry->name, name)) && - (xmlStrEqual(entry->name2, name2)) && - (xmlStrEqual(entry->name3, name3))) - return(entry->payload); - } + if ((hash == NULL) || (hash->size == 0) || (key == NULL)) + return(NULL); + hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, NULL); + entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found); + if (found) + return(entry->payload); return(NULL); }
/** * xmlHashQLookup3: - * @table: the hash table - * @prefix: the prefix of the userdata - * @name: the name of the userdata - * @prefix2: the second prefix of the userdata - * @name2: a second name of the userdata - * @prefix3: the third prefix of the userdata - * @name3: a third name of the userdata + * @hash: hash table + * @prefix: first prefix + * @name: first local name + * @prefix2: second prefix + * @name2: second local name + * @prefix3: third prefix + * @name3: third local name * - * Find the userdata specified by the (@name, @name2, @name3) tuple. + * Find the payload specified by the QNames tuple. * - * Returns the a pointer to the userdata + * Returns a pointer to the payload or NULL if no entry was found. */ +ATTRIBUTE_NO_SANITIZE_INTEGER void * -xmlHashQLookup3(xmlHashTablePtr table, +xmlHashQLookup3(xmlHashTablePtr hash, const xmlChar *prefix, const xmlChar *name, - const xmlChar *prefix2, const xmlChar *name2, - const xmlChar *prefix3, const xmlChar *name3) { - unsigned long key; - xmlHashEntryPtr entry; + const xmlChar *prefix2, const xmlChar *name2, + const xmlChar *prefix3, const xmlChar *name3) { + const xmlHashEntry *entry; + unsigned hashValue, mask, pos, displ;
- if (table == NULL) - return(NULL); - if (name == NULL) - return(NULL); - key = xmlHashComputeQKey(table, prefix, name, prefix2, - name2, prefix3, name3); - if (table->table[key].valid == 0) - return(NULL); - for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { - if ((xmlStrQEqual(prefix, name, entry->name)) && - (xmlStrQEqual(prefix2, name2, entry->name2)) && - (xmlStrQEqual(prefix3, name3, entry->name3))) - return(entry->payload); + if ((hash == NULL) || (hash->size == 0) || (name == NULL)) + return(NULL); + + hashValue = xmlHashQNameValue(hash->randomSeed, prefix, name, prefix2, + name2, prefix3, name3); + mask = hash->size - 1; + pos = hashValue & mask; + entry = &hash->table[pos]; + + if (entry->hashValue != 0) { + displ = 0; + hashValue |= MAX_HASH_SIZE; + + do { + if ((hashValue == entry->hashValue) && + (xmlStrQEqual(prefix, name, entry->key)) && + (xmlStrQEqual(prefix2, name2, entry->key2)) && + (xmlStrQEqual(prefix3, name3, entry->key3))) + return(entry->payload); + + displ++; + pos++; + entry++; + if ((pos & mask) == 0) + entry = hash->table; + } while ((entry->hashValue != 0) && + (((pos - entry->hashValue) & mask) >= displ)); } + return(NULL); }
typedef struct { - xmlHashScanner hashscanner; + xmlHashScanner scan; void *data; } stubData;
static void -stubHashScannerFull (void *payload, void *data, const xmlChar *name, - const xmlChar *name2 ATTRIBUTE_UNUSED, - const xmlChar *name3 ATTRIBUTE_UNUSED) { - stubData *stubdata = (stubData *) data; - stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name); +stubHashScannerFull(void *payload, void *data, const xmlChar *key, + const xmlChar *key2 ATTRIBUTE_UNUSED, + const xmlChar *key3 ATTRIBUTE_UNUSED) { + stubData *sdata = (stubData *) data; + sdata->scan(payload, sdata->data, key); }
/** * xmlHashScan: - * @table: the hash table - * @f: the scanner function for items in the hash - * @data: extra data passed to f + * @hash: hash table + * @scan: scanner function for items in the hash + * @data: extra data passed to @scan * - * Scan the hash @table and applied @f to each value. + * Scan the hash @table and apply @scan to each value. */ void -xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) { - stubData stubdata; - stubdata.data = data; - stubdata.hashscanner = f; - xmlHashScanFull (table, stubHashScannerFull, &stubdata); +xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data) { + stubData sdata; + sdata.data = data; + sdata.scan = scan; + xmlHashScanFull(hash, stubHashScannerFull, &sdata); }
/** * xmlHashScanFull: - * @table: the hash table - * @f: the scanner function for items in the hash - * @data: extra data passed to f + * @hash: hash table + * @scan: scanner function for items in the hash + * @data: extra data passed to @scan * - * Scan the hash @table and applied @f to each value. + * Scan the hash @table and apply @scan to each value. */ void -xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) { - int i, nb; - xmlHashEntryPtr iter; - xmlHashEntryPtr next; +xmlHashScanFull(xmlHashTablePtr hash, xmlHashScannerFull scan, void *data) { + const xmlHashEntry *entry, *end; + xmlHashEntry old; + unsigned i;
- if (table == NULL) - return; - if (f == NULL) - return; - - if (table->table) { - for(i = 0; i < table->size; i++) { - if (table->table[i].valid == 0) - continue; - iter = &(table->table[i]); - while (iter) { - next = iter->next; - nb = table->nbElems; - if ((f != NULL) && (iter->payload != NULL)) - f(iter->payload, data, iter->name, - iter->name2, iter->name3); - if (nb != table->nbElems) { - /* table was modified by the callback, be careful */ - if (iter == &(table->table[i])) { - if (table->table[i].valid == 0) - iter = NULL; - if (table->table[i].next != next) - iter = &(table->table[i]); - } else - iter = next; - } else - iter = next; - } - } + if ((hash == NULL) || (hash->size == 0) || (scan == NULL)) + return; + + /* + * We must handle the case that a scanned entry is removed when executing + * the callback (xmlCleanSpecialAttr and possibly other places). + * + * Find the start of a probe sequence to avoid scanning entries twice if + * a deletion happens. + */ + entry = hash->table; + end = &hash->table[hash->size]; + while (entry->hashValue != 0) { + if (++entry >= end) + entry = hash->table; + } + + for (i = 0; i < hash->size; i++) { + if ((entry->hashValue != 0) && (entry->payload != NULL)) { + /* + * Make sure to rescan after a possible deletion. + */ + do { + old = *entry; + scan(entry->payload, data, entry->key, entry->key2, entry->key3); + } while ((entry->hashValue != 0) && + (entry->payload != NULL) && + ((entry->key != old.key) || + (entry->key2 != old.key2) || + (entry->key3 != old.key3))); + } + if (++entry >= end) + entry = hash->table; } }
/** * xmlHashScan3: - * @table: the hash table - * @name: the name of the userdata or NULL - * @name2: a second name of the userdata or NULL - * @name3: a third name of the userdata or NULL - * @f: the scanner function for items in the hash - * @data: extra data passed to f + * @hash: hash table + * @key: first string key or NULL + * @key2: second string key or NULL + * @key3: third string key or NULL + * @scan: scanner function for items in the hash + * @data: extra data passed to @scan * - * Scan the hash @table and applied @f to each value matching - * (@name, @name2, @name3) tuple. If one of the names is null, + * Scan the hash @table and apply @scan to each value matching + * (@key, @key2, @key3) tuple. If one of the keys is null, * the comparison is considered to match. */ void -xmlHashScan3(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3, - xmlHashScanner f, void *data) { - stubData stubdata; - stubdata.data = data; - stubdata.hashscanner = f; - xmlHashScanFull3(table, name, name2, name3, stubHashScannerFull, - &stubdata); +xmlHashScan3(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + xmlHashScanner scan, void *data) { + stubData sdata; + sdata.data = data; + sdata.scan = scan; + xmlHashScanFull3(hash, key, key2, key3, stubHashScannerFull, &sdata); }
/** * xmlHashScanFull3: - * @table: the hash table - * @name: the name of the userdata or NULL - * @name2: a second name of the userdata or NULL - * @name3: a third name of the userdata or NULL - * @f: the scanner function for items in the hash - * @data: extra data passed to f + * @hash: hash table + * @key: first string key or NULL + * @key2: second string key or NULL + * @key3: third string key or NULL + * @scan: scanner function for items in the hash + * @data: extra data passed to @scan * - * Scan the hash @table and applied @f to each value matching - * (@name, @name2, @name3) tuple. If one of the names is null, + * Scan the hash @table and apply @scan to each value matching + * (@key, @key2, @key3) tuple. If one of the keys is null, * the comparison is considered to match. */ void -xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3, - xmlHashScannerFull f, void *data) { - int i; - xmlHashEntryPtr iter; - xmlHashEntryPtr next; +xmlHashScanFull3(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + xmlHashScannerFull scan, void *data) { + const xmlHashEntry *entry, *end; + xmlHashEntry old; + unsigned i;
- if (table == NULL) - return; - if (f == NULL) - return; - - if (table->table) { - for(i = 0; i < table->size; i++) { - if (table->table[i].valid == 0) - continue; - iter = &(table->table[i]); - while (iter) { - next = iter->next; - if (((name == NULL) || (xmlStrEqual(name, iter->name))) && - ((name2 == NULL) || (xmlStrEqual(name2, iter->name2))) && - ((name3 == NULL) || (xmlStrEqual(name3, iter->name3))) && - (iter->payload != NULL)) { - f(iter->payload, data, iter->name, - iter->name2, iter->name3); - } - iter = next; - } - } + if ((hash == NULL) || (hash->size == 0) || (scan == NULL)) + return; + + /* + * We must handle the case that a scanned entry is removed when executing + * the callback (xmlCleanSpecialAttr and possibly other places). + * + * Find the start of a probe sequence to avoid scanning entries twice if + * a deletion happens. + */ + entry = hash->table; + end = &hash->table[hash->size]; + while (entry->hashValue != 0) { + if (++entry >= end) + entry = hash->table; + } + + for (i = 0; i < hash->size; i++) { + if ((entry->hashValue != 0) && (entry->payload != NULL)) { + /* + * Make sure to rescan after a possible deletion. + */ + do { + if (((key != NULL) && (strcmp((const char *) key, + (const char *) entry->key) != 0)) || + ((key2 != NULL) && (!xmlFastStrEqual(key2, entry->key2))) || + ((key3 != NULL) && (!xmlFastStrEqual(key3, entry->key3)))) + break; + old = *entry; + scan(entry->payload, data, entry->key, entry->key2, entry->key3); + } while ((entry->hashValue != 0) && + (entry->payload != NULL) && + ((entry->key != old.key) || + (entry->key2 != old.key2) || + (entry->key3 != old.key3))); + } + if (++entry >= end) + entry = hash->table; } }
/** * xmlHashCopy: - * @table: the hash table - * @f: the copier function for items in the hash + * @hash: hash table + * @copy: copier function for items in the hash * - * Scan the hash @table and applied @f to each value. + * Copy the hash @table using @copy to copy payloads. * - * Returns the new table or NULL in case of error. + * Returns the new table or NULL if a memory allocation failed. */ xmlHashTablePtr -xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) { - int i; - xmlHashEntryPtr iter; - xmlHashEntryPtr next; +xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy) { + const xmlHashEntry *entry, *end; xmlHashTablePtr ret;
- if (table == NULL) - return(NULL); - if (f == NULL) - return(NULL); + if ((hash == NULL) || (copy == NULL)) + return(NULL);
- ret = xmlHashCreate(table->size); + ret = xmlHashCreate(hash->size); if (ret == NULL) return(NULL);
- if (table->table) { - for(i = 0; i < table->size; i++) { - if (table->table[i].valid == 0) - continue; - iter = &(table->table[i]); - while (iter) { - next = iter->next; - xmlHashAddEntry3(ret, iter->name, iter->name2, - iter->name3, f(iter->payload, iter->name)); - iter = next; - } - } + if (hash->size == 0) + return(ret); + + end = &hash->table[hash->size]; + + for (entry = hash->table; entry < end; entry++) { + if (entry->hashValue != 0) + xmlHashAddEntry3(ret, entry->key, entry->key2, entry->key3, + copy(entry->payload, entry->key)); } - ret->nbElems = table->nbElems; + return(ret); }
/** * xmlHashSize: - * @table: the hash table + * @hash: hash table * - * Query the number of elements installed in the hash @table. + * Query the number of elements in the hash table. * * Returns the number of elements in the hash table or - * -1 in case of error + * -1 in case of error. */ int -xmlHashSize(xmlHashTablePtr table) { - if (table == NULL) - return(-1); - return(table->nbElems); +xmlHashSize(xmlHashTablePtr hash) { + if (hash == NULL) + return(-1); + return(hash->nbElems); }
/** * xmlHashRemoveEntry: - * @table: the hash table - * @name: the name of the userdata - * @f: the deallocator function for removed item (if any) + * @hash: hash table + * @key: string key + * @dealloc: deallocator function for removed item or NULL * - * Find the userdata specified by the @name and remove - * it from the hash @table. Existing userdata for this tuple will be removed - * and freed with @f. + * Find the entry specified by the @key and remove it from the hash table. + * Payload will be freed with @dealloc. * - * Returns 0 if the removal succeeded and -1 in case of error or not found. + * Returns 0 on success and -1 if no entry was found. */ -int xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, - xmlHashDeallocator f) { - return(xmlHashRemoveEntry3(table, name, NULL, NULL, f)); +int xmlHashRemoveEntry(xmlHashTablePtr hash, const xmlChar *key, + xmlHashDeallocator dealloc) { + return(xmlHashRemoveEntry3(hash, key, NULL, NULL, dealloc)); }
/** * xmlHashRemoveEntry2: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata - * @f: the deallocator function for removed item (if any) + * @hash: hash table + * @key: first string key + * @key2: second string key + * @dealloc: deallocator function for removed item or NULL * - * Find the userdata specified by the (@name, @name2) tuple and remove - * it from the hash @table. Existing userdata for this tuple will be removed - * and freed with @f. + * Remove an entry with two strings as key. * - * Returns 0 if the removal succeeded and -1 in case of error or not found. + * See xmlHashRemoveEntry. + * + * Returns 0 on success and -1 in case of error. */ int -xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, xmlHashDeallocator f) { - return(xmlHashRemoveEntry3(table, name, name2, NULL, f)); +xmlHashRemoveEntry2(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, xmlHashDeallocator dealloc) { + return(xmlHashRemoveEntry3(hash, key, key2, NULL, dealloc)); }
/** * xmlHashRemoveEntry3: - * @table: the hash table - * @name: the name of the userdata - * @name2: a second name of the userdata - * @name3: a third name of the userdata - * @f: the deallocator function for removed item (if any) + * @hash: hash table + * @key: first string key + * @key2: second string key + * @key3: third string key + * @dealloc: deallocator function for removed item or NULL + * + * Remove an entry with three strings as key. * - * Find the userdata specified by the (@name, @name2, @name3) tuple and remove - * it from the hash @table. Existing userdata for this tuple will be removed - * and freed with @f. + * See xmlHashRemoveEntry. * - * Returns 0 if the removal succeeded and -1 in case of error or not found. + * Returns 0 on success and -1 in case of error. */ +ATTRIBUTE_NO_SANITIZE_INTEGER int -xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f) { - unsigned long key; - xmlHashEntryPtr entry; - xmlHashEntryPtr prev = NULL; - - if (table == NULL || name == NULL) +xmlHashRemoveEntry3(xmlHashTablePtr hash, const xmlChar *key, + const xmlChar *key2, const xmlChar *key3, + xmlHashDeallocator dealloc) { + xmlHashEntry *entry, *cur, *next; + unsigned hashValue, mask, pos, nextpos; + int found; + + if ((hash == NULL) || (hash->size == 0) || (key == NULL)) return(-1);
- key = xmlHashComputeKey(table, name, name2, name3); - if (table->table[key].valid == 0) { - return(-1); - } else { - for (entry = &(table->table[key]); entry != NULL; entry = entry->next) { - if (xmlStrEqual(entry->name, name) && - xmlStrEqual(entry->name2, name2) && - xmlStrEqual(entry->name3, name3)) { - if ((f != NULL) && (entry->payload != NULL)) - f(entry->payload, entry->name); - entry->payload = NULL; - if (table->dict == NULL) { - if(entry->name) - xmlFree(entry->name); - if(entry->name2) - xmlFree(entry->name2); - if(entry->name3) - xmlFree(entry->name3); - } - if(prev) { - prev->next = entry->next; - xmlFree(entry); - } else { - if (entry->next == NULL) { - entry->valid = 0; - } else { - entry = entry->next; - memcpy(&(table->table[key]), entry, sizeof(xmlHashEntry)); - xmlFree(entry); - } - } - table->nbElems--; - return(0); - } - prev = entry; - } + hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, NULL); + entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found); + if (!found) return(-1); + + if ((dealloc != NULL) && (entry->payload != NULL)) + dealloc(entry->payload, entry->key); + if (hash->dict == NULL) { + if (entry->key) + xmlFree(entry->key); + if (entry->key2) + xmlFree(entry->key2); + if (entry->key3) + xmlFree(entry->key3); } -}
+ /* + * Find end of probe sequence. Entries at their initial probe + * position start a new sequence. + */ + mask = hash->size - 1; + pos = entry - hash->table; + cur = entry; + + while (1) { + nextpos = pos + 1; + next = cur + 1; + if ((nextpos & mask) == 0) + next = hash->table; + + if ((next->hashValue == 0) || + (((next->hashValue - nextpos) & mask) == 0)) + break; + + cur = next; + pos = nextpos; + } + + /* + * Backward shift + */ + next = entry + 1; + + if (cur < entry) { + xmlHashEntry *end = &hash->table[hash->size]; + + memmove(entry, next, (char *) end - (char *) next); + entry = hash->table; + end[-1] = *entry; + next = entry + 1; + } + + memmove(entry, next, (char *) cur - (char *) entry); + + /* + * Update entry + */ + cur->hashValue = 0; + + hash->nbElems--; + + return(0); +} diff --git a/libs/xml2/include/libxml/HTMLparser.h b/libs/xml2/include/libxml/HTMLparser.h index e43feeea2e7..e16d77492b2 100644 --- a/libs/xml2/include/libxml/HTMLparser.h +++ b/libs/xml2/include/libxml/HTMLparser.h @@ -80,6 +80,23 @@ struct _htmlEntityDesc { const char *desc; /* the description */ };
+/** DOC_DISABLE */ +#ifdef LIBXML_SAX1_ENABLED + #define XML_GLOBALS_HTML \ + XML_OP(htmlDefaultSAXHandler, xmlSAXHandlerV1, XML_DEPRECATED) +#else + #define XML_GLOBALS_HTML +#endif + +#define XML_OP XML_DECLARE_GLOBAL +XML_GLOBALS_HTML +#undef XML_OP + +#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) + #define htmlDefaultSAXHandler XML_GLOBAL_MACRO(htmlDefaultSAXHandler) +#endif +/** DOC_ENABLE */ + /* * There is only few public functions. */ @@ -316,5 +333,11 @@ XMLPUBFUN htmlStatus htmlNodeStatus(const htmlNodePtr, int) ; } #endif
+#else /* LIBXML_HTML_ENABLED */ + +/** DOC_DISABLE */ +#define XML_GLOBALS_HTML +/** DOC_ENABLE */ + #endif /* LIBXML_HTML_ENABLED */ #endif /* __HTML_PARSER_H__ */ diff --git a/libs/xml2/include/libxml/SAX.h b/libs/xml2/include/libxml/SAX.h index ecd3211a5af..eea1057bfcc 100644 --- a/libs/xml2/include/libxml/SAX.h +++ b/libs/xml2/include/libxml/SAX.h @@ -12,8 +12,6 @@ #ifndef __XML_SAX_H__ #define __XML_SAX_H__
-#include <stdio.h> -#include <stdlib.h> #include <libxml/xmlversion.h> #include <libxml/parser.h>
diff --git a/libs/xml2/include/libxml/SAX2.h b/libs/xml2/include/libxml/SAX2.h index 35e7a5f4b2a..4c4ecce8e59 100644 --- a/libs/xml2/include/libxml/SAX2.h +++ b/libs/xml2/include/libxml/SAX2.h @@ -12,8 +12,6 @@ #ifndef __XML_SAX2_H__ #define __XML_SAX2_H__
-#include <stdio.h> -#include <stdlib.h> #include <libxml/xmlversion.h> #include <libxml/parser.h>
diff --git a/libs/xml2/include/libxml/dict.h b/libs/xml2/include/libxml/dict.h index eb8f85db6ef..22aa3d9db8b 100644 --- a/libs/xml2/include/libxml/dict.h +++ b/libs/xml2/include/libxml/dict.h @@ -13,6 +13,7 @@
#include <stddef.h> #include <libxml/xmlversion.h> +#include <libxml/xmlstring.h>
#ifdef __cplusplus extern "C" { diff --git a/libs/xml2/include/libxml/encoding.h b/libs/xml2/include/libxml/encoding.h index 67add3b0508..8594cffc173 100644 --- a/libs/xml2/include/libxml/encoding.h +++ b/libs/xml2/include/libxml/encoding.h @@ -32,6 +32,15 @@ extern "C" { #endif
+typedef enum { + XML_ENC_ERR_SUCCESS = 0, + XML_ENC_ERR_SPACE = -1, + XML_ENC_ERR_INPUT = -2, + XML_ENC_ERR_PARTIAL = -3, + XML_ENC_ERR_INTERNAL = -4, + XML_ENC_ERR_MEMORY = -5 +} xmlCharEncError; + /* * xmlCharEncoding: * @@ -142,14 +151,6 @@ struct _xmlCharEncodingHandler { #endif /* LIBXML_ICU_ENABLED */ };
-#ifdef __cplusplus -} -#endif -#include <libxml/tree.h> -#ifdef __cplusplus -extern "C" { -#endif - /* * Interfaces for encoding handlers. */ @@ -194,20 +195,21 @@ XMLPUBFUN xmlCharEncoding xmlDetectCharEncoding (const unsigned char *in, int len);
+struct _xmlBuffer; XMLPUBFUN int xmlCharEncOutFunc (xmlCharEncodingHandler *handler, - xmlBufferPtr out, - xmlBufferPtr in); + struct _xmlBuffer *out, + struct _xmlBuffer *in);
XMLPUBFUN int xmlCharEncInFunc (xmlCharEncodingHandler *handler, - xmlBufferPtr out, - xmlBufferPtr in); + struct _xmlBuffer *out, + struct _xmlBuffer *in); XML_DEPRECATED XMLPUBFUN int xmlCharEncFirstLine (xmlCharEncodingHandler *handler, - xmlBufferPtr out, - xmlBufferPtr in); + struct _xmlBuffer *out, + struct _xmlBuffer *in); XMLPUBFUN int xmlCharEncCloseFunc (xmlCharEncodingHandler *handler);
diff --git a/libs/xml2/include/libxml/entities.h b/libs/xml2/include/libxml/entities.h index 2c69514cd20..f679375321e 100644 --- a/libs/xml2/include/libxml/entities.h +++ b/libs/xml2/include/libxml/entities.h @@ -12,7 +12,9 @@ #define __XML_ENTITIES_H__
#include <libxml/xmlversion.h> +#define XML_TREE_INTERNALS #include <libxml/tree.h> +#undef XML_TREE_INTERNALS
#ifdef __cplusplus extern "C" { @@ -85,6 +87,8 @@ XMLPUBFUN xmlEntityPtr const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content); +XMLPUBFUN void + xmlFreeEntity (xmlEntityPtr entity); XMLPUBFUN xmlEntityPtr xmlAddDocEntity (xmlDocPtr doc, const xmlChar *name, diff --git a/libs/xml2/include/libxml/globals.h b/libs/xml2/include/libxml/globals.h index 59697290528..92f41312f54 100644 --- a/libs/xml2/include/libxml/globals.h +++ b/libs/xml2/include/libxml/globals.h @@ -1,526 +1,38 @@ /* * Summary: interface for all global variables of the library - * Description: all the global variables and thread handling for - * those variables is handled by this module. - * - * The bottom of this file is automatically generated by build_glob.py - * based on the description file global.data + * Description: Deprecated, don't use * * Copy: See Copyright for the status of this software. - * - * Author: Gary Pennington Gary.Pennington@uk.sun.com, Daniel Veillard */
#ifndef __XML_GLOBALS_H #define __XML_GLOBALS_H
#include <libxml/xmlversion.h> -#include <libxml/parser.h> -#include <libxml/xmlerror.h> -#include <libxml/SAX2.h> -#include <libxml/xmlmemory.h> - -#ifdef __cplusplus -extern "C" { -#endif - -XML_DEPRECATED -XMLPUBFUN void xmlInitGlobals(void); -XML_DEPRECATED -XMLPUBFUN void xmlCleanupGlobals(void); - -/** - * xmlParserInputBufferCreateFilenameFunc: - * @URI: the URI to read from - * @enc: the requested source encoding - * - * Signature for the function doing the lookup for a suitable input method - * corresponding to an URI. - * - * Returns the new xmlParserInputBufferPtr in case of success or NULL if no - * method was found. - */ -typedef xmlParserInputBufferPtr (*xmlParserInputBufferCreateFilenameFunc) (const char *URI, - xmlCharEncoding enc); - - -/** - * xmlOutputBufferCreateFilenameFunc: - * @URI: the URI to write to - * @enc: the requested target encoding - * - * Signature for the function doing the lookup for a suitable output method - * corresponding to an URI. - * - * Returns the new xmlOutputBufferPtr in case of success or NULL if no - * method was found. - */ -typedef xmlOutputBufferPtr (*xmlOutputBufferCreateFilenameFunc) (const char *URI, - xmlCharEncodingHandlerPtr encoder, - int compression); - -XMLPUBFUN xmlParserInputBufferCreateFilenameFunc -xmlParserInputBufferCreateFilenameDefault (xmlParserInputBufferCreateFilenameFunc func); -XMLPUBFUN xmlOutputBufferCreateFilenameFunc -xmlOutputBufferCreateFilenameDefault (xmlOutputBufferCreateFilenameFunc func);
/* - * Externally global symbols which need to be protected for backwards - * compatibility support. - */ - -#undef htmlDefaultSAXHandler -#undef oldXMLWDcompatibility -#undef xmlBufferAllocScheme -#undef xmlDefaultBufferSize -#undef xmlDefaultSAXHandler -#undef xmlDefaultSAXLocator -#undef xmlDoValidityCheckingDefaultValue -#undef xmlFree -#undef xmlGenericError -#undef xmlStructuredError -#undef xmlGenericErrorContext -#undef xmlStructuredErrorContext -#undef xmlGetWarningsDefaultValue -#undef xmlIndentTreeOutput -#undef xmlTreeIndentString -#undef xmlKeepBlanksDefaultValue -#undef xmlLineNumbersDefaultValue -#undef xmlLoadExtDtdDefaultValue -#undef xmlMalloc -#undef xmlMallocAtomic -#undef xmlMemStrdup -#undef xmlParserDebugEntities -#undef xmlParserVersion -#undef xmlPedanticParserDefaultValue -#undef xmlRealloc -#undef xmlSaveNoEmptyTags -#undef xmlSubstituteEntitiesDefaultValue -#undef xmlRegisterNodeDefaultValue -#undef xmlDeregisterNodeDefaultValue -#undef xmlLastError -#undef xmlParserInputBufferCreateFilenameValue -#undef xmlOutputBufferCreateFilenameValue - -/** - * xmlRegisterNodeFunc: - * @node: the current node - * - * Signature for the registration callback of a created node - */ -typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node); -/** - * xmlDeregisterNodeFunc: - * @node: the current node + * This file was required to access global variables until version v2.12.0. * - * Signature for the deregistration callback of a discarded node + * These includes are for backward compatibility. */ -typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node); - -typedef struct _xmlGlobalState xmlGlobalState; -typedef xmlGlobalState *xmlGlobalStatePtr; -struct _xmlGlobalState -{ - const char *xmlParserVersion; - - xmlSAXLocator xmlDefaultSAXLocator; - xmlSAXHandlerV1 xmlDefaultSAXHandler; - xmlSAXHandlerV1 docbDefaultSAXHandler; /* unused */ - xmlSAXHandlerV1 htmlDefaultSAXHandler; - - xmlFreeFunc xmlFree; - xmlMallocFunc xmlMalloc; - xmlStrdupFunc xmlMemStrdup; - xmlReallocFunc xmlRealloc; - - xmlGenericErrorFunc xmlGenericError; - xmlStructuredErrorFunc xmlStructuredError; - void *xmlGenericErrorContext; - - int oldXMLWDcompatibility; - - xmlBufferAllocationScheme xmlBufferAllocScheme; - int xmlDefaultBufferSize; - - int xmlSubstituteEntitiesDefaultValue; - int xmlDoValidityCheckingDefaultValue; - int xmlGetWarningsDefaultValue; - int xmlKeepBlanksDefaultValue; - int xmlLineNumbersDefaultValue; - int xmlLoadExtDtdDefaultValue; - int xmlParserDebugEntities; - int xmlPedanticParserDefaultValue; - - int xmlSaveNoEmptyTags; - int xmlIndentTreeOutput; - const char *xmlTreeIndentString; - - xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; - xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; - - xmlMallocFunc xmlMallocAtomic; - xmlError xmlLastError; - - xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; - xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; - - void *xmlStructuredErrorContext; -}; - -#ifdef __cplusplus -} -#endif +#include <libxml/HTMLparser.h> +#include <libxml/parser.h> +#include <libxml/xmlerror.h> +#include <libxml/xmlIO.h> +#include <libxml/xmlsave.h> #include <libxml/threads.h> + #ifdef __cplusplus extern "C" { #endif
-XMLPUBFUN void xmlInitializeGlobalState(xmlGlobalStatePtr gs); - -XMLPUBFUN void xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler); - -XMLPUBFUN void xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler); - -XMLPUBFUN xmlRegisterNodeFunc xmlRegisterNodeDefault(xmlRegisterNodeFunc func); -XMLPUBFUN xmlRegisterNodeFunc xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func); -XMLPUBFUN xmlDeregisterNodeFunc xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func); -XMLPUBFUN xmlDeregisterNodeFunc xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func); - -XMLPUBFUN xmlOutputBufferCreateFilenameFunc - xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func); -XMLPUBFUN xmlParserInputBufferCreateFilenameFunc - xmlThrDefParserInputBufferCreateFilenameDefault( - xmlParserInputBufferCreateFilenameFunc func); - -/* - * In general the memory allocation entry points are not kept - * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED - * - xmlMalloc - * - xmlMallocAtomic - * - xmlRealloc - * - xmlMemStrdup - * - xmlFree - */ - -#ifdef LIBXML_THREAD_ALLOC_ENABLED -/** DOC_DISABLE */ - -#ifdef LIBXML_THREAD_ENABLED -XMLPUBFUN xmlMallocFunc * __xmlMalloc(void); -#define xmlMalloc \ -(*(__xmlMalloc())) -#else -XMLPUBVAR xmlMallocFunc xmlMalloc; -#endif - -#ifdef LIBXML_THREAD_ENABLED -XMLPUBFUN xmlMallocFunc * __xmlMallocAtomic(void); -#define xmlMallocAtomic \ -(*(__xmlMallocAtomic())) -#else -XMLPUBVAR xmlMallocFunc xmlMallocAtomic; -#endif - -#ifdef LIBXML_THREAD_ENABLED -XMLPUBFUN xmlReallocFunc * __xmlRealloc(void); -#define xmlRealloc \ -(*(__xmlRealloc())) -#else -XMLPUBVAR xmlReallocFunc xmlRealloc; -#endif - -#ifdef LIBXML_THREAD_ENABLED -XMLPUBFUN xmlFreeFunc * __xmlFree(void); -#define xmlFree \ -(*(__xmlFree())) -#else -XMLPUBVAR xmlFreeFunc xmlFree; -#endif - -#ifdef LIBXML_THREAD_ENABLED -XMLPUBFUN xmlStrdupFunc * __xmlMemStrdup(void); -#define xmlMemStrdup \ -(*(__xmlMemStrdup())) -#else -XMLPUBVAR xmlStrdupFunc xmlMemStrdup; -#endif - -/** DOC_ENABLE */ -#else /* !LIBXML_THREAD_ALLOC_ENABLED */ -XMLPUBVAR xmlMallocFunc xmlMalloc; -XMLPUBVAR xmlMallocFunc xmlMallocAtomic; -XMLPUBVAR xmlReallocFunc xmlRealloc; -XMLPUBVAR xmlFreeFunc xmlFree; -XMLPUBVAR xmlStrdupFunc xmlMemStrdup; -#endif /* LIBXML_THREAD_ALLOC_ENABLED */ - -#ifdef LIBXML_HTML_ENABLED -XML_DEPRECATED -XMLPUBFUN xmlSAXHandlerV1 * __htmlDefaultSAXHandler(void); -#ifdef LIBXML_THREAD_ENABLED -#define htmlDefaultSAXHandler \ -(*(__htmlDefaultSAXHandler())) -#else -XML_DEPRECATED -XMLPUBVAR xmlSAXHandlerV1 htmlDefaultSAXHandler; -#endif -#endif - -XMLPUBFUN xmlError * __xmlLastError(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlLastError \ -(*(__xmlLastError())) -#else -XMLPUBVAR xmlError xmlLastError; -#endif - -/* - * Everything starting from the line below is - * Automatically generated by build_glob.py. - * Do not modify the previous line. - */ - - -XML_DEPRECATED -XMLPUBFUN int * __oldXMLWDcompatibility(void); -#ifdef LIBXML_THREAD_ENABLED -#define oldXMLWDcompatibility \ -(*(__oldXMLWDcompatibility())) -#else -XML_DEPRECATED -XMLPUBVAR int oldXMLWDcompatibility; -#endif - -XML_DEPRECATED -XMLPUBFUN xmlBufferAllocationScheme * __xmlBufferAllocScheme(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlBufferAllocScheme \ -(*(__xmlBufferAllocScheme())) -#else -XML_DEPRECATED -XMLPUBVAR xmlBufferAllocationScheme xmlBufferAllocScheme; -#endif -XML_DEPRECATED -XMLPUBFUN xmlBufferAllocationScheme - xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v); - -XML_DEPRECATED -XMLPUBFUN int * __xmlDefaultBufferSize(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlDefaultBufferSize \ -(*(__xmlDefaultBufferSize())) -#else -XML_DEPRECATED -XMLPUBVAR int xmlDefaultBufferSize; -#endif -XML_DEPRECATED -XMLPUBFUN int xmlThrDefDefaultBufferSize(int v); - -XML_DEPRECATED -XMLPUBFUN xmlSAXHandlerV1 * __xmlDefaultSAXHandler(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlDefaultSAXHandler \ -(*(__xmlDefaultSAXHandler())) -#else -XML_DEPRECATED -XMLPUBVAR xmlSAXHandlerV1 xmlDefaultSAXHandler; -#endif - -XML_DEPRECATED -XMLPUBFUN xmlSAXLocator * __xmlDefaultSAXLocator(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlDefaultSAXLocator \ -(*(__xmlDefaultSAXLocator())) -#else -XML_DEPRECATED -XMLPUBVAR xmlSAXLocator xmlDefaultSAXLocator; -#endif - -XMLPUBFUN int * __xmlDoValidityCheckingDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlDoValidityCheckingDefaultValue \ -(*(__xmlDoValidityCheckingDefaultValue())) -#else -XMLPUBVAR int xmlDoValidityCheckingDefaultValue; -#endif -XMLPUBFUN int xmlThrDefDoValidityCheckingDefaultValue(int v); - -XMLPUBFUN xmlGenericErrorFunc * __xmlGenericError(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlGenericError \ -(*(__xmlGenericError())) -#else -XMLPUBVAR xmlGenericErrorFunc xmlGenericError; -#endif - -XMLPUBFUN xmlStructuredErrorFunc * __xmlStructuredError(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlStructuredError \ -(*(__xmlStructuredError())) -#else -XMLPUBVAR xmlStructuredErrorFunc xmlStructuredError; -#endif - -XMLPUBFUN void * * __xmlGenericErrorContext(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlGenericErrorContext \ -(*(__xmlGenericErrorContext())) -#else -XMLPUBVAR void * xmlGenericErrorContext; -#endif - -XMLPUBFUN void * * __xmlStructuredErrorContext(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlStructuredErrorContext \ -(*(__xmlStructuredErrorContext())) -#else -XMLPUBVAR void * xmlStructuredErrorContext; -#endif - -XMLPUBFUN int * __xmlGetWarningsDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlGetWarningsDefaultValue \ -(*(__xmlGetWarningsDefaultValue())) -#else -XMLPUBVAR int xmlGetWarningsDefaultValue; -#endif -XMLPUBFUN int xmlThrDefGetWarningsDefaultValue(int v); - -XMLPUBFUN int * __xmlIndentTreeOutput(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlIndentTreeOutput \ -(*(__xmlIndentTreeOutput())) -#else -XMLPUBVAR int xmlIndentTreeOutput; -#endif -XMLPUBFUN int xmlThrDefIndentTreeOutput(int v); - -XMLPUBFUN const char * * __xmlTreeIndentString(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlTreeIndentString \ -(*(__xmlTreeIndentString())) -#else -XMLPUBVAR const char * xmlTreeIndentString; -#endif -XMLPUBFUN const char * xmlThrDefTreeIndentString(const char * v); - -XMLPUBFUN int * __xmlKeepBlanksDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlKeepBlanksDefaultValue \ -(*(__xmlKeepBlanksDefaultValue())) -#else -XMLPUBVAR int xmlKeepBlanksDefaultValue; -#endif -XMLPUBFUN int xmlThrDefKeepBlanksDefaultValue(int v); - -XML_DEPRECATED -XMLPUBFUN int * __xmlLineNumbersDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlLineNumbersDefaultValue \ -(*(__xmlLineNumbersDefaultValue())) -#else -XML_DEPRECATED -XMLPUBVAR int xmlLineNumbersDefaultValue; -#endif -XML_DEPRECATED -XMLPUBFUN int xmlThrDefLineNumbersDefaultValue(int v); - -XMLPUBFUN int * __xmlLoadExtDtdDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlLoadExtDtdDefaultValue \ -(*(__xmlLoadExtDtdDefaultValue())) -#else -XMLPUBVAR int xmlLoadExtDtdDefaultValue; -#endif -XMLPUBFUN int xmlThrDefLoadExtDtdDefaultValue(int v); - -XMLPUBFUN int * __xmlParserDebugEntities(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlParserDebugEntities \ -(*(__xmlParserDebugEntities())) -#else -XMLPUBVAR int xmlParserDebugEntities; -#endif -XMLPUBFUN int xmlThrDefParserDebugEntities(int v); - -XMLPUBFUN const char * * __xmlParserVersion(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlParserVersion \ -(*(__xmlParserVersion())) -#else -XMLPUBVAR const char * xmlParserVersion; -#endif - -XML_DEPRECATED -XMLPUBFUN int * __xmlPedanticParserDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlPedanticParserDefaultValue \ -(*(__xmlPedanticParserDefaultValue())) -#else -XML_DEPRECATED -XMLPUBVAR int xmlPedanticParserDefaultValue; -#endif -XML_DEPRECATED -XMLPUBFUN int xmlThrDefPedanticParserDefaultValue(int v); - -XMLPUBFUN int * __xmlSaveNoEmptyTags(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlSaveNoEmptyTags \ -(*(__xmlSaveNoEmptyTags())) -#else -XMLPUBVAR int xmlSaveNoEmptyTags; -#endif -XMLPUBFUN int xmlThrDefSaveNoEmptyTags(int v); - -XMLPUBFUN int * __xmlSubstituteEntitiesDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlSubstituteEntitiesDefaultValue \ -(*(__xmlSubstituteEntitiesDefaultValue())) -#else -XMLPUBVAR int xmlSubstituteEntitiesDefaultValue; -#endif -XMLPUBFUN int xmlThrDefSubstituteEntitiesDefaultValue(int v); - -XML_DEPRECATED -XMLPUBFUN xmlRegisterNodeFunc * __xmlRegisterNodeDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlRegisterNodeDefaultValue \ -(*(__xmlRegisterNodeDefaultValue())) -#else -XML_DEPRECATED -XMLPUBVAR xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; -#endif - -XML_DEPRECATED -XMLPUBFUN xmlDeregisterNodeFunc * __xmlDeregisterNodeDefaultValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlDeregisterNodeDefaultValue \ -(*(__xmlDeregisterNodeDefaultValue())) -#else -XML_DEPRECATED -XMLPUBVAR xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; -#endif - -XML_DEPRECATED -XMLPUBFUN xmlParserInputBufferCreateFilenameFunc * \ - __xmlParserInputBufferCreateFilenameValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlParserInputBufferCreateFilenameValue \ -(*(__xmlParserInputBufferCreateFilenameValue())) -#else -XML_DEPRECATED -XMLPUBVAR xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; -#endif +typedef struct _xmlGlobalState xmlGlobalState; +typedef xmlGlobalState *xmlGlobalStatePtr;
-XML_DEPRECATED -XMLPUBFUN xmlOutputBufferCreateFilenameFunc * __xmlOutputBufferCreateFilenameValue(void); -#ifdef LIBXML_THREAD_ENABLED -#define xmlOutputBufferCreateFilenameValue \ -(*(__xmlOutputBufferCreateFilenameValue())) -#else -XML_DEPRECATED -XMLPUBVAR xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; -#endif +XML_DEPRECATED XMLPUBFUN void +xmlInitializeGlobalState(xmlGlobalStatePtr gs); +XML_DEPRECATED XMLPUBFUN +xmlGlobalStatePtr xmlGetGlobalState(void);
#ifdef __cplusplus } diff --git a/libs/xml2/include/libxml/hash.h b/libs/xml2/include/libxml/hash.h index 1dac035b02f..f4af09ee5f9 100644 --- a/libs/xml2/include/libxml/hash.h +++ b/libs/xml2/include/libxml/hash.h @@ -11,6 +11,10 @@ #ifndef __XML_HASH_H__ #define __XML_HASH_H__
+#include <libxml/xmlversion.h> +#include <libxml/dict.h> +#include <libxml/xmlstring.h> + #ifdef __cplusplus extern "C" { #endif @@ -21,18 +25,6 @@ extern "C" { typedef struct _xmlHashTable xmlHashTable; typedef xmlHashTable *xmlHashTablePtr;
-#ifdef __cplusplus -} -#endif - -#include <libxml/xmlversion.h> -#include <libxml/parser.h> -#include <libxml/dict.h> - -#ifdef __cplusplus -extern "C" { -#endif - /* * Recent version of gcc produce a warning when a function pointer is assigned * to an object pointer, or vice versa. The following macro is a dirty hack @@ -55,7 +47,6 @@ extern "C" {
#define XML_CAST_FPTR(fptr) fptr
- /* * function types: */ @@ -104,131 +95,136 @@ typedef void (*xmlHashScannerFull)(void *payload, void *data, * Constructor and destructor. */ XMLPUBFUN xmlHashTablePtr - xmlHashCreate (int size); + xmlHashCreate (int size); XMLPUBFUN xmlHashTablePtr - xmlHashCreateDict(int size, + xmlHashCreateDict (int size, xmlDictPtr dict); XMLPUBFUN void - xmlHashFree (xmlHashTablePtr table, - xmlHashDeallocator f); + xmlHashFree (xmlHashTablePtr hash, + xmlHashDeallocator dealloc); XMLPUBFUN void - xmlHashDefaultDeallocator(void *entry, + xmlHashDefaultDeallocator(void *entry, const xmlChar *name);
/* * Add a new entry to the hash table. */ XMLPUBFUN int - xmlHashAddEntry (xmlHashTablePtr table, + xmlHashAddEntry (xmlHashTablePtr hash, const xmlChar *name, void *userdata); XMLPUBFUN int - xmlHashUpdateEntry(xmlHashTablePtr table, + xmlHashUpdateEntry (xmlHashTablePtr hash, const xmlChar *name, void *userdata, - xmlHashDeallocator f); + xmlHashDeallocator dealloc); XMLPUBFUN int - xmlHashAddEntry2(xmlHashTablePtr table, + xmlHashAddEntry2 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2, void *userdata); XMLPUBFUN int - xmlHashUpdateEntry2(xmlHashTablePtr table, + xmlHashUpdateEntry2 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2, void *userdata, - xmlHashDeallocator f); + xmlHashDeallocator dealloc); XMLPUBFUN int - xmlHashAddEntry3(xmlHashTablePtr table, + xmlHashAddEntry3 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata); XMLPUBFUN int - xmlHashUpdateEntry3(xmlHashTablePtr table, + xmlHashUpdateEntry3 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata, - xmlHashDeallocator f); + xmlHashDeallocator dealloc);
/* * Remove an entry from the hash table. */ XMLPUBFUN int - xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, - xmlHashDeallocator f); + xmlHashRemoveEntry (xmlHashTablePtr hash, + const xmlChar *name, + xmlHashDeallocator dealloc); XMLPUBFUN int - xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, xmlHashDeallocator f); + xmlHashRemoveEntry2 (xmlHashTablePtr hash, + const xmlChar *name, + const xmlChar *name2, + xmlHashDeallocator dealloc); XMLPUBFUN int - xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name, - const xmlChar *name2, const xmlChar *name3, - xmlHashDeallocator f); + xmlHashRemoveEntry3 (xmlHashTablePtr hash, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + xmlHashDeallocator dealloc);
/* - * Retrieve the userdata. + * Retrieve the payload. */ XMLPUBFUN void * - xmlHashLookup (xmlHashTablePtr table, + xmlHashLookup (xmlHashTablePtr hash, const xmlChar *name); XMLPUBFUN void * - xmlHashLookup2 (xmlHashTablePtr table, + xmlHashLookup2 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2); XMLPUBFUN void * - xmlHashLookup3 (xmlHashTablePtr table, + xmlHashLookup3 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2, const xmlChar *name3); XMLPUBFUN void * - xmlHashQLookup (xmlHashTablePtr table, - const xmlChar *name, - const xmlChar *prefix); -XMLPUBFUN void * - xmlHashQLookup2 (xmlHashTablePtr table, - const xmlChar *name, + xmlHashQLookup (xmlHashTablePtr hash, const xmlChar *prefix, - const xmlChar *name2, - const xmlChar *prefix2); + const xmlChar *name); XMLPUBFUN void * - xmlHashQLookup3 (xmlHashTablePtr table, + xmlHashQLookup2 (xmlHashTablePtr hash, + const xmlChar *prefix, const xmlChar *name, + const xmlChar *prefix2, + const xmlChar *name2); +XMLPUBFUN void * + xmlHashQLookup3 (xmlHashTablePtr hash, const xmlChar *prefix, - const xmlChar *name2, + const xmlChar *name, const xmlChar *prefix2, - const xmlChar *name3, - const xmlChar *prefix3); + const xmlChar *name2, + const xmlChar *prefix3, + const xmlChar *name3);
/* * Helpers. */ XMLPUBFUN xmlHashTablePtr - xmlHashCopy (xmlHashTablePtr table, - xmlHashCopier f); + xmlHashCopy (xmlHashTablePtr hash, + xmlHashCopier copy); XMLPUBFUN int - xmlHashSize (xmlHashTablePtr table); + xmlHashSize (xmlHashTablePtr hash); XMLPUBFUN void - xmlHashScan (xmlHashTablePtr table, - xmlHashScanner f, + xmlHashScan (xmlHashTablePtr hash, + xmlHashScanner scan, void *data); XMLPUBFUN void - xmlHashScan3 (xmlHashTablePtr table, + xmlHashScan3 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, - xmlHashScanner f, + xmlHashScanner scan, void *data); XMLPUBFUN void - xmlHashScanFull (xmlHashTablePtr table, - xmlHashScannerFull f, + xmlHashScanFull (xmlHashTablePtr hash, + xmlHashScannerFull scan, void *data); XMLPUBFUN void - xmlHashScanFull3(xmlHashTablePtr table, + xmlHashScanFull3 (xmlHashTablePtr hash, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, - xmlHashScannerFull f, + xmlHashScannerFull scan, void *data); #ifdef __cplusplus } diff --git a/libs/xml2/include/libxml/nanoftp.h b/libs/xml2/include/libxml/nanoftp.h index 87a22aab01f..ed3ac4f1fd2 100644 --- a/libs/xml2/include/libxml/nanoftp.h +++ b/libs/xml2/include/libxml/nanoftp.h @@ -14,7 +14,7 @@
#include <libxml/xmlversion.h>
-#ifdef LIBXML_FTP_ENABLED +#if defined(LIBXML_FTP_ENABLED)
/* Needed for portability to Windows 64 bits */ #if defined(_WIN32) @@ -182,5 +182,5 @@ XMLPUBFUN int #ifdef __cplusplus } #endif -#endif /* LIBXML_FTP_ENABLED */ +#endif /* defined(LIBXML_FTP_ENABLED) || defined(LIBXML_LEGACY_ENABLED) */ #endif /* __NANO_FTP_H__ */ diff --git a/libs/xml2/include/libxml/parser.h b/libs/xml2/include/libxml/parser.h index 950ebe32fdc..87aacef910f 100644 --- a/libs/xml2/include/libxml/parser.h +++ b/libs/xml2/include/libxml/parser.h @@ -11,13 +11,21 @@ #define __XML_PARSER_H__
#include <libxml/xmlversion.h> +#define XML_TREE_INTERNALS #include <libxml/tree.h> +#undef XML_TREE_INTERNALS #include <libxml/dict.h> #include <libxml/hash.h> #include <libxml/valid.h> #include <libxml/entities.h> #include <libxml/xmlerror.h> #include <libxml/xmlstring.h> +#include <libxml/xmlmemory.h> +#include <libxml/encoding.h> +#include <libxml/xmlIO.h> +/* for compatibility */ +#include <libxml/SAX2.h> +#include <libxml/threads.h>
#ifdef __cplusplus extern "C" { @@ -63,9 +71,9 @@ struct _xmlParserInput { int col; /* Current column */ unsigned long consumed; /* How many xmlChars already consumed */ xmlParserInputDeallocate free; /* function to deallocate the base */ - const xmlChar *encoding; /* the encoding string for entity */ + const xmlChar *encoding; /* unused */ const xmlChar *version; /* the version string for entity */ - int standalone; /* Was that entity marked standalone */ + int flags; /* Flags */ int id; /* an unique identifier for the entity */ unsigned long parentConsumed; /* consumed bytes from parents */ xmlEntityPtr entity; /* entity, if any */ @@ -122,7 +130,8 @@ typedef enum { XML_PARSER_SYSTEM_LITERAL, /* within a SYSTEM value */ XML_PARSER_EPILOG, /* the Misc* after the last end tag */ XML_PARSER_IGNORE, /* within an IGNORED section */ - XML_PARSER_PUBLIC_LITERAL /* within a PUBLIC value */ + XML_PARSER_PUBLIC_LITERAL, /* within a PUBLIC value */ + XML_PARSER_XML_DECL /* before XML decl (but after BOM) */ } xmlParserInputState;
/** @@ -165,6 +174,8 @@ typedef enum { } xmlParserMode;
typedef struct _xmlStartTag xmlStartTag; +typedef struct _xmlParserNsData xmlParserNsData; +typedef struct _xmlAttrHashBucket xmlAttrHashBucket;
/** * xmlParserCtxt: @@ -245,8 +256,7 @@ struct _xmlParserCtxt {
int depth; /* to prevent entity substitution loops */ xmlParserInputPtr entity; /* used to check entities boundaries */ - int charset; /* encoding of the in-memory content - actually an xmlCharEncoding */ + int charset; /* unused */ int nodelen; /* Those two fields are there to */ int nodemem; /* Speed up large node parsing */ int pedantic; /* signal pedantic warnings */ @@ -276,7 +286,7 @@ struct _xmlParserCtxt { int nsNr; /* the number of inherited namespaces */ int nsMax; /* the size of the arrays */ const xmlChar * *nsTab; /* the array of prefix/namespace name */ - int *attallocs; /* which attribute were allocated */ + unsigned *attallocs; /* which attribute were allocated */ xmlStartTag *pushTab; /* array of data for push */ xmlHashTablePtr attsDefault; /* defaulted attributes if any */ xmlHashTablePtr attsSpecial; /* non-CDATA attributes if any */ @@ -312,6 +322,11 @@ struct _xmlParserCtxt { int endCheckState; /* quote state for push parser */ unsigned short nbErrors; /* number of errors */ unsigned short nbWarnings; /* number of warnings */ + unsigned maxAmpl; /* maximum amplification factor */ + + xmlParserNsData *nsdb; /* namespace database */ + unsigned attrHashMax; /* allocated size */ + xmlAttrHashBucket *attrHash; /* atttribute hash table */ };
/** @@ -732,6 +747,19 @@ struct _xmlSAXHandler { setDocumentLocatorSAXFunc setDocumentLocator; startDocumentSAXFunc startDocument; endDocumentSAXFunc endDocument; + /* + * `startElement` and `endElement` are only used by the legacy SAX1 + * interface and should not be used in new software. If you really + * have to enable SAX1, the preferred way is set the `initialized` + * member to 1 instead of XML_SAX2_MAGIC. + * + * For backward compatibility, it's also possible to set the + * `startElementNs` and `endElementNs` handlers to NULL. + * + * You can also set the XML_PARSE_SAX1 parser option, but versions + * older than 2.12.0 will probably crash if this option is provided + * together with custom SAX callbacks. + */ startElementSAXFunc startElement; endElementSAXFunc endElement; referenceSAXFunc reference; @@ -745,8 +773,14 @@ struct _xmlSAXHandler { getParameterEntitySAXFunc getParameterEntity; cdataBlockSAXFunc cdataBlock; externalSubsetSAXFunc externalSubset; + /* + * `initialized` should always be set to XML_SAX2_MAGIC to enable the + * modern SAX2 interface. + */ unsigned int initialized; - /* The following fields are extensions available only on version 2 */ + /* + * The following members are only used by the SAX2 interface. + */ void *_private; startElementNsSAX2Func startElementNs; endElementNsSAX2Func endElementNs; @@ -804,18 +838,78 @@ typedef xmlParserInputPtr (*xmlExternalEntityLoader) (const char *URL, const char *ID, xmlParserCtxtPtr context);
-#ifdef __cplusplus -} +/* + * Variables + */ + +XMLPUBVAR const char *const xmlParserVersion; +#ifdef LIBXML_THREAD_ENABLED +/* backward compatibility */ +XMLPUBFUN const char *const *__xmlParserVersion(void); #endif
-#include <libxml/encoding.h> -#include <libxml/xmlIO.h> -#include <libxml/globals.h> +/** DOC_DISABLE */ +#define XML_GLOBALS_PARSER_CORE \ + XML_OP(oldXMLWDcompatibility, int, XML_DEPRECATED) \ + XML_OP(xmlDefaultSAXLocator, xmlSAXLocator, XML_DEPRECATED) \ + XML_OP(xmlDoValidityCheckingDefaultValue, int, XML_DEPRECATED) \ + XML_OP(xmlGetWarningsDefaultValue, int, XML_DEPRECATED) \ + XML_OP(xmlKeepBlanksDefaultValue, int, XML_DEPRECATED) \ + XML_OP(xmlLineNumbersDefaultValue, int, XML_DEPRECATED) \ + XML_OP(xmlLoadExtDtdDefaultValue, int, XML_DEPRECATED) \ + XML_OP(xmlParserDebugEntities, int, XML_DEPRECATED) \ + XML_OP(xmlPedanticParserDefaultValue, int, XML_DEPRECATED) \ + XML_OP(xmlSubstituteEntitiesDefaultValue, int, XML_DEPRECATED) + +#ifdef LIBXML_OUTPUT_ENABLED + #define XML_GLOBALS_PARSER_OUTPUT \ + XML_OP(xmlIndentTreeOutput, int, XML_NO_ATTR) \ + XML_OP(xmlTreeIndentString, const char *, XML_NO_ATTR) \ + XML_OP(xmlSaveNoEmptyTags, int, XML_NO_ATTR) +#else + #define XML_GLOBALS_PARSER_OUTPUT +#endif
-#ifdef __cplusplus -extern "C" { +#ifdef LIBXML_SAX1_ENABLED + #define XML_GLOBALS_PARSER_SAX1 \ + XML_OP(xmlDefaultSAXHandler, xmlSAXHandlerV1, XML_DEPRECATED) +#else + #define XML_GLOBALS_PARSER_SAX1 #endif
+#define XML_GLOBALS_PARSER \ + XML_GLOBALS_PARSER_CORE \ + XML_GLOBALS_PARSER_OUTPUT \ + XML_GLOBALS_PARSER_SAX1 + +#define XML_OP XML_DECLARE_GLOBAL +XML_GLOBALS_PARSER +#undef XML_OP + +#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) + #define oldXMLWDcompatibility XML_GLOBAL_MACRO(oldXMLWDcompatibility) + #define xmlDefaultSAXHandler XML_GLOBAL_MACRO(xmlDefaultSAXHandler) + #define xmlDefaultSAXLocator XML_GLOBAL_MACRO(xmlDefaultSAXLocator) + #define xmlDoValidityCheckingDefaultValue \ + XML_GLOBAL_MACRO(xmlDoValidityCheckingDefaultValue) + #define xmlGetWarningsDefaultValue \ + XML_GLOBAL_MACRO(xmlGetWarningsDefaultValue) + #define xmlKeepBlanksDefaultValue XML_GLOBAL_MACRO(xmlKeepBlanksDefaultValue) + #define xmlLineNumbersDefaultValue \ + XML_GLOBAL_MACRO(xmlLineNumbersDefaultValue) + #define xmlLoadExtDtdDefaultValue XML_GLOBAL_MACRO(xmlLoadExtDtdDefaultValue) + #define xmlParserDebugEntities XML_GLOBAL_MACRO(xmlParserDebugEntities) + #define xmlPedanticParserDefaultValue \ + XML_GLOBAL_MACRO(xmlPedanticParserDefaultValue) + #define xmlSubstituteEntitiesDefaultValue \ + XML_GLOBAL_MACRO(xmlSubstituteEntitiesDefaultValue) + #ifdef LIBXML_OUTPUT_ENABLED + #define xmlIndentTreeOutput XML_GLOBAL_MACRO(xmlIndentTreeOutput) + #define xmlTreeIndentString XML_GLOBAL_MACRO(xmlTreeIndentString) + #define xmlSaveNoEmptyTags XML_GLOBAL_MACRO(xmlSaveNoEmptyTags) + #endif +#endif +/** DOC_ENABLE */
/* * Init/Cleanup @@ -824,6 +918,12 @@ XMLPUBFUN void xmlInitParser (void); XMLPUBFUN void xmlCleanupParser (void); +XML_DEPRECATED +XMLPUBFUN void + xmlInitGlobals (void); +XML_DEPRECATED +XMLPUBFUN void + xmlCleanupGlobals (void);
/* * Input functions @@ -849,16 +949,32 @@ XMLPUBFUN xmlDocPtr xmlParseMemory (const char *buffer, int size); #endif /* LIBXML_SAX1_ENABLED */ -XMLPUBFUN int +XML_DEPRECATED XMLPUBFUN int xmlSubstituteEntitiesDefault(int val); -XMLPUBFUN int +XML_DEPRECATED XMLPUBFUN int + xmlThrDefSubstituteEntitiesDefaultValue(int v); +XML_DEPRECATED XMLPUBFUN int xmlKeepBlanksDefault (int val); +XML_DEPRECATED XMLPUBFUN int + xmlThrDefKeepBlanksDefaultValue(int v); XMLPUBFUN void xmlStopParser (xmlParserCtxtPtr ctxt); -XMLPUBFUN int +XML_DEPRECATED XMLPUBFUN int xmlPedanticParserDefault(int val); -XMLPUBFUN int +XML_DEPRECATED XMLPUBFUN int + xmlThrDefPedanticParserDefaultValue(int v); +XML_DEPRECATED XMLPUBFUN int xmlLineNumbersDefault (int val); +XML_DEPRECATED XMLPUBFUN int + xmlThrDefLineNumbersDefaultValue(int v); +XML_DEPRECATED XMLPUBFUN int + xmlThrDefDoValidityCheckingDefaultValue(int v); +XML_DEPRECATED XMLPUBFUN int + xmlThrDefGetWarningsDefaultValue(int v); +XML_DEPRECATED XMLPUBFUN int + xmlThrDefLoadExtDtdDefaultValue(int v); +XML_DEPRECATED XMLPUBFUN int + xmlThrDefParserDebugEntities(int v);
#ifdef LIBXML_SAX1_ENABLED /* @@ -1149,6 +1265,9 @@ XMLPUBFUN int XMLPUBFUN int xmlCtxtUseOptions (xmlParserCtxtPtr ctxt, int options); +XMLPUBFUN void + xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, + unsigned maxAmpl); XMLPUBFUN xmlDocPtr xmlReadDoc (const xmlChar *cur, const char *URL, diff --git a/libs/xml2/include/libxml/parserInternals.h b/libs/xml2/include/libxml/parserInternals.h index 513981eaf12..017ed27358a 100644 --- a/libs/xml2/include/libxml/parserInternals.h +++ b/libs/xml2/include/libxml/parserInternals.h @@ -16,6 +16,7 @@ #include <libxml/parser.h> #include <libxml/HTMLparser.h> #include <libxml/chvalid.h> +#include <libxml/SAX2.h>
#ifdef __cplusplus extern "C" { diff --git a/libs/xml2/include/libxml/relaxng.h b/libs/xml2/include/libxml/relaxng.h index aecaea309ba..079b7f125d0 100644 --- a/libs/xml2/include/libxml/relaxng.h +++ b/libs/xml2/include/libxml/relaxng.h @@ -11,8 +11,9 @@ #define __XML_RELAX_NG__
#include <libxml/xmlversion.h> -#include <libxml/hash.h> +#include <libxml/xmlerror.h> #include <libxml/xmlstring.h> +#include <libxml/tree.h>
#ifdef LIBXML_SCHEMAS_ENABLED
diff --git a/libs/xml2/include/libxml/schemasInternals.h b/libs/xml2/include/libxml/schemasInternals.h index 5806f0182c7..e9d3b3c7abb 100644 --- a/libs/xml2/include/libxml/schemasInternals.h +++ b/libs/xml2/include/libxml/schemasInternals.h @@ -21,6 +21,7 @@ #include <libxml/xmlregexp.h> #include <libxml/hash.h> #include <libxml/dict.h> +#include <libxml/tree.h>
#ifdef __cplusplus extern "C" { diff --git a/libs/xml2/include/libxml/threads.h b/libs/xml2/include/libxml/threads.h index dd2304cc4a2..8f4b6e174fb 100644 --- a/libs/xml2/include/libxml/threads.h +++ b/libs/xml2/include/libxml/threads.h @@ -29,13 +29,9 @@ typedef xmlMutex *xmlMutexPtr; typedef struct _xmlRMutex xmlRMutex; typedef xmlRMutex *xmlRMutexPtr;
-#ifdef __cplusplus -} -#endif -#include <libxml/globals.h> -#ifdef __cplusplus -extern "C" { -#endif +XMLPUBFUN int + xmlCheckThreadLocalStorage(void); + XMLPUBFUN xmlMutexPtr xmlNewMutex (void); XMLPUBFUN void @@ -73,13 +69,10 @@ XMLPUBFUN int XML_DEPRECATED XMLPUBFUN void xmlCleanupThreads(void); -XML_DEPRECATED -XMLPUBFUN xmlGlobalStatePtr - xmlGetGlobalState(void);
/** DOC_DISABLE */ #if defined(LIBXML_THREAD_ENABLED) && defined(_WIN32) && \ - !defined(HAVE_COMPILER_TLS) && defined(LIBXML_STATIC_FOR_DLL) + defined(LIBXML_STATIC_FOR_DLL) int xmlDllMain(void *hinstDLL, unsigned long fdwReason, void *lpvReserved); diff --git a/libs/xml2/include/libxml/tree.h b/libs/xml2/include/libxml/tree.h index b4989667ab1..61c1ed49d95 100644 --- a/libs/xml2/include/libxml/tree.h +++ b/libs/xml2/include/libxml/tree.h @@ -9,6 +9,15 @@ * Author: Daniel Veillard */
+#ifndef XML_TREE_INTERNALS + +/* + * Emulate circular dependency for backward compatibility + */ +#include <libxml/parser.h> + +#else /* XML_TREE_INTERNALS */ + #ifndef __XML_TREE_H__ #define __XML_TREE_H__
@@ -16,6 +25,8 @@ #include <limits.h> #include <libxml/xmlversion.h> #include <libxml/xmlstring.h> +#include <libxml/xmlmemory.h> +#include <libxml/xmlregexp.h>
#ifdef __cplusplus extern "C" { @@ -329,14 +340,6 @@ typedef enum { XML_ELEMENT_TYPE_ELEMENT } xmlElementTypeVal;
-#ifdef __cplusplus -} -#endif -#include <libxml/xmlregexp.h> -#ifdef __cplusplus -extern "C" { -#endif - /** * xmlElement: * @@ -573,12 +576,11 @@ struct _xmlDoc { struct _xmlDtd *extSubset; /* the document external subset */ struct _xmlNs *oldNs; /* Global namespace, the old way */ const xmlChar *version; /* the XML version string */ - const xmlChar *encoding; /* external initial encoding, if any */ + const xmlChar *encoding; /* actual encoding, if any */ void *ids; /* Hash table for ID attributes if any */ void *refs; /* Hash table for IDREFs attributes if any */ const xmlChar *URL; /* The URI for that document */ - int charset; /* Internal flag for charset handling, - actually an xmlCharEncoding */ + int charset; /* unused */ struct _xmlDict *dict; /* dict used to allocate names or NULL */ void *psvi; /* for type/PSVI information */ int parseFlags; /* set of xmlParserOption used to parse the @@ -630,6 +632,22 @@ struct _xmlDOMWrapCtxt { xmlDOMWrapAcquireNsFunction getNsForNodeFunc; };
+/** + * xmlRegisterNodeFunc: + * @node: the current node + * + * Signature for the registration callback of a created node + */ +typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node); + +/** + * xmlDeregisterNodeFunc: + * @node: the current node + * + * Signature for the deregistration callback of a discarded node + */ +typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node); + /** * xmlChildrenNode: * @@ -654,18 +672,34 @@ struct _xmlDOMWrapCtxt { * Variables. */
+/** DOC_DISABLE */ +#define XML_GLOBALS_TREE \ + XML_OP(xmlBufferAllocScheme, xmlBufferAllocationScheme, XML_DEPRECATED) \ + XML_OP(xmlDefaultBufferSize, int, XML_DEPRECATED) \ + XML_OP(xmlRegisterNodeDefaultValue, xmlRegisterNodeFunc, XML_DEPRECATED) \ + XML_OP(xmlDeregisterNodeDefaultValue, xmlDeregisterNodeFunc, \ + XML_DEPRECATED) + +#define XML_OP XML_DECLARE_GLOBAL +XML_GLOBALS_TREE +#undef XML_OP + +#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) + #define xmlBufferAllocScheme XML_GLOBAL_MACRO(xmlBufferAllocScheme) + #define xmlDefaultBufferSize XML_GLOBAL_MACRO(xmlDefaultBufferSize) + #define xmlRegisterNodeDefaultValue \ + XML_GLOBAL_MACRO(xmlRegisterNodeDefaultValue) + #define xmlDeregisterNodeDefaultValue \ + XML_GLOBAL_MACRO(xmlDeregisterNodeDefaultValue) +#endif +/** DOC_ENABLE */ + /* * Some helper functions */ -#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || \ - defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || \ - defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || \ - defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || \ - defined(LIBXML_LEGACY_ENABLED) XMLPUBFUN int xmlValidateNCName (const xmlChar *value, int space); -#endif
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN int @@ -1303,12 +1337,25 @@ XMLPUBFUN xmlNodePtr XMLPUBFUN xmlNodePtr xmlPreviousElementSibling (xmlNodePtr node); #endif + +XMLPUBFUN xmlRegisterNodeFunc + xmlRegisterNodeDefault (xmlRegisterNodeFunc func); +XMLPUBFUN xmlDeregisterNodeFunc + xmlDeregisterNodeDefault (xmlDeregisterNodeFunc func); +XMLPUBFUN xmlRegisterNodeFunc + xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func); +XMLPUBFUN xmlDeregisterNodeFunc + xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func); + +XML_DEPRECATED XMLPUBFUN xmlBufferAllocationScheme + xmlThrDefBufferAllocScheme (xmlBufferAllocationScheme v); +XML_DEPRECATED XMLPUBFUN int + xmlThrDefDefaultBufferSize (int v); + #ifdef __cplusplus } #endif -#ifndef __XML_PARSER_H__ -#include <libxml/xmlmemory.h> -#endif
#endif /* __XML_TREE_H__ */
+#endif /* XML_TREE_INTERNALS */ diff --git a/libs/xml2/include/libxml/uri.h b/libs/xml2/include/libxml/uri.h index 0470a5d9f8d..eb8631cf081 100644 --- a/libs/xml2/include/libxml/uri.h +++ b/libs/xml2/include/libxml/uri.h @@ -11,8 +11,9 @@ #ifndef __XML_URI_H__ #define __XML_URI_H__
+#include <stdio.h> #include <libxml/xmlversion.h> -#include <libxml/tree.h> +#include <libxml/xmlstring.h>
#ifdef __cplusplus extern "C" { diff --git a/libs/xml2/include/libxml/valid.h b/libs/xml2/include/libxml/valid.h index b19cbacb9f5..3e04b55217c 100644 --- a/libs/xml2/include/libxml/valid.h +++ b/libs/xml2/include/libxml/valid.h @@ -13,7 +13,9 @@
#include <libxml/xmlversion.h> #include <libxml/xmlerror.h> +#define XML_TREE_INTERNALS #include <libxml/tree.h> +#undef XML_TREE_INTERNALS #include <libxml/list.h> #include <libxml/xmlautomata.h> #include <libxml/xmlregexp.h> diff --git a/libs/xml2/include/libxml/xmlIO.h b/libs/xml2/include/libxml/xmlIO.h index 55d25ed915c..2487be3be0d 100644 --- a/libs/xml2/include/libxml/xmlIO.h +++ b/libs/xml2/include/libxml/xmlIO.h @@ -12,6 +12,10 @@
#include <stdio.h> #include <libxml/xmlversion.h> +#include <libxml/encoding.h> +#define XML_TREE_INTERNALS +#include <libxml/tree.h> +#undef XML_TREE_INTERNALS
#ifdef __cplusplus extern "C" { @@ -110,18 +114,35 @@ typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer, typedef int (*xmlOutputCloseCallback) (void * context); #endif /* LIBXML_OUTPUT_ENABLED */
-#ifdef __cplusplus -} -#endif +/** + * xmlParserInputBufferCreateFilenameFunc: + * @URI: the URI to read from + * @enc: the requested source encoding + * + * Signature for the function doing the lookup for a suitable input method + * corresponding to an URI. + * + * Returns the new xmlParserInputBufferPtr in case of success or NULL if no + * method was found. + */ +typedef xmlParserInputBufferPtr +(*xmlParserInputBufferCreateFilenameFunc)(const char *URI, xmlCharEncoding enc);
-#include <libxml/globals.h> -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/encoding.h> +/** + * xmlOutputBufferCreateFilenameFunc: + * @URI: the URI to write to + * @enc: the requested target encoding + * + * Signature for the function doing the lookup for a suitable output method + * corresponding to an URI. + * + * Returns the new xmlOutputBufferPtr in case of success or NULL if no + * method was found. + */ +typedef xmlOutputBufferPtr +(*xmlOutputBufferCreateFilenameFunc)(const char *URI, + xmlCharEncodingHandlerPtr encoder, int compression);
-#ifdef __cplusplus -extern "C" { -#endif struct _xmlParserInputBuffer { void* context; xmlInputReadCallback readcallback; @@ -152,6 +173,25 @@ struct _xmlOutputBuffer { }; #endif /* LIBXML_OUTPUT_ENABLED */
+/** DOC_DISABLE */ +#define XML_GLOBALS_IO \ + XML_OP(xmlParserInputBufferCreateFilenameValue, \ + xmlParserInputBufferCreateFilenameFunc, XML_DEPRECATED) \ + XML_OP(xmlOutputBufferCreateFilenameValue, \ + xmlOutputBufferCreateFilenameFunc, XML_DEPRECATED) + +#define XML_OP XML_DECLARE_GLOBAL +XML_GLOBALS_IO +#undef XML_OP + +#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) + #define xmlParserInputBufferCreateFilenameValue \ + XML_GLOBAL_MACRO(xmlParserInputBufferCreateFilenameValue) + #define xmlOutputBufferCreateFilenameValue \ + XML_GLOBAL_MACRO(xmlOutputBufferCreateFilenameValue) +#endif +/** DOC_ENABLE */ + /* * Interfaces for input */ @@ -178,7 +218,6 @@ XMLPUBFUN xmlParserInputBufferPtr XMLPUBFUN xmlParserInputBufferPtr xmlParserInputBufferCreateMem (const char *mem, int size, xmlCharEncoding enc); -XML_DEPRECATED XMLPUBFUN xmlParserInputBufferPtr xmlParserInputBufferCreateStatic (const char *mem, int size, xmlCharEncoding enc); @@ -349,7 +388,7 @@ XMLPUBFUN int /** * Default 'ftp://' protocol callbacks */ -#ifdef LIBXML_FTP_ENABLED +#if defined(LIBXML_FTP_ENABLED) XMLPUBFUN int xmlIOFTPMatch (const char *filename); XMLPUBFUN void * @@ -360,7 +399,20 @@ XMLPUBFUN int int len); XMLPUBFUN int xmlIOFTPClose (void * context); -#endif /* LIBXML_FTP_ENABLED */ +#endif /* defined(LIBXML_FTP_ENABLED) */ + +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc + xmlParserInputBufferCreateFilenameDefault( + xmlParserInputBufferCreateFilenameFunc func); +XMLPUBFUN xmlOutputBufferCreateFilenameFunc + xmlOutputBufferCreateFilenameDefault( + xmlOutputBufferCreateFilenameFunc func); +XMLPUBFUN xmlOutputBufferCreateFilenameFunc + xmlThrDefOutputBufferCreateFilenameDefault( + xmlOutputBufferCreateFilenameFunc func); +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc + xmlThrDefParserInputBufferCreateFilenameDefault( + xmlParserInputBufferCreateFilenameFunc func);
#ifdef __cplusplus } diff --git a/libs/xml2/include/libxml/xmlerror.h b/libs/xml2/include/libxml/xmlerror.h index 830b4a68108..1f0ab4a3a2f 100644 --- a/libs/xml2/include/libxml/xmlerror.h +++ b/libs/xml2/include/libxml/xmlerror.h @@ -7,11 +7,11 @@ * Author: Daniel Veillard */
-#include <libxml/parser.h> - #ifndef __XML_ERROR_H__ #define __XML_ERROR_H__
+#include <libxml/xmlversion.h> + #ifdef __cplusplus extern "C" { #endif @@ -210,6 +210,7 @@ typedef enum { XML_ERR_NAME_TOO_LONG, /* 110 */ XML_ERR_USER_STOP, /* 111 */ XML_ERR_COMMENT_ABRUPTLY_ENDED, /* 112 */ + XML_WAR_ENCODING_MISMATCH, /* 113 */ XML_NS_ERR_XML_NAMESPACE = 200, XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */ XML_NS_ERR_QNAME, /* 202 */ @@ -855,7 +856,28 @@ typedef void (*xmlGenericErrorFunc) (void *ctx, * Signature of the function to use when there is an error and * the module handles the new error reporting mechanism. */ -typedef void (*xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error); +typedef void (*xmlStructuredErrorFunc) (void *userData, const xmlError *error); + +/** DOC_DISABLE */ +#define XML_GLOBALS_ERROR \ + XML_OP(xmlLastError, xmlError, XML_DEPRECATED) \ + XML_OP(xmlGenericError, xmlGenericErrorFunc, XML_NO_ATTR) \ + XML_OP(xmlGenericErrorContext, void *, XML_NO_ATTR) \ + XML_OP(xmlStructuredError, xmlStructuredErrorFunc, XML_NO_ATTR) \ + XML_OP(xmlStructuredErrorContext, void *, XML_NO_ATTR) + +#define XML_OP XML_DECLARE_GLOBAL +XML_GLOBALS_ERROR +#undef XML_OP + +#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) + #define xmlLastError XML_GLOBAL_MACRO(xmlLastError) + #define xmlGenericError XML_GLOBAL_MACRO(xmlGenericError) + #define xmlGenericErrorContext XML_GLOBAL_MACRO(xmlGenericErrorContext) + #define xmlStructuredError XML_GLOBAL_MACRO(xmlStructuredError) + #define xmlStructuredErrorContext XML_GLOBAL_MACRO(xmlStructuredErrorContext) +#endif +/** DOC_ENABLE */
/* * Use the following function to reset the two global variables @@ -864,6 +886,9 @@ typedef void (*xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error); XMLPUBFUN void xmlSetGenericErrorFunc (void *ctx, xmlGenericErrorFunc handler); +XMLPUBFUN void + xmlThrDefSetGenericErrorFunc(void *ctx, + xmlGenericErrorFunc handler); XML_DEPRECATED XMLPUBFUN void initGenericErrorDefaultFunc (xmlGenericErrorFunc *handler); @@ -871,6 +896,9 @@ XMLPUBFUN void XMLPUBFUN void xmlSetStructuredErrorFunc (void *ctx, xmlStructuredErrorFunc handler); +XMLPUBFUN void + xmlThrDefSetStructuredErrorFunc(void *ctx, + xmlStructuredErrorFunc handler); /* * Default message routines used by SAX and Valid context for error * and warning reporting. @@ -891,26 +919,27 @@ XMLPUBFUN void xmlParserValidityWarning (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); +struct _xmlParserInput; XMLPUBFUN void - xmlParserPrintFileInfo (xmlParserInputPtr input); + xmlParserPrintFileInfo (struct _xmlParserInput *input); XMLPUBFUN void - xmlParserPrintFileContext (xmlParserInputPtr input); + xmlParserPrintFileContext (struct _xmlParserInput *input);
/* * Extended error information routines */ -XMLPUBFUN xmlErrorPtr +XMLPUBFUN const xmlError * xmlGetLastError (void); XMLPUBFUN void xmlResetLastError (void); -XMLPUBFUN xmlErrorPtr +XMLPUBFUN const xmlError * xmlCtxtGetLastError (void *ctx); XMLPUBFUN void xmlCtxtResetLastError (void *ctx); XMLPUBFUN void xmlResetError (xmlErrorPtr err); XMLPUBFUN int - xmlCopyError (xmlErrorPtr from, + xmlCopyError (const xmlError *from, xmlErrorPtr to);
#ifdef __cplusplus diff --git a/libs/xml2/include/libxml/xmlmemory.h b/libs/xml2/include/libxml/xmlmemory.h index 830933a77bb..dac3b804f45 100644 --- a/libs/xml2/include/libxml/xmlmemory.h +++ b/libs/xml2/include/libxml/xmlmemory.h @@ -15,32 +15,6 @@ #include <stdio.h> #include <libxml/xmlversion.h>
-/** - * DEBUG_MEMORY: - * - * DEBUG_MEMORY replaces the allocator with a collect and debug - * shell to the libc allocator. - * DEBUG_MEMORY should only be activated when debugging - * libxml i.e. if libxml has been configured with --with-debug-mem too. - */ -/* #define DEBUG_MEMORY_FREED */ -/* #define DEBUG_MEMORY_LOCATION */ - -#ifdef DEBUG -#ifndef DEBUG_MEMORY -#define DEBUG_MEMORY -#endif -#endif - -/** - * DEBUG_MEMORY_LOCATION: - * - * DEBUG_MEMORY_LOCATION should be activated only when debugging - * libxml i.e. if libxml has been configured with --with-debug-mem too. - */ -#ifdef DEBUG_MEMORY_LOCATION -#endif - #ifdef __cplusplus extern "C" { #endif @@ -87,13 +61,41 @@ typedef void *(*xmlReallocFunc)(void *mem, size_t size); typedef char *(*xmlStrdupFunc)(const char *str);
/* - * The 4 interfaces used for all memory handling within libxml. -LIBXML_DLL_IMPORT xmlFreeFunc xmlFree; -LIBXML_DLL_IMPORT xmlMallocFunc xmlMalloc; -LIBXML_DLL_IMPORT xmlMallocFunc xmlMallocAtomic; -LIBXML_DLL_IMPORT xmlReallocFunc xmlRealloc; -LIBXML_DLL_IMPORT xmlStrdupFunc xmlMemStrdup; - */ + * In general the memory allocation entry points are not kept + * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED + * - xmlMalloc + * - xmlMallocAtomic + * - xmlRealloc + * - xmlMemStrdup + * - xmlFree + */ +/** DOC_DISABLE */ +#ifdef LIBXML_THREAD_ALLOC_ENABLED + #define XML_GLOBALS_ALLOC \ + XML_OP(xmlMalloc, xmlMallocFunc, XML_NO_ATTR) \ + XML_OP(xmlMallocAtomic, xmlMallocFunc, XML_NO_ATTR) \ + XML_OP(xmlRealloc, xmlReallocFunc, XML_NO_ATTR) \ + XML_OP(xmlFree, xmlFreeFunc, XML_NO_ATTR) \ + XML_OP(xmlMemStrdup, xmlStrdupFunc, XML_NO_ATTR) + #define XML_OP XML_DECLARE_GLOBAL + XML_GLOBALS_ALLOC + #undef XML_OP + #if defined(LIBXML_THREAD_ENABLED) && !defined(XML_GLOBALS_NO_REDEFINITION) + #define xmlMalloc XML_GLOBAL_MACRO(xmlMalloc) + #define xmlMallocAtomic XML_GLOBAL_MACRO(xmlMallocAtomic) + #define xmlRealloc XML_GLOBAL_MACRO(xmlRealloc) + #define xmlFree XML_GLOBAL_MACRO(xmlFree) + #define xmlMemStrdup XML_GLOBAL_MACRO(xmlMemStrdup) + #endif +#else + #define XML_GLOBALS_ALLOC +/** DOC_ENABLE */ + XMLPUBVAR xmlMallocFunc xmlMalloc; + XMLPUBVAR xmlMallocFunc xmlMallocAtomic; + XMLPUBVAR xmlReallocFunc xmlRealloc; + XMLPUBVAR xmlFreeFunc xmlFree; + XMLPUBVAR xmlStrdupFunc xmlMemStrdup; +#endif
/* * The way to overload the existing functions. @@ -171,6 +173,7 @@ XMLPUBFUN char * xmlMemStrdupLoc (const char *str, const char *file, int line);
+/** DOC_DISABLE */ #ifdef DEBUG_MEMORY_LOCATION /** * xmlMalloc: @@ -212,17 +215,10 @@ XMLPUBFUN char * #define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__)
#endif /* DEBUG_MEMORY_LOCATION */ +/** DOC_ENABLE */
#ifdef __cplusplus } #endif /* __cplusplus */
-#ifndef __XML_GLOBALS_H -#ifndef __XML_THREADS_H__ -#include <libxml/threads.h> -#include <libxml/globals.h> -#endif -#endif - #endif /* __DEBUG_MEMORY_ALLOC__ */ - diff --git a/libs/xml2/include/libxml/xmlreader.h b/libs/xml2/include/libxml/xmlreader.h index 1ac151040e8..514f74e6572 100644 --- a/libs/xml2/include/libxml/xmlreader.h +++ b/libs/xml2/include/libxml/xmlreader.h @@ -12,11 +12,14 @@
#include <libxml/xmlversion.h> #include <libxml/tree.h> +#include <libxml/xmlerror.h> #include <libxml/xmlIO.h> #ifdef LIBXML_SCHEMAS_ENABLED #include <libxml/relaxng.h> #include <libxml/xmlschemas.h> #endif +/* for compatibility */ +#include <libxml/parser.h>
#ifdef __cplusplus extern "C" { @@ -121,6 +124,9 @@ XMLPUBFUN int xmlTextReaderSetup(xmlTextReaderPtr reader, xmlParserInputBufferPtr input, const char *URL, const char *encoding, int options); +XMLPUBFUN void + xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, + unsigned maxAmpl);
/* * Iterators @@ -425,4 +431,3 @@ XMLPUBFUN void #endif
#endif /* __XML_XMLREADER_H__ */ - diff --git a/libs/xml2/include/libxml/xmlregexp.h b/libs/xml2/include/libxml/xmlregexp.h index 39a72ab3399..2d66437a55b 100644 --- a/libs/xml2/include/libxml/xmlregexp.h +++ b/libs/xml2/include/libxml/xmlregexp.h @@ -11,7 +11,9 @@ #ifndef __XML_REGEXP_H__ #define __XML_REGEXP_H__
+#include <stdio.h> #include <libxml/xmlversion.h> +#include <libxml/xmlstring.h>
#ifdef LIBXML_REGEXP_ENABLED
@@ -36,15 +38,6 @@ typedef xmlRegexp *xmlRegexpPtr; typedef struct _xmlRegExecCtxt xmlRegExecCtxt; typedef xmlRegExecCtxt *xmlRegExecCtxtPtr;
-#ifdef __cplusplus -} -#endif -#include <libxml/tree.h> -#include <libxml/dict.h> -#ifdef __cplusplus -extern "C" { -#endif - /* * The POSIX like API */ diff --git a/libs/xml2/include/libxml/xmlsave.h b/libs/xml2/include/libxml/xmlsave.h index a744b7ac276..ec2ba53c653 100644 --- a/libs/xml2/include/libxml/xmlsave.h +++ b/libs/xml2/include/libxml/xmlsave.h @@ -79,10 +79,17 @@ XMLPUBFUN int XMLPUBFUN int xmlSaveSetAttrEscape (xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape); + +XMLPUBFUN int + xmlThrDefIndentTreeOutput(int v); +XMLPUBFUN const char * + xmlThrDefTreeIndentString(const char * v); +XMLPUBFUN int + xmlThrDefSaveNoEmptyTags(int v); + #ifdef __cplusplus } #endif + #endif /* LIBXML_OUTPUT_ENABLED */ #endif /* __XML_XMLSAVE_H__ */ - - diff --git a/libs/xml2/include/libxml/xmlschemas.h b/libs/xml2/include/libxml/xmlschemas.h index 4d61ad0d3d3..c2af3d7098b 100644 --- a/libs/xml2/include/libxml/xmlschemas.h +++ b/libs/xml2/include/libxml/xmlschemas.h @@ -16,7 +16,10 @@
#ifdef LIBXML_SCHEMAS_ENABLED
+#include <stdio.h> +#include <libxml/encoding.h> #include <libxml/tree.h> +#include <libxml/xmlerror.h>
#ifdef __cplusplus extern "C" { diff --git a/libs/xml2/include/libxml/xmlversion.h b/libs/xml2/include/libxml/xmlversion.h index 6678a7da8e6..2374eaf1aea 100644 --- a/libs/xml2/include/libxml/xmlversion.h +++ b/libs/xml2/include/libxml/xmlversion.h @@ -29,21 +29,21 @@ XMLPUBFUN void xmlCheckVersion(int version); * * the version string like "1.2.3" */ -#define LIBXML_DOTTED_VERSION "2.11.7" +#define LIBXML_DOTTED_VERSION "2.12.8"
/** * LIBXML_VERSION: * * the version number: 1.2.3 value is 10203 */ -#define LIBXML_VERSION 21107 +#define LIBXML_VERSION 21208
/** * LIBXML_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ -#define LIBXML_VERSION_STRING "21107" +#define LIBXML_VERSION_STRING "21208"
/** * LIBXML_VERSION_EXTRA: @@ -58,7 +58,7 @@ XMLPUBFUN void xmlCheckVersion(int version); * Macro to check that the libxml version in use is compatible with * the version the software has been compiled against */ -#define LIBXML_TEST_VERSION xmlCheckVersion(21107); +#define LIBXML_TEST_VERSION xmlCheckVersion(21208);
#ifndef VMS #if 0 @@ -449,43 +449,27 @@ XMLPUBFUN void xmlCheckVersion(int version); #endif
#if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) -#define XML_IGNORE_FPTR_CAST_WARNINGS \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored "-Wpedantic"") \ - _Pragma("GCC diagnostic ignored "-Wcast-function-type"") -#define XML_POP_WARNINGS \ + #if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 800) + #define XML_IGNORE_FPTR_CAST_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored "-Wpedantic"") \ + _Pragma("GCC diagnostic ignored "-Wcast-function-type"") + #else + #define XML_IGNORE_FPTR_CAST_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored "-Wpedantic"") + #endif + #define XML_POP_WARNINGS \ _Pragma("GCC diagnostic pop") #else -#define XML_IGNORE_FPTR_CAST_WARNINGS -#define XML_POP_WARNINGS + #define XML_IGNORE_FPTR_CAST_WARNINGS + #define XML_POP_WARNINGS #endif
-/** DOC_ENABLE */ #else /* ! __GNUC__ */ -/** - * ATTRIBUTE_UNUSED: - * - * Macro used to signal to GCC unused function parameters - */ #define ATTRIBUTE_UNUSED -/** - * LIBXML_ATTR_ALLOC_SIZE: - * - * Macro used to indicate to GCC this is an allocator function - */ #define LIBXML_ATTR_ALLOC_SIZE(x) -/** - * LIBXML_ATTR_FORMAT: - * - * Macro used to indicate to GCC the parameter are printf like - */ #define LIBXML_ATTR_FORMAT(fmt,args) -/** - * XML_DEPRECATED: - * - * Macro used to indicate that a function, variable, type or struct member - * is deprecated. - */ #ifndef XML_DEPRECATED # if defined (IN_LIBXML) || !defined (_MSC_VER) # define XML_DEPRECATED @@ -494,21 +478,11 @@ XMLPUBFUN void xmlCheckVersion(int version); # define XML_DEPRECATED __declspec(deprecated) # endif #endif -/** - * LIBXML_IGNORE_FPTR_CAST_WARNINGS: - * - * Macro used to ignore pointer cast warnings that can't be worked around. - */ #if defined (_MSC_VER) && (_MSC_VER >= 1400) # define XML_IGNORE_FPTR_CAST_WARNINGS __pragma(warning(push)) #else # define XML_IGNORE_FPTR_CAST_WARNINGS #endif -/** - * XML_POP_WARNINGS: - * - * Macro used to restore warnings state. - */ #ifndef XML_POP_WARNINGS # if defined (_MSC_VER) && (_MSC_VER >= 1400) # define XML_POP_WARNINGS __pragma(warning(pop)) @@ -518,6 +492,17 @@ XMLPUBFUN void xmlCheckVersion(int version); #endif #endif /* __GNUC__ */
+#define XML_NO_ATTR + +#ifdef LIBXML_THREAD_ENABLED + #define XML_DECLARE_GLOBAL(name, type, attrs) \ + attrs XMLPUBFUN type *__##name(void); + #define XML_GLOBAL_MACRO(name) (*__##name()) +#else + #define XML_DECLARE_GLOBAL(name, type, attrs) \ + attrs XMLPUBVAR type name; +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/libs/xml2/include/libxml/xpath.h b/libs/xml2/include/libxml/xpath.h index b57985a20f3..6dae0780d83 100644 --- a/libs/xml2/include/libxml/xpath.h +++ b/libs/xml2/include/libxml/xpath.h @@ -400,7 +400,7 @@ struct _xmlXPathParserContext { int xptr; /* it this an XPointer expression */ xmlNodePtr ancestor; /* used for walking preceding axis */
- int valueFrame; /* unused */ + int valueFrame; /* always zero for compatibility */ };
/************************************************************************ diff --git a/libs/xml2/include/libxml/xpathInternals.h b/libs/xml2/include/libxml/xpathInternals.h index cb0991d7f35..d1c90dff2aa 100644 --- a/libs/xml2/include/libxml/xpathInternals.h +++ b/libs/xml2/include/libxml/xpathInternals.h @@ -12,6 +12,7 @@ #ifndef __XML_XPATH_INTERNALS_H__ #define __XML_XPATH_INTERNALS_H__
+#include <stdio.h> #include <libxml/xmlversion.h> #include <libxml/xpath.h>
@@ -297,7 +298,7 @@ XMLPUBFUN void * if (ctxt == NULL) return; \ if (nargs != (x)) \ XP_ERROR(XPATH_INVALID_ARITY); \ - if (ctxt->valueNr < ctxt->valueFrame + (x)) \ + if (ctxt->valueNr < (x)) \ XP_ERROR(XPATH_STACK_ERROR);
/** diff --git a/libs/xml2/include/libxml/xpointer.h b/libs/xml2/include/libxml/xpointer.h index 12ce9edda63..a5260008fc0 100644 --- a/libs/xml2/include/libxml/xpointer.h +++ b/libs/xml2/include/libxml/xpointer.h @@ -28,7 +28,7 @@ extern "C" { #endif
-#ifdef LIBXML_XPTR_LOCS_ENABLED +#if defined(LIBXML_XPTR_LOCS_ENABLED) /* * A Location Set */ @@ -105,7 +105,7 @@ XML_DEPRECATED XMLPUBFUN void xmlXPtrLocationSetRemove (xmlLocationSetPtr cur, int val); -#endif /* LIBXML_XPTR_LOCS_ENABLED */ +#endif /* defined(LIBXML_XPTR_LOCS_ENABLED) */
/* * Functions. @@ -117,7 +117,8 @@ XMLPUBFUN xmlXPathContextPtr XMLPUBFUN xmlXPathObjectPtr xmlXPtrEval (const xmlChar *str, xmlXPathContextPtr ctx); -#ifdef LIBXML_XPTR_LOCS_ENABLED + +#if defined(LIBXML_XPTR_LOCS_ENABLED) XML_DEPRECATED XMLPUBFUN void xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt, @@ -128,7 +129,7 @@ XMLPUBFUN xmlNodePtr XML_DEPRECATED XMLPUBFUN void xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt); -#endif /* LIBXML_XPTR_LOCS_ENABLED */ +#endif /* defined(LIBXML_XPTR_LOCS_ENABLED) */ #ifdef __cplusplus } #endif diff --git a/libs/xml2/include/private/buf.h b/libs/xml2/include/private/buf.h index c18eed42daa..6fef4ce05dd 100644 --- a/libs/xml2/include/private/buf.h +++ b/libs/xml2/include/private/buf.h @@ -61,10 +61,7 @@ xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer);
XML_HIDDEN int xmlBufResetInput(xmlBufPtr buf, xmlParserInputPtr input); -XML_HIDDEN size_t -xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input); XML_HIDDEN int -xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input, - size_t base, size_t cur); +xmlBufUpdateInput(xmlBufPtr buf, xmlParserInputPtr input, size_t pos);
#endif /* XML_BUF_H_PRIVATE__ */ diff --git a/libs/xml2/include/private/dict.h b/libs/xml2/include/private/dict.h index fcc10bac11a..9b0be621adc 100644 --- a/libs/xml2/include/private/dict.h +++ b/libs/xml2/include/private/dict.h @@ -1,11 +1,72 @@ #ifndef XML_DICT_H_PRIVATE__ #define XML_DICT_H_PRIVATE__
-XML_HIDDEN int -__xmlInitializeDict(void); +#include <libxml/dict.h> + +/* + * Values are ANDed with 0xFFFFFFFF to support platforms where + * unsigned is larger than 32 bits. With 32-bit unsigned values, + * modern compilers should optimize the operation away. + */ + +#define HASH_ROL(x,n) ((x) << (n) | ((x) & 0xFFFFFFFF) >> (32 - (n))) +#define HASH_ROR(x,n) (((x) & 0xFFFFFFFF) >> (n) | (x) << (32 - (n))) + +/* + * GoodOAAT: One of a smallest non-multiplicative One-At-a-Time functions + * that passes SMHasher. + * + * Author: Sokolov Yura aka funny-falcon + */ + +#define HASH_INIT(h1, h2, seed) \ + do { \ + h1 = seed ^ 0x3b00; \ + h2 = HASH_ROL(seed, 15); \ + } while (0) + +#define HASH_UPDATE(h1, h2, ch) \ + do { \ + h1 += ch; \ + h1 += h1 << 3; \ + h2 += h1; \ + h2 = HASH_ROL(h2, 7); \ + h2 += h2 << 2; \ + } while (0) + +/* Result is in h2 */ +#define HASH_FINISH(h1, h2) \ + do { \ + h1 ^= h2; \ + h1 += HASH_ROL(h2, 14); \ + h2 ^= h1; h2 += HASH_ROR(h1, 6); \ + h1 ^= h2; h1 += HASH_ROL(h2, 5); \ + h2 ^= h1; h2 += HASH_ROR(h1, 8); \ + h2 &= 0xFFFFFFFF; \ + } while (0) + +typedef struct { + unsigned hashValue; + const xmlChar *name; +} xmlHashedString; + +XML_HIDDEN void +xmlInitDictInternal(void); XML_HIDDEN void xmlCleanupDictInternal(void); -XML_HIDDEN int -__xmlRandom(void); + +XML_HIDDEN unsigned +xmlDictComputeHash(const xmlDict *dict, const xmlChar *string); +XML_HIDDEN unsigned +xmlDictCombineHash(unsigned v1, unsigned v2); +XML_HIDDEN xmlHashedString +xmlDictLookupHashed(xmlDictPtr dict, const xmlChar *name, int len); + +XML_HIDDEN void +xmlInitRandom(void); +XML_HIDDEN void +xmlCleanupRandom(void); +XML_HIDDEN unsigned +xmlRandom(void);
#endif /* XML_DICT_H_PRIVATE__ */ diff --git a/libs/xml2/include/private/enc.h b/libs/xml2/include/private/enc.h index cbdc2b33ab7..cd549145eb2 100644 --- a/libs/xml2/include/private/enc.h +++ b/libs/xml2/include/private/enc.h @@ -9,9 +9,9 @@ xmlInitEncodingInternal(void);
XML_HIDDEN int xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out, - int *outlen, const unsigned char *in, int *inlen, int flush); + int *outlen, const unsigned char *in, int *inlen); XML_HIDDEN int -xmlCharEncInput(xmlParserInputBufferPtr input, int flush); +xmlCharEncInput(xmlParserInputBufferPtr input); XML_HIDDEN int xmlCharEncOutput(xmlOutputBufferPtr output, int init);
diff --git a/libs/xml2/include/private/error.h b/libs/xml2/include/private/error.h index 7f284f9872a..165b782b136 100644 --- a/libs/xml2/include/private/error.h +++ b/libs/xml2/include/private/error.h @@ -4,6 +4,8 @@ #include <libxml/xmlerror.h> #include <libxml/xmlversion.h>
+struct _xmlNode; + XML_HIDDEN void __xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, void *data, void *ctx, @@ -12,7 +14,7 @@ __xmlRaiseError(xmlStructuredErrorFunc schannel, const char *str2, const char *str3, int int1, int col, const char *msg, ...) LIBXML_ATTR_FORMAT(16,17); XML_HIDDEN void -__xmlSimpleError(int domain, int code, xmlNodePtr node, +__xmlSimpleError(int domain, int code, struct _xmlNode *node, const char *msg, const char *extra) LIBXML_ATTR_FORMAT(4,0); XML_HIDDEN void xmlGenericErrorDefaultFunc(void *ctx, const char *msg, diff --git a/libs/xml2/include/private/io.h b/libs/xml2/include/private/io.h index 86a72e15ec6..5f4b210a80e 100644 --- a/libs/xml2/include/private/io.h +++ b/libs/xml2/include/private/io.h @@ -11,6 +11,9 @@ XML_HIDDEN void __xmlLoaderErr(void *ctx, const char *msg, const char *filename) LIBXML_ATTR_FORMAT(2,0);
+xmlParserInputBufferPtr +xmlParserInputBufferCreateString(const xmlChar *str); + #ifdef LIBXML_OUTPUT_ENABLED XML_HIDDEN xmlOutputBufferPtr xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder); diff --git a/libs/xml2/include/private/parser.h b/libs/xml2/include/private/parser.h index 820bb587cae..7f8f6912a98 100644 --- a/libs/xml2/include/private/parser.h +++ b/libs/xml2/include/private/parser.h @@ -17,9 +17,23 @@ */ #define XML_VCTXT_USE_PCTXT (1u << 1)
+#define XML_INPUT_HAS_ENCODING (1u << 0) +#define XML_INPUT_AUTO_ENCODING (7u << 1) +#define XML_INPUT_AUTO_UTF8 (1u << 1) +#define XML_INPUT_AUTO_UTF16LE (2u << 1) +#define XML_INPUT_AUTO_UTF16BE (3u << 1) +#define XML_INPUT_AUTO_OTHER (4u << 1) +#define XML_INPUT_USES_ENC_DECL (1u << 4) +#define XML_INPUT_ENCODING_ERROR (1u << 5) + XML_HIDDEN void xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra); XML_HIDDEN void +xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info); +XML_HIDDEN void LIBXML_ATTR_FORMAT(3,0) +xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, + const char *msg, const xmlChar *str1, const xmlChar *str2); +XML_HIDDEN void __xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr, const char *msg, const xmlChar *str1, const xmlChar *str2) LIBXML_ATTR_FORMAT(3,0); @@ -30,4 +44,25 @@ xmlParserGrow(xmlParserCtxtPtr ctxt); XML_HIDDEN void xmlParserShrink(xmlParserCtxtPtr ctxt);
+XML_HIDDEN void +xmlDetectEncoding(xmlParserCtxtPtr ctxt); +XML_HIDDEN void +xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding); +XML_HIDDEN const xmlChar * +xmlGetActualEncoding(xmlParserCtxtPtr ctxt); + +XML_HIDDEN xmlParserNsData * +xmlParserNsCreate(void); +XML_HIDDEN void +xmlParserNsFree(xmlParserNsData *nsdb); +/* + * These functions allow SAX handlers to attach extra data to namespaces + * efficiently and should be made public. + */ +XML_HIDDEN int +xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix, + void *saxData); +XML_HIDDEN void * +xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix); + #endif /* XML_PARSER_H_PRIVATE__ */ diff --git a/libs/xml2/include/private/threads.h b/libs/xml2/include/private/threads.h index b337bfa0b6d..473bc7c0bcb 100644 --- a/libs/xml2/include/private/threads.h +++ b/libs/xml2/include/private/threads.h @@ -10,9 +10,6 @@ #elif defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include <windows.h> - #ifndef HAVE_COMPILER_TLS - #include <process.h> - #endif #define HAVE_WIN32_THREADS #endif #endif @@ -30,18 +27,6 @@ struct _xmlMutex { #endif };
-XML_HIDDEN void -__xmlGlobalInitMutexLock(void); -XML_HIDDEN void -__xmlGlobalInitMutexUnlock(void); -XML_HIDDEN void -__xmlGlobalInitMutexDestroy(void); - -XML_HIDDEN void -xmlInitThreadsInternal(void); -XML_HIDDEN void -xmlCleanupThreadsInternal(void); - XML_HIDDEN void xmlInitMutex(xmlMutexPtr mutex); XML_HIDDEN void diff --git a/libs/xml2/libxml.h b/libs/xml2/libxml.h index 6062ba5f18b..eb84ebbfe06 100644 --- a/libs/xml2/libxml.h +++ b/libs/xml2/libxml.h @@ -59,4 +59,12 @@ #define ATTRIBUTE_NO_SANITIZE(arg) #endif
+#ifdef __clang__ + #define ATTRIBUTE_NO_SANITIZE_INTEGER \ + ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow") \ + ATTRIBUTE_NO_SANITIZE("unsigned-shift-base") +#else + #define ATTRIBUTE_NO_SANITIZE_INTEGER +#endif + #endif /* ! __XML_LIBXML_H__ */ diff --git a/libs/xml2/list.c b/libs/xml2/list.c index 12a7c009277..4927a263020 100644 --- a/libs/xml2/list.c +++ b/libs/xml2/list.c @@ -21,8 +21,8 @@ #include <stdlib.h> #include <string.h> #include <libxml/xmlmemory.h> +#include <libxml/xmlerror.h> #include <libxml/list.h> -#include <libxml/globals.h>
/* * Type definition are kept internal diff --git a/libs/xml2/parser.c b/libs/xml2/parser.c index 1145a58860d..8fa8672ecea 100644 --- a/libs/xml2/parser.c +++ b/libs/xml2/parser.c @@ -51,42 +51,33 @@ #include <stddef.h> #include <ctype.h> #include <stdlib.h> +#include <libxml/parser.h> #include <libxml/xmlmemory.h> -#include <libxml/threads.h> -#include <libxml/globals.h> #include <libxml/tree.h> -#include <libxml/parser.h> #include <libxml/parserInternals.h> -#include <libxml/HTMLparser.h> #include <libxml/valid.h> #include <libxml/entities.h> #include <libxml/xmlerror.h> #include <libxml/encoding.h> #include <libxml/xmlIO.h> #include <libxml/uri.h> +#include <libxml/SAX2.h> #ifdef LIBXML_CATALOG_ENABLED #include <libxml/catalog.h> #endif -#ifdef LIBXML_SCHEMAS_ENABLED -#include <libxml/xmlschemastypes.h> -#include <libxml/relaxng.h> -#endif -#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) -#include <libxml/xpath.h> -#endif
#include "private/buf.h" #include "private/dict.h" -#include "private/enc.h" #include "private/entities.h" #include "private/error.h" -#include "private/globals.h" #include "private/html.h" #include "private/io.h" -#include "private/memory.h" #include "private/parser.h" -#include "private/threads.h" -#include "private/xpath.h" + +#define NS_INDEX_EMPTY INT_MAX +#define NS_INDEX_XML (INT_MAX - 1) +#define URI_HASH_EMPTY 0xD943A04E +#define URI_HASH_XML 0xF0451F02
struct _xmlStartTag { const xmlChar *prefix; @@ -95,6 +86,34 @@ struct _xmlStartTag { int nsNr; };
+typedef struct { + void *saxData; + unsigned prefixHashValue; + unsigned uriHashValue; + unsigned elementId; + int oldIndex; +} xmlParserNsExtra; + +typedef struct { + unsigned hashValue; + int index; +} xmlParserNsBucket; + +struct _xmlParserNsData { + xmlParserNsExtra *extra; + + unsigned hashSize; + unsigned hashElems; + xmlParserNsBucket *hash; + + unsigned elementId; + int defaultNsIndex; +}; + +struct _xmlAttrHashBucket { + int index; +}; + static xmlParserCtxtPtr xmlCreateEntityParserCtxtInternal(xmlSAXHandlerPtr sax, void *userData, const xmlChar *URL, const xmlChar *ID, const xmlChar *base, @@ -121,13 +140,7 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt); */
/* - * XML_PARSER_NON_LINEAR is roughly the maximum allowed amplification factor - * of serialized output after entity expansion. - */ -#define XML_PARSER_NON_LINEAR 5 - -/* - * A certain amount is always allowed. + * A certain amount of entity expansion which is always allowed. */ #define XML_PARSER_ALLOWED_EXPANSION 1000000
@@ -150,7 +163,6 @@ unsigned int xmlParserMaxDepth = 256;
-#define SAX2 1 #define XML_PARSER_BIG_BUFFER_SIZE 300 #define XML_PARSER_BUFFER_SIZE 100 #define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document" @@ -166,6 +178,14 @@ unsigned int xmlParserMaxDepth = 256; */ #define XML_PARSER_CHUNK_SIZE 100
+/** + * xmlParserVersion: + * + * Constant string describing the internal version of the library + */ +const char *const +xmlParserVersion = LIBXML_VERSION_STRING LIBXML_VERSION_EXTRA; + /* * List of XML prefixed PI allowed by W3C specs */ @@ -188,8 +208,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, const xmlChar *ID, xmlNodePtr *list);
static int -xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, - const char *encoding); +xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options); #ifdef LIBXML_LEGACY_ENABLED static void xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode, @@ -245,222 +264,6 @@ xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix, } }
-/** - * xmlFatalErr: - * @ctxt: an XML parser context - * @error: the error number - * @extra: extra information string - * - * Handle a fatal parser error, i.e. violating Well-Formedness constraints - */ -static void -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"; - break; - case XML_ERR_INVALID_DEC_CHARREF: - errmsg = "CharRef: invalid decimal value"; - break; - case XML_ERR_INVALID_CHARREF: - errmsg = "CharRef: invalid value"; - break; - case XML_ERR_INTERNAL_ERROR: - errmsg = "internal error"; - break; - case XML_ERR_PEREF_AT_EOF: - errmsg = "PEReference at end of document"; - break; - case XML_ERR_PEREF_IN_PROLOG: - errmsg = "PEReference in prolog"; - break; - case XML_ERR_PEREF_IN_EPILOG: - errmsg = "PEReference in epilog"; - break; - case XML_ERR_PEREF_NO_NAME: - errmsg = "PEReference: no name"; - break; - case XML_ERR_PEREF_SEMICOL_MISSING: - errmsg = "PEReference: expecting ';'"; - break; - case XML_ERR_ENTITY_LOOP: - errmsg = "Detected an entity reference loop"; - break; - case XML_ERR_ENTITY_NOT_STARTED: - errmsg = "EntityValue: " or ' expected"; - break; - case XML_ERR_ENTITY_PE_INTERNAL: - errmsg = "PEReferences forbidden in internal subset"; - break; - case XML_ERR_ENTITY_NOT_FINISHED: - errmsg = "EntityValue: " or ' expected"; - break; - case XML_ERR_ATTRIBUTE_NOT_STARTED: - errmsg = "AttValue: " or ' expected"; - break; - case XML_ERR_LT_IN_ATTRIBUTE: - errmsg = "Unescaped '<' not allowed in attributes values"; - break; - case XML_ERR_LITERAL_NOT_STARTED: - errmsg = "SystemLiteral " or ' expected"; - break; - case XML_ERR_LITERAL_NOT_FINISHED: - errmsg = "Unfinished System or Public ID " or ' expected"; - break; - case XML_ERR_MISPLACED_CDATA_END: - errmsg = "Sequence ']]>' not allowed in content"; - break; - case XML_ERR_URI_REQUIRED: - errmsg = "SYSTEM or PUBLIC, the URI is missing"; - break; - case XML_ERR_PUBID_REQUIRED: - errmsg = "PUBLIC, the Public Identifier is missing"; - break; - case XML_ERR_HYPHEN_IN_COMMENT: - errmsg = "Comment must not contain '--' (double-hyphen)"; - break; - case XML_ERR_PI_NOT_STARTED: - errmsg = "xmlParsePI : no target name"; - break; - case XML_ERR_RESERVED_XML_NAME: - errmsg = "Invalid PI name"; - break; - case XML_ERR_NOTATION_NOT_STARTED: - errmsg = "NOTATION: Name expected here"; - break; - case XML_ERR_NOTATION_NOT_FINISHED: - errmsg = "'>' required to close NOTATION declaration"; - break; - case XML_ERR_VALUE_REQUIRED: - errmsg = "Entity value required"; - break; - case XML_ERR_URI_FRAGMENT: - errmsg = "Fragment not allowed"; - break; - case XML_ERR_ATTLIST_NOT_STARTED: - errmsg = "'(' required to start ATTLIST enumeration"; - break; - case XML_ERR_NMTOKEN_REQUIRED: - errmsg = "NmToken expected in ATTLIST enumeration"; - break; - case XML_ERR_ATTLIST_NOT_FINISHED: - errmsg = "')' required to finish ATTLIST enumeration"; - break; - case XML_ERR_MIXED_NOT_STARTED: - errmsg = "MixedContentDecl : '|' or ')*' expected"; - break; - case XML_ERR_PCDATA_REQUIRED: - errmsg = "MixedContentDecl : '#PCDATA' expected"; - break; - case XML_ERR_ELEMCONTENT_NOT_STARTED: - errmsg = "ContentDecl : Name or '(' expected"; - break; - case XML_ERR_ELEMCONTENT_NOT_FINISHED: - errmsg = "ContentDecl : ',' '|' or ')' expected"; - break; - case XML_ERR_PEREF_IN_INT_SUBSET: - errmsg = - "PEReference: forbidden within markup decl in internal subset"; - break; - case XML_ERR_GT_REQUIRED: - errmsg = "expected '>'"; - break; - case XML_ERR_CONDSEC_INVALID: - errmsg = "XML conditional section '[' expected"; - break; - case XML_ERR_EXT_SUBSET_NOT_FINISHED: - errmsg = "Content error in the external subset"; - break; - case XML_ERR_CONDSEC_INVALID_KEYWORD: - errmsg = - "conditional section INCLUDE or IGNORE keyword expected"; - break; - case XML_ERR_CONDSEC_NOT_FINISHED: - errmsg = "XML conditional section not closed"; - break; - case XML_ERR_XMLDECL_NOT_STARTED: - errmsg = "Text declaration '<?xml' required"; - break; - case XML_ERR_XMLDECL_NOT_FINISHED: - errmsg = "parsing XML declaration: '?>' expected"; - break; - case XML_ERR_EXT_ENTITY_STANDALONE: - errmsg = "external parsed entities cannot be standalone"; - break; - case XML_ERR_ENTITYREF_SEMICOL_MISSING: - errmsg = "EntityRef: expecting ';'"; - break; - case XML_ERR_DOCTYPE_NOT_FINISHED: - errmsg = "DOCTYPE improperly terminated"; - break; - case XML_ERR_LTSLASH_REQUIRED: - errmsg = "EndTag: '</' not found"; - break; - case XML_ERR_EQUAL_REQUIRED: - errmsg = "expected '='"; - break; - case XML_ERR_STRING_NOT_CLOSED: - errmsg = "String not closed expecting " or '"; - break; - case XML_ERR_STRING_NOT_STARTED: - errmsg = "String not started expecting ' or ""; - break; - case XML_ERR_ENCODING_NAME: - errmsg = "Invalid XML encoding name"; - break; - case XML_ERR_STANDALONE_VALUE: - errmsg = "standalone accepts only 'yes' or 'no'"; - break; - case XML_ERR_DOCUMENT_EMPTY: - errmsg = "Document is empty"; - break; - case XML_ERR_DOCUMENT_END: - errmsg = "Extra content at the end of the document"; - break; - case XML_ERR_NOT_WELL_BALANCED: - errmsg = "chunk is not well balanced"; - break; - case XML_ERR_EXTRA_CONTENT: - errmsg = "extra content at the end of well balanced chunk"; - break; - case XML_ERR_VERSION_MISSING: - errmsg = "Malformed declaration expecting version"; - break; - case XML_ERR_NAME_TOO_LONG: - errmsg = "Name too long"; - break; -#if 0 - case: - errmsg = ""; - break; -#endif - 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); - } 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; - } -} - /** * xmlFatalErrMsg: * @ctxt: an XML parser context @@ -497,7 +300,7 @@ xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, * * Handle a warning. */ -static void LIBXML_ATTR_FORMAT(3,0) +void LIBXML_ATTR_FORMAT(3,0) xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *msg, const xmlChar *str1, const xmlChar *str2) { @@ -806,9 +609,10 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long extra) */ if ((ctxt->sizeentcopy > XML_PARSER_ALLOWED_EXPANSION) && ((ctxt->sizeentcopy >= ULONG_MAX) || - (ctxt->sizeentcopy / XML_PARSER_NON_LINEAR > consumed))) { + (ctxt->sizeentcopy / ctxt->maxAmpl > consumed))) { xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_LOOP, - "Maximum entity amplification factor exceeded"); + "Maximum entity amplification factor exceeded, see " + "xmlCtxtSetMaxAmplification.\n"); xmlHaltParser(ctxt); return(1); } @@ -1058,7 +862,11 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) { if (ctxt == NULL) return; sax = ctxt->sax; #ifdef LIBXML_SAX1_ENABLED - if ((sax) && (sax->initialized == XML_SAX2_MAGIC) && + /* + * Only enable SAX2 if there SAX2 element handlers, except when there + * are no element handlers at all. + */ + if ((sax) && (sax->initialized == XML_SAX2_MAGIC) && ((sax->startElementNs != NULL) || (sax->endElementNs != NULL) || ((sax->startElement == NULL) && (sax->endElement == NULL)))) @@ -1076,6 +884,15 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) { } }
+typedef struct { + xmlHashedString prefix; + xmlHashedString name; + xmlHashedString value; + const xmlChar *valueEnd; + int external; + int expandedSize; +} xmlDefAttr; + typedef struct _xmlDefAttrs xmlDefAttrs; typedef xmlDefAttrs *xmlDefAttrsPtr; struct _xmlDefAttrs { @@ -1083,9 +900,9 @@ struct _xmlDefAttrs { int maxAttrs; /* the size of the array */ #if __STDC_VERSION__ >= 199901L /* Using a C99 flexible array member avoids UBSan errors. */ - const xmlChar *values[]; /* array of localname/prefix/values/external */ + xmlDefAttr attrs[]; /* array of localname/prefix/values/external */ #else - const xmlChar *values[5]; + xmlDefAttr attrs[1]; #endif };
@@ -1202,9 +1019,12 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt, const xmlChar *fullattr, const xmlChar *value) { xmlDefAttrsPtr defaults; - int len; - const xmlChar *name; - const xmlChar *prefix; + xmlDefAttr *attr; + int len, expandedSize; + xmlHashedString name; + xmlHashedString prefix; + xmlHashedString hvalue; + const xmlChar *localname;
/* * Allows to detect attribute redefinitions @@ -1224,41 +1044,38 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt, * split the element name into prefix:localname , the string found * are within the DTD and then not associated to namespace names. */ - name = xmlSplitQName3(fullname, &len); - if (name == NULL) { - name = xmlDictLookup(ctxt->dict, fullname, -1); - prefix = NULL; + localname = xmlSplitQName3(fullname, &len); + if (localname == NULL) { + name = xmlDictLookupHashed(ctxt->dict, fullname, -1); + prefix.name = NULL; } else { - name = xmlDictLookup(ctxt->dict, name, -1); - prefix = xmlDictLookup(ctxt->dict, fullname, len); + name = xmlDictLookupHashed(ctxt->dict, localname, -1); + prefix = xmlDictLookupHashed(ctxt->dict, fullname, len); + if (prefix.name == NULL) + goto mem_error; } + if (name.name == NULL) + goto mem_error;
/* * make sure there is some storage */ - defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix); - if (defaults == NULL) { - defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) + - (4 * 5) * sizeof(const xmlChar *)); - if (defaults == NULL) - goto mem_error; - defaults->nbAttrs = 0; - defaults->maxAttrs = 4; - if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, - defaults, NULL) < 0) { - xmlFree(defaults); - goto mem_error; - } - } else if (defaults->nbAttrs >= defaults->maxAttrs) { + defaults = xmlHashLookup2(ctxt->attsDefault, name.name, prefix.name); + if ((defaults == NULL) || + (defaults->nbAttrs >= defaults->maxAttrs)) { xmlDefAttrsPtr temp; + int newSize;
- temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) + - (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *)); + newSize = (defaults != NULL) ? 2 * defaults->maxAttrs : 4; + temp = xmlRealloc(defaults, + sizeof(*defaults) + newSize * sizeof(xmlDefAttr)); if (temp == NULL) goto mem_error; - defaults = temp; - defaults->maxAttrs *= 2; - if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, + if (defaults == NULL) + temp->nbAttrs = 0; + temp->maxAttrs = newSize; + defaults = temp; + if (xmlHashUpdateEntry2(ctxt->attsDefault, name.name, prefix.name, defaults, NULL) < 0) { xmlFree(defaults); goto mem_error; @@ -1266,32 +1083,40 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt, }
/* - * Split the element name into prefix:localname , the string found + * Split the attribute name into prefix:localname , the string found * are within the DTD and hen not associated to namespace names. */ - name = xmlSplitQName3(fullattr, &len); - if (name == NULL) { - name = xmlDictLookup(ctxt->dict, fullattr, -1); - prefix = NULL; + localname = xmlSplitQName3(fullattr, &len); + if (localname == NULL) { + name = xmlDictLookupHashed(ctxt->dict, fullattr, -1); + prefix.name = NULL; } else { - name = xmlDictLookup(ctxt->dict, name, -1); - prefix = xmlDictLookup(ctxt->dict, fullattr, len); + name = xmlDictLookupHashed(ctxt->dict, localname, -1); + prefix = xmlDictLookupHashed(ctxt->dict, fullattr, len); + if (prefix.name == NULL) + goto mem_error; } + if (name.name == NULL) + goto mem_error;
- defaults->values[5 * defaults->nbAttrs] = name; - defaults->values[5 * defaults->nbAttrs + 1] = prefix; /* intern the string and precompute the end */ - len = xmlStrlen(value); - value = xmlDictLookup(ctxt->dict, value, len); - if (value == NULL) + len = strlen((const char *) value); + hvalue = xmlDictLookupHashed(ctxt->dict, value, len); + if (hvalue.name == NULL) goto mem_error; - defaults->values[5 * defaults->nbAttrs + 2] = value; - defaults->values[5 * defaults->nbAttrs + 3] = value + len; - if (ctxt->external) - defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external"; - else - defaults->values[5 * defaults->nbAttrs + 4] = NULL; - defaults->nbAttrs++; + + expandedSize = strlen((const char *) name.name); + if (prefix.name != NULL) + expandedSize += strlen((const char *) prefix.name); + expandedSize += len; + + attr = &defaults->attrs[defaults->nbAttrs++]; + attr->name = name; + attr->prefix = prefix; + attr->value = hvalue; + attr->valueEnd = hvalue.name + len; + attr->external = ctxt->external; + attr->expandedSize = expandedSize;
return;
@@ -1577,184 +1402,553 @@ region_m49: static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str);
-#ifdef SAX2 /** - * nsPush: - * @ctxt: an XML parser context - * @prefix: the namespace prefix or NULL - * @URL: the namespace name + * xmlParserNsCreate: * - * Pushes a new parser namespace on top of the ns stack + * Create a new namespace database. * - * Returns -1 in case of error, -2 if the namespace should be discarded - * and the index in the stack otherwise. + * Returns the new obejct. */ -static int -nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL) -{ - if (ctxt->options & XML_PARSE_NSCLEAN) { - int i; - for (i = ctxt->nsNr - 2;i >= 0;i -= 2) { - if (ctxt->nsTab[i] == prefix) { - /* in scope */ - if (ctxt->nsTab[i + 1] == URL) - return(-2); - /* out of scope keep it */ - break; - } - } - } - if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) { - ctxt->nsMax = 10; - ctxt->nsNr = 0; - ctxt->nsTab = (const xmlChar **) - xmlMalloc(ctxt->nsMax * sizeof(xmlChar *)); - if (ctxt->nsTab == NULL) { - xmlErrMemory(ctxt, NULL); - ctxt->nsMax = 0; - return (-1); - } - } else if (ctxt->nsNr >= ctxt->nsMax) { - const xmlChar ** tmp; - ctxt->nsMax *= 2; - tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab, - ctxt->nsMax * sizeof(ctxt->nsTab[0])); - if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); - ctxt->nsMax /= 2; - return (-1); - } - ctxt->nsTab = tmp; - } - ctxt->nsTab[ctxt->nsNr++] = prefix; - ctxt->nsTab[ctxt->nsNr++] = URL; - return (ctxt->nsNr); +xmlParserNsData * +xmlParserNsCreate(void) { + xmlParserNsData *nsdb = xmlMalloc(sizeof(*nsdb)); + + if (nsdb == NULL) + return(NULL); + memset(nsdb, 0, sizeof(*nsdb)); + nsdb->defaultNsIndex = INT_MAX; + + return(nsdb); } + /** - * nsPop: - * @ctxt: an XML parser context - * @nr: the number to pop + * xmlParserNsFree: + * @nsdb: namespace database * - * Pops the top @nr parser prefix/namespace from the ns stack + * Free a namespace database. + */ +void +xmlParserNsFree(xmlParserNsData *nsdb) { + if (nsdb == NULL) + return; + + xmlFree(nsdb->extra); + xmlFree(nsdb->hash); + xmlFree(nsdb); +} + +/** + * xmlParserNsReset: + * @nsdb: namespace database * - * Returns the number of namespaces removed + * Reset a namespace database. */ -static int -nsPop(xmlParserCtxtPtr ctxt, int nr) -{ - int i; +static void +xmlParserNsReset(xmlParserNsData *nsdb) { + if (nsdb == NULL) + return;
- if (ctxt->nsTab == NULL) return(0); - if (ctxt->nsNr < nr) { - xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr); - nr = ctxt->nsNr; - } - if (ctxt->nsNr <= 0) - return (0); + nsdb->hashElems = 0; + nsdb->elementId = 0; + nsdb->defaultNsIndex = INT_MAX;
- for (i = 0;i < nr;i++) { - ctxt->nsNr--; - ctxt->nsTab[ctxt->nsNr] = NULL; - } - return(nr); + if (nsdb->hash) + memset(nsdb->hash, 0, nsdb->hashSize * sizeof(nsdb->hash[0])); } -#endif
+/** + * xmlParserStartElement: + * @nsdb: namespace database + * + * Signal that a new element has started. + * + * Returns 0 on success, -1 if the element counter overflowed. + */ static int -xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) { - const xmlChar **atts; - int *attallocs; - int maxatts; +xmlParserNsStartElement(xmlParserNsData *nsdb) { + if (nsdb->elementId == UINT_MAX) + return(-1); + nsdb->elementId++;
- if (nr + 5 > ctxt->maxatts) { - maxatts = ctxt->maxatts == 0 ? 55 : (nr + 5) * 2; - atts = (const xmlChar **) xmlMalloc( - maxatts * sizeof(const xmlChar *)); - if (atts == NULL) goto mem_error; - attallocs = (int *) xmlRealloc((void *) ctxt->attallocs, - (maxatts / 5) * sizeof(int)); - if (attallocs == NULL) { - xmlFree(atts); - goto mem_error; - } - if (ctxt->maxatts > 0) - memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *)); - xmlFree(ctxt->atts); - ctxt->atts = atts; - ctxt->attallocs = attallocs; - ctxt->maxatts = maxatts; - } - return(ctxt->maxatts); -mem_error: - xmlErrMemory(ctxt, NULL); - return(-1); + return(0); }
/** - * inputPush: - * @ctxt: an XML parser context - * @value: the parser input + * xmlParserNsLookup: + * @ctxt: parser context + * @prefix: namespace prefix + * @bucketPtr: optional bucket (return value) * - * Pushes a new parser input on top of the input stack + * Lookup namespace with given prefix. If @bucketPtr is non-NULL, it will + * be set to the matching bucket, or the first empty bucket if no match + * was found. * - * Returns -1 in case of error, the index in the stack otherwise + * Returns the namespace index on success, INT_MAX if no namespace was + * found. */ -int -inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value) -{ - if ((ctxt == NULL) || (value == NULL)) - return(-1); - if (ctxt->inputNr >= ctxt->inputMax) { - size_t newSize = ctxt->inputMax * 2; - xmlParserInputPtr *tmp; +static int +xmlParserNsLookup(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix, + xmlParserNsBucket **bucketPtr) { + xmlParserNsBucket *bucket, *tombstone; + unsigned index, hashValue; + + if (prefix->name == NULL) + return(ctxt->nsdb->defaultNsIndex); + + if (ctxt->nsdb->hashSize == 0) + return(INT_MAX); + + hashValue = prefix->hashValue; + index = hashValue & (ctxt->nsdb->hashSize - 1); + bucket = &ctxt->nsdb->hash[index]; + tombstone = NULL; + + while (bucket->hashValue) { + if (bucket->index == INT_MAX) { + if (tombstone == NULL) + tombstone = bucket; + } else if (bucket->hashValue == hashValue) { + if (ctxt->nsTab[bucket->index * 2] == prefix->name) { + if (bucketPtr != NULL) + *bucketPtr = bucket; + return(bucket->index); + } + }
- tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab, - newSize * sizeof(*tmp)); - if (tmp == NULL) { - xmlErrMemory(ctxt, NULL); - return (-1); + index++; + bucket++; + if (index == ctxt->nsdb->hashSize) { + index = 0; + bucket = ctxt->nsdb->hash; } - ctxt->inputTab = tmp; - ctxt->inputMax = newSize; } - ctxt->inputTab[ctxt->inputNr] = value; - ctxt->input = value; - return (ctxt->inputNr++); + + if (bucketPtr != NULL) + *bucketPtr = tombstone ? tombstone : bucket; + return(INT_MAX); } + /** - * inputPop: - * @ctxt: an XML parser context + * xmlParserNsLookupUri: + * @ctxt: parser context + * @prefix: namespace prefix * - * Pops the top parser input from the input stack + * Lookup namespace URI with given prefix. * - * Returns the input just removed + * Returns the namespace URI on success, NULL if no namespace was found. */ -xmlParserInputPtr -inputPop(xmlParserCtxtPtr ctxt) -{ - xmlParserInputPtr ret; +static const xmlChar * +xmlParserNsLookupUri(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix) { + const xmlChar *ret; + int nsIndex;
- if (ctxt == NULL) + if (prefix->name == ctxt->str_xml) + return(ctxt->str_xml_ns); + + nsIndex = xmlParserNsLookup(ctxt, prefix, NULL); + if (nsIndex == INT_MAX) return(NULL); - if (ctxt->inputNr <= 0) - return (NULL); - ctxt->inputNr--; - if (ctxt->inputNr > 0) - ctxt->input = ctxt->inputTab[ctxt->inputNr - 1]; - else - ctxt->input = NULL; - ret = ctxt->inputTab[ctxt->inputNr]; - ctxt->inputTab[ctxt->inputNr] = NULL; - return (ret); + + ret = ctxt->nsTab[nsIndex * 2 + 1]; + if (ret[0] == 0) + ret = NULL; + return(ret); } + /** - * nodePush: - * @ctxt: an XML parser context - * @value: the element node - * - * DEPRECATED: Internal function, do not use. + * xmlParserNsLookupSax: + * @ctxt: parser context + * @prefix: namespace prefix * - * Pushes a new element node on top of the node stack + * Lookup extra data for the given prefix. This returns data stored + * with xmlParserNsUdpateSax. + * + * Returns the data on success, NULL if no namespace was found. + */ +void * +xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix) { + xmlHashedString hprefix; + int nsIndex; + + if (prefix == ctxt->str_xml) + return(NULL); + + hprefix.name = prefix; + if (prefix != NULL) + hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix); + else + hprefix.hashValue = 0; + nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL); + if (nsIndex == INT_MAX) + return(NULL); + + return(ctxt->nsdb->extra[nsIndex].saxData); +} + +/** + * xmlParserNsUpdateSax: + * @ctxt: parser context + * @prefix: namespace prefix + * @saxData: extra data for SAX handler + * + * Sets or updates extra data for the given prefix. This value will be + * returned by xmlParserNsLookupSax as long as the namespace with the + * given prefix is in scope. + * + * Returns the data on success, NULL if no namespace was found. + */ +int +xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix, + void *saxData) { + xmlHashedString hprefix; + int nsIndex; + + if (prefix == ctxt->str_xml) + return(-1); + + hprefix.name = prefix; + if (prefix != NULL) + hprefix.hashValue = xmlDictComputeHash(ctxt->dict, prefix); + else + hprefix.hashValue = 0; + nsIndex = xmlParserNsLookup(ctxt, &hprefix, NULL); + if (nsIndex == INT_MAX) + return(-1); + + ctxt->nsdb->extra[nsIndex].saxData = saxData; + return(0); +} + +/** + * xmlParserNsGrow: + * @ctxt: parser context + * + * Grows the namespace tables. + * + * Returns 0 on success, -1 if a memory allocation failed. + */ +static int +xmlParserNsGrow(xmlParserCtxtPtr ctxt) { + const xmlChar **table; + xmlParserNsExtra *extra; + int newSize; + + if (ctxt->nsMax > INT_MAX / 2) + goto error; + newSize = ctxt->nsMax ? ctxt->nsMax * 2 : 16; + + table = xmlRealloc(ctxt->nsTab, 2 * newSize * sizeof(table[0])); + if (table == NULL) + goto error; + ctxt->nsTab = table; + + extra = xmlRealloc(ctxt->nsdb->extra, newSize * sizeof(extra[0])); + if (extra == NULL) + goto error; + ctxt->nsdb->extra = extra; + + ctxt->nsMax = newSize; + return(0); + +error: + xmlErrMemory(ctxt, NULL); + return(-1); +} + +/** + * xmlParserNsPush: + * @ctxt: parser context + * @prefix: prefix with hash value + * @uri: uri with hash value + * @saxData: extra data for SAX handler + * @defAttr: whether the namespace comes from a default attribute + * + * Push a new namespace on the table. + * + * Returns 1 if the namespace was pushed, 0 if the namespace was ignored, + * -1 if a memory allocation failed. + */ +static int +xmlParserNsPush(xmlParserCtxtPtr ctxt, const xmlHashedString *prefix, + const xmlHashedString *uri, void *saxData, int defAttr) { + xmlParserNsBucket *bucket = NULL; + xmlParserNsExtra *extra; + const xmlChar **ns; + unsigned hashValue, nsIndex, oldIndex; + + if ((prefix != NULL) && (prefix->name == ctxt->str_xml)) + return(0); + + if ((ctxt->nsNr >= ctxt->nsMax) && (xmlParserNsGrow(ctxt) < 0)) { + xmlErrMemory(ctxt, NULL); + return(-1); + } + + /* + * Default namespace and 'xml' namespace + */ + if ((prefix == NULL) || (prefix->name == NULL)) { + oldIndex = ctxt->nsdb->defaultNsIndex; + + if (oldIndex != INT_MAX) { + extra = &ctxt->nsdb->extra[oldIndex]; + + if (extra->elementId == ctxt->nsdb->elementId) { + if (defAttr == 0) + xmlErrAttributeDup(ctxt, NULL, BAD_CAST "xmlns"); + return(0); + } + + if ((ctxt->options & XML_PARSE_NSCLEAN) && + (uri->name == ctxt->nsTab[oldIndex * 2 + 1])) + return(0); + } + + ctxt->nsdb->defaultNsIndex = ctxt->nsNr; + goto populate_entry; + } + + /* + * Hash table lookup + */ + oldIndex = xmlParserNsLookup(ctxt, prefix, &bucket); + if (oldIndex != INT_MAX) { + extra = &ctxt->nsdb->extra[oldIndex]; + + /* + * Check for duplicate definitions on the same element. + */ + if (extra->elementId == ctxt->nsdb->elementId) { + if (defAttr == 0) + xmlErrAttributeDup(ctxt, BAD_CAST "xmlns", prefix->name); + return(0); + } + + if ((ctxt->options & XML_PARSE_NSCLEAN) && + (uri->name == ctxt->nsTab[bucket->index * 2 + 1])) + return(0); + + bucket->index = ctxt->nsNr; + goto populate_entry; + } + + /* + * Insert new bucket + */ + + hashValue = prefix->hashValue; + + /* + * Grow hash table, 50% fill factor + */ + if (ctxt->nsdb->hashElems + 1 > ctxt->nsdb->hashSize / 2) { + xmlParserNsBucket *newHash; + unsigned newSize, i, index; + + if (ctxt->nsdb->hashSize > UINT_MAX / 2) { + xmlErrMemory(ctxt, NULL); + return(-1); + } + newSize = ctxt->nsdb->hashSize ? ctxt->nsdb->hashSize * 2 : 16; + newHash = xmlMalloc(newSize * sizeof(newHash[0])); + if (newHash == NULL) { + xmlErrMemory(ctxt, NULL); + return(-1); + } + memset(newHash, 0, newSize * sizeof(newHash[0])); + + for (i = 0; i < ctxt->nsdb->hashSize; i++) { + unsigned hv = ctxt->nsdb->hash[i].hashValue; + unsigned newIndex; + + if ((hv == 0) || (ctxt->nsdb->hash[i].index == INT_MAX)) + continue; + newIndex = hv & (newSize - 1); + + while (newHash[newIndex].hashValue != 0) { + newIndex++; + if (newIndex == newSize) + newIndex = 0; + } + + newHash[newIndex] = ctxt->nsdb->hash[i]; + } + + xmlFree(ctxt->nsdb->hash); + ctxt->nsdb->hash = newHash; + ctxt->nsdb->hashSize = newSize; + + /* + * Relookup + */ + index = hashValue & (newSize - 1); + + while (newHash[index].hashValue != 0) { + index++; + if (index == newSize) + index = 0; + } + + bucket = &newHash[index]; + } + + bucket->hashValue = hashValue; + bucket->index = ctxt->nsNr; + ctxt->nsdb->hashElems++; + oldIndex = INT_MAX; + +populate_entry: + nsIndex = ctxt->nsNr; + + ns = &ctxt->nsTab[nsIndex * 2]; + ns[0] = prefix ? prefix->name : NULL; + ns[1] = uri->name; + + extra = &ctxt->nsdb->extra[nsIndex]; + extra->saxData = saxData; + extra->prefixHashValue = prefix ? prefix->hashValue : 0; + extra->uriHashValue = uri->hashValue; + extra->elementId = ctxt->nsdb->elementId; + extra->oldIndex = oldIndex; + + ctxt->nsNr++; + + return(1); +} + +/** + * xmlParserNsPop: + * @ctxt: an XML parser context + * @nr: the number to pop + * + * Pops the top @nr namespaces and restores the hash table. + * + * Returns the number of namespaces popped. + */ +static int +xmlParserNsPop(xmlParserCtxtPtr ctxt, int nr) +{ + int i; + + /* assert(nr <= ctxt->nsNr); */ + + for (i = ctxt->nsNr - 1; i >= ctxt->nsNr - nr; i--) { + const xmlChar *prefix = ctxt->nsTab[i * 2]; + xmlParserNsExtra *extra = &ctxt->nsdb->extra[i]; + + if (prefix == NULL) { + ctxt->nsdb->defaultNsIndex = extra->oldIndex; + } else { + xmlHashedString hprefix; + xmlParserNsBucket *bucket = NULL; + + hprefix.name = prefix; + hprefix.hashValue = extra->prefixHashValue; + xmlParserNsLookup(ctxt, &hprefix, &bucket); + /* assert(bucket && bucket->hashValue); */ + bucket->index = extra->oldIndex; + } + } + + ctxt->nsNr -= nr; + return(nr); +} + +static int +xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) { + const xmlChar **atts; + unsigned *attallocs; + int maxatts; + + if (nr + 5 > ctxt->maxatts) { + maxatts = ctxt->maxatts == 0 ? 55 : (nr + 5) * 2; + atts = (const xmlChar **) xmlMalloc( + maxatts * sizeof(const xmlChar *)); + if (atts == NULL) goto mem_error; + attallocs = xmlRealloc(ctxt->attallocs, + (maxatts / 5) * sizeof(attallocs[0])); + if (attallocs == NULL) { + xmlFree(atts); + goto mem_error; + } + if (ctxt->maxatts > 0) + memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *)); + xmlFree(ctxt->atts); + ctxt->atts = atts; + ctxt->attallocs = attallocs; + ctxt->maxatts = maxatts; + } + return(ctxt->maxatts); +mem_error: + xmlErrMemory(ctxt, NULL); + return(-1); +} + +/** + * inputPush: + * @ctxt: an XML parser context + * @value: the parser input + * + * Pushes a new parser input on top of the input stack + * + * Returns -1 in case of error, the index in the stack otherwise + */ +int +inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value) +{ + if ((ctxt == NULL) || (value == NULL)) + return(-1); + if (ctxt->inputNr >= ctxt->inputMax) { + size_t newSize = ctxt->inputMax * 2; + xmlParserInputPtr *tmp; + + tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab, + newSize * sizeof(*tmp)); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + return (-1); + } + ctxt->inputTab = tmp; + ctxt->inputMax = newSize; + } + ctxt->inputTab[ctxt->inputNr] = value; + ctxt->input = value; + return (ctxt->inputNr++); +} +/** + * inputPop: + * @ctxt: an XML parser context + * + * Pops the top parser input from the input stack + * + * Returns the input just removed + */ +xmlParserInputPtr +inputPop(xmlParserCtxtPtr ctxt) +{ + xmlParserInputPtr ret; + + if (ctxt == NULL) + return(NULL); + if (ctxt->inputNr <= 0) + return (NULL); + ctxt->inputNr--; + if (ctxt->inputNr > 0) + ctxt->input = ctxt->inputTab[ctxt->inputNr - 1]; + else + ctxt->input = NULL; + ret = ctxt->inputTab[ctxt->inputNr]; + ctxt->inputTab[ctxt->inputNr] = NULL; + return (ret); +} +/** + * nodePush: + * @ctxt: an XML parser context + * @value: the element node + * + * DEPRECATED: Internal function, do not use. + * + * Pushes a new element node on top of the node stack * * Returns -1 in case of error, the index in the stack otherwise */ @@ -2071,13 +2265,14 @@ static int spacePop(xmlParserCtxtPtr ctxt) { xmlParserGrow(ctxt); \ } while (0)
-#define SHRINK if ((ctxt->progressive == 0) && \ - (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ - (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ +/* Don't shrink push parser buffer. */ +#define SHRINK \ + if (((ctxt->progressive == 0) || (ctxt->inputNr > 1)) && \ + (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ + (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ xmlParserShrink(ctxt);
-#define GROW if ((ctxt->progressive == 0) && \ - (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ +#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) \ xmlParserGrow(ctxt);
#define SKIP_BLANKS xmlSkipBlankChars(ctxt) @@ -2101,8 +2296,8 @@ static int spacePop(xmlParserCtxtPtr ctxt) { #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l) #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
-#define COPY_BUF(l,b,i,v) \ - if (l == 1) b[i++] = v; \ +#define COPY_BUF(b, i, v) \ + if (v < 0x80) b[i++] = v; \ else i += xmlCopyCharMultiByte(&b[i],v)
/** @@ -2532,6 +2727,7 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) { return; case XML_PARSER_PROLOG: case XML_PARSER_START: + case XML_PARSER_XML_DECL: case XML_PARSER_MISC: xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL); return; @@ -2651,7 +2847,7 @@ xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, int val = xmlParseStringCharRef(ctxt, &str); if (val == 0) goto int_error; - COPY_BUF(0,buffer,nbchars,val); + COPY_BUF(buffer, nbchars, val); if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { growBuffer(buffer, XML_PARSER_BUFFER_SIZE); } @@ -2664,7 +2860,7 @@ xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { if (ent->content != NULL) { - COPY_BUF(0,buffer,nbchars,ent->content[0]); + COPY_BUF(buffer, nbchars, ent->content[0]); if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { growBuffer(buffer, XML_PARSER_BUFFER_SIZE); } @@ -2775,7 +2971,7 @@ xmlStringDecodeEntitiesInt(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, rep = NULL; } } else { - COPY_BUF(l,buffer,nbchars,c); + COPY_BUF(buffer, nbchars, c); str += l; if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) { growBuffer(buffer, XML_PARSER_BUFFER_SIZE); @@ -3120,14 +3316,6 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { * Routines to parse Name, NCName and NmToken * * * ************************************************************************/ -#ifdef DEBUG -static unsigned long nbParseName = 0; -static unsigned long nbParseNmToken = 0; -static unsigned long nbParseNCName = 0; -static unsigned long nbParseNCNameComplex = 0; -static unsigned long nbParseNameComplex = 0; -static unsigned long nbParseStringName = 0; -#endif
/* * The two following functions are related to the change of accepted @@ -3220,10 +3408,6 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { XML_MAX_TEXT_LENGTH : XML_MAX_NAME_LENGTH;
-#ifdef DEBUG - nbParseNameComplex++; -#endif - /* * Handler for more complex cases */ @@ -3354,10 +3538,6 @@ xmlParseName(xmlParserCtxtPtr ctxt) { if (ctxt->instate == XML_PARSER_EOF) return(NULL);
-#ifdef DEBUG - nbParseName++; -#endif - /* * Accelerator for simple ASCII names */ @@ -3390,8 +3570,9 @@ xmlParseName(xmlParserCtxtPtr ctxt) { return(xmlParseNameComplex(ctxt)); }
-static const xmlChar * +static xmlHashedString xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + xmlHashedString ret; int len = 0, l; int c; int maxLength = (ctxt->options & XML_PARSE_HUGE) ? @@ -3399,9 +3580,8 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { XML_MAX_NAME_LENGTH; size_t startPosition = 0;
-#ifdef DEBUG - nbParseNCNameComplex++; -#endif + ret.name = NULL; + ret.hashValue = 0;
/* * Handler for more complex cases @@ -3410,7 +3590,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { c = CUR_CHAR(l); if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) { - return(NULL); + return(ret); }
while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ @@ -3421,12 +3601,13 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { c = CUR_CHAR(l); } if (ctxt->instate == XML_PARSER_EOF) - return(NULL); + return(ret); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); - return(NULL); + return(ret); } - return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len)); + ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len); + return(ret); }
/** @@ -3444,18 +3625,16 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { * Returns the Name parsed or NULL */
-static const xmlChar * +static xmlHashedString xmlParseNCName(xmlParserCtxtPtr ctxt) { const xmlChar *in, *e; - const xmlChar *ret; + xmlHashedString ret; size_t count = 0; size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? XML_MAX_TEXT_LENGTH : XML_MAX_NAME_LENGTH;
-#ifdef DEBUG - nbParseNCName++; -#endif + ret.name = NULL;
/* * Accelerator for simple ASCII names @@ -3478,12 +3657,12 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) { count = in - ctxt->input->cur; if (count > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); - return(NULL); + return(ret); } - ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count); + ret = xmlDictLookupHashed(ctxt->dict, ctxt->input->cur, count); ctxt->input->cur = in; ctxt->input->col += count; - if (ret == NULL) { + if (ret.name == NULL) { xmlErrMemory(ctxt, NULL); } return(ret); @@ -3562,20 +3741,16 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { XML_MAX_TEXT_LENGTH : XML_MAX_NAME_LENGTH;
-#ifdef DEBUG - nbParseStringName++; -#endif - c = CUR_SCHAR(cur, l); if (!xmlIsNameStartChar(ctxt, c)) { return(NULL); }
- COPY_BUF(l,buf,len,c); + COPY_BUF(buf, len, c); cur += l; c = CUR_SCHAR(cur, l); while (xmlIsNameChar(ctxt, c)) { - COPY_BUF(l,buf,len,c); + COPY_BUF(buf, len, c); cur += l; c = CUR_SCHAR(cur, l); if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */ @@ -3605,7 +3780,7 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { } buffer = tmp; } - COPY_BUF(l,buffer,len,c); + COPY_BUF(buffer, len, c); cur += l; c = CUR_SCHAR(cur, l); if (len > maxLength) { @@ -3651,14 +3826,10 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { XML_MAX_TEXT_LENGTH : XML_MAX_NAME_LENGTH;
-#ifdef DEBUG - nbParseNmToken++; -#endif - c = CUR_CHAR(l);
while (xmlIsNameChar(ctxt, c)) { - COPY_BUF(l,buf,len,c); + COPY_BUF(buf, len, c); NEXTL(l); c = CUR_CHAR(l); if (len >= XML_MAX_NAMELEN) { @@ -3688,7 +3859,7 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { } buffer = tmp; } - COPY_BUF(l,buffer,len,c); + COPY_BUF(buffer, len, c); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); xmlFree(buffer); @@ -3790,7 +3961,7 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { } buf = tmp; } - COPY_BUF(l,buf,len,c); + COPY_BUF(buf, len, c); NEXTL(l);
GROW; @@ -4074,7 +4245,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) { if ((len != 0) || (!normalize)) { if ((!normalize) || (!in_space)) { - COPY_BUF(l,buf,len,0x20); + COPY_BUF(buf, len, 0x20); while (len + 10 > buf_size) { growBuffer(buf, 10); } @@ -4083,7 +4254,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { } } else { in_space = 0; - COPY_BUF(l,buf,len,c); + COPY_BUF(buf, len, c); if (len + 10 > buf_size) { growBuffer(buf, 10); } @@ -4230,7 +4401,7 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { } buf = tmp; } - COPY_BUF(l,buf,len,cur); + COPY_BUF(buf, len, cur); if (len > maxLength) { xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral"); xmlFree(buf); @@ -4418,6 +4589,7 @@ get_more_space: ctxt->input->cur = in;
if ((ctxt->sax != NULL) && + (ctxt->disableSAX == 0) && (ctxt->sax->ignorableWhitespace != ctxt->sax->characters)) { if (areBlanks(ctxt, tmp, nbchar, 1)) { @@ -4432,6 +4604,7 @@ get_more_space: *ctxt->space = -2; } } else if ((ctxt->sax != NULL) && + (ctxt->disableSAX == 0) && (ctxt->sax->characters != NULL)) { ctxt->sax->characters(ctxt->userData, tmp, nbchar); @@ -4468,6 +4641,7 @@ get_more: nbchar = in - ctxt->input->cur; if (nbchar > 0) { if ((ctxt->sax != NULL) && + (ctxt->disableSAX == 0) && (ctxt->sax->ignorableWhitespace != ctxt->sax->characters) && (IS_BLANK_CH(*ctxt->input->cur))) { @@ -4487,7 +4661,8 @@ get_more: } line = ctxt->input->line; col = ctxt->input->col; - } else if (ctxt->sax != NULL) { + } else if ((ctxt->sax != NULL) && + (ctxt->disableSAX == 0)) { if (ctxt->sax->characters != NULL) ctxt->sax->characters(ctxt->userData, ctxt->input->cur, nbchar); @@ -4546,11 +4721,11 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int partial) { cur = CUR_CHAR(l); while ((cur != '<') && /* checked */ (cur != '&') && - (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ { + (IS_CHAR(cur))) { if ((cur == ']') && (NXT(1) == ']') && (NXT(2) == '>')) { xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL); } - COPY_BUF(l,buf,nbchar,cur); + COPY_BUF(buf, nbchar, cur); /* move current position before possible calling of ctxt->sax->characters */ NEXTL(l); if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) { @@ -4793,7 +4968,7 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, buf = new_buf; size = new_size; } - COPY_BUF(ql,buf,len,q); + COPY_BUF(buf, len, q); if (len > maxLength) { xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, "Comment too big found", NULL); @@ -4916,37 +5091,34 @@ get_more: * save current set of data */ if (nbchar > 0) { - if ((ctxt->sax != NULL) && - (ctxt->sax->comment != NULL)) { - if (buf == NULL) { - if ((*in == '-') && (in[1] == '-')) - size = nbchar + 1; - else - size = XML_PARSER_BUFFER_SIZE + nbchar; - buf = (xmlChar *) xmlMallocAtomic(size); - if (buf == NULL) { - xmlErrMemory(ctxt, NULL); - ctxt->instate = state; - return; - } - len = 0; - } else if (len + nbchar + 1 >= size) { - xmlChar *new_buf; - size += len + nbchar + XML_PARSER_BUFFER_SIZE; - new_buf = (xmlChar *) xmlRealloc(buf, size); - if (new_buf == NULL) { - xmlFree (buf); - xmlErrMemory(ctxt, NULL); - ctxt->instate = state; - return; - } - buf = new_buf; - } - memcpy(&buf[len], ctxt->input->cur, nbchar); - len += nbchar; - buf[len] = 0; - } - } + if (buf == NULL) { + if ((*in == '-') && (in[1] == '-')) + size = nbchar + 1; + else + size = XML_PARSER_BUFFER_SIZE + nbchar; + buf = (xmlChar *) xmlMallocAtomic(size); + if (buf == NULL) { + xmlErrMemory(ctxt, NULL); + ctxt->instate = state; + return; + } + len = 0; + } else if (len + nbchar + 1 >= size) { + xmlChar *new_buf; + size += len + nbchar + XML_PARSER_BUFFER_SIZE; + new_buf = (xmlChar *) xmlRealloc(buf, size); + if (new_buf == NULL) { + xmlFree (buf); + xmlErrMemory(ctxt, NULL); + ctxt->instate = state; + return; + } + buf = new_buf; + } + memcpy(&buf[len], ctxt->input->cur, nbchar); + len += nbchar; + buf[len] = 0; + } if (len > maxLength) { xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, "Comment too big found", NULL); @@ -5218,7 +5390,7 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { buf = tmp; size = new_size; } - COPY_BUF(l,buf,len,cur); + COPY_BUF(buf, len, cur); if (len > maxLength) { xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, "PI %s too big found", target); @@ -6901,7 +7073,6 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) { void xmlParseTextDecl(xmlParserCtxtPtr ctxt) { xmlChar *version; - const xmlChar *encoding; int oldstate;
/* @@ -6940,7 +7111,7 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) { /* * We must have the encoding declaration */ - encoding = xmlParseEncodingDecl(ctxt); + xmlParseEncodingDecl(ctxt); if (ctxt->instate == XML_PARSER_EOF) return; if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { @@ -6950,10 +7121,6 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) { ctxt->instate = oldstate; return; } - if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) { - xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING, - "Missing encoding in text declaration\n"); - }
SKIP_BLANKS; if ((RAW == '?') && (NXT(1) == '>')) { @@ -6973,7 +7140,8 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) { } }
- ctxt->instate = oldstate; + if (ctxt->instate != XML_PARSER_EOF) + ctxt->instate = oldstate; }
/** @@ -6992,21 +7160,8 @@ void xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID, const xmlChar *SystemID) { xmlDetectSAX2(ctxt); - GROW;
- if ((ctxt->encoding == NULL) && - (ctxt->input->end - ctxt->input->cur >= 4)) { - xmlChar start[4]; - xmlCharEncoding enc; - - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(start, 4); - if (enc != XML_CHAR_ENCODING_NONE) - xmlSwitchEncoding(ctxt, enc); - } + xmlDetectEncoding(ctxt);
if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) { xmlParseTextDecl(ctxt); @@ -7086,42 +7241,19 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { if (NXT(1) == '#') { int i = 0; xmlChar out[16]; - int hex = NXT(2); int value = xmlParseCharRef(ctxt);
if (value == 0) return; - if (ctxt->charset != XML_CHAR_ENCODING_UTF8) { - /* - * So we are using non-UTF-8 buffers - * Check that the char fit on 8bits, if not - * generate a CharRef. - */ - if (value <= 0xFF) { - out[0] = value; - out[1] = 0; - if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) && - (!ctxt->disableSAX)) - ctxt->sax->characters(ctxt->userData, out, 1); - } else { - if ((hex == 'x') || (hex == 'X')) - snprintf((char *)out, sizeof(out), "#x%X", value); - else - snprintf((char *)out, sizeof(out), "#%d", value); - if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && - (!ctxt->disableSAX)) - ctxt->sax->reference(ctxt->userData, out); - } - } else { - /* - * Just encode the value in UTF-8 - */ - COPY_BUF(0 ,out, i, value); - out[i] = 0; - if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) && - (!ctxt->disableSAX)) - ctxt->sax->characters(ctxt->userData, out, i); - } + + /* + * Just encode the value in UTF-8 + */ + COPY_BUF(out, i, value); + out[i] = 0; + if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) && + (!ctxt->disableSAX)) + ctxt->sax->characters(ctxt->userData, out, i); return; }
@@ -7157,6 +7289,39 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { * of validating, or substituting entities were given. Doing so is * far more secure as the parser will only process data coming from * the document entity by default. + * + * FIXME: This doesn't work correctly since entities can be + * expanded with different namespace declarations in scope. + * For example: + * + * <!DOCTYPE doc [ + * <!ENTITY ent "<ns:elem/>"> + * ]> + * <doc> + * <decl1 xmlns:ns="urn:ns1"> + * &ent; + * </decl1> + * <decl2 xmlns:ns="urn:ns2"> + * &ent; + * </decl2> + * </doc> + * + * Proposed fix: + * + * - Remove the ent->owner optimization which tries to avoid the + * initial copy of the entity. Always make entities own the + * subtree. + * - Ignore current namespace declarations when parsing the + * entity. If a prefix can't be resolved, don't report an error + * but mark it as unresolved. + * - Try to resolve these prefixes when expanding the entity. + * This will require a specialized version of xmlStaticCopyNode + * which can also make use of the namespace hash table to avoid + * quadratic behavior. + * + * Alternatively, we could simply reparse the entity on each + * expansion like we already do with custom SAX callbacks. + * External entity content should be cached in this case. */ if (((ent->flags & XML_ENT_PARSED) == 0) && ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) || @@ -7596,6 +7761,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) { "Entity '%s' not defined\n", name); if ((ctxt->inSubset == 0) && (ctxt->sax != NULL) && + (ctxt->disableSAX == 0) && (ctxt->sax->reference != NULL)) { ctxt->sax->reference(ctxt->userData, name); } @@ -7969,8 +8135,6 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt) "Internal: %%%s; is not a parameter entity\n", name, NULL); } else { - xmlChar start[4]; - xmlCharEncoding enc; unsigned long parentConsumed; xmlEntityPtr oldEnt;
@@ -8011,28 +8175,7 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt) input->parentConsumed = parentConsumed;
if (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) { - /* - * Get the 4 first bytes and decode the charset - * if enc != XML_CHAR_ENCODING_NONE - * plug some encoding conversion routines. - * Note that, since we may have some non-UTF8 - * encoding (like UTF16, bug 135229), the 'length' - * is not known, but we can calculate based upon - * the amount of data in the buffer. - */ - GROW - if (ctxt->instate == XML_PARSER_EOF) - return; - if ((ctxt->input->end - ctxt->input->cur)>=4) { - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(start, 4); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } - } + xmlDetectEncoding(ctxt);
if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { @@ -8057,9 +8200,14 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt) */ static int xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { - xmlParserInputPtr input; - xmlBufferPtr buf; - int l, c; + xmlParserInputPtr oldinput, input = NULL; + xmlParserInputPtr *oldinputTab; + const xmlChar *oldencoding; + xmlChar *content = NULL; + size_t length, i; + int oldinputNr, oldinputMax, oldprogressive; + int ret = -1; + int res;
if ((ctxt == NULL) || (entity == NULL) || ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) && @@ -8074,61 +8222,114 @@ xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { xmlGenericError(xmlGenericErrorContext, "Reading %s entity content input\n", entity->name);
- buf = xmlBufferCreate(); - if (buf == NULL) { - xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, - "xmlLoadEntityContent parameter error"); - return(-1); - } - xmlBufferSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT); - - input = xmlNewEntityInputStream(ctxt, entity); + input = xmlLoadExternalEntity((char *) entity->URI, + (char *) entity->ExternalID, ctxt); if (input == NULL) { xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "xmlLoadEntityContent input error"); - xmlBufferFree(buf); return(-1); }
+ oldinput = ctxt->input; + oldinputNr = ctxt->inputNr; + oldinputMax = ctxt->inputMax; + oldinputTab = ctxt->inputTab; + oldencoding = ctxt->encoding; + oldprogressive = ctxt->progressive; + + ctxt->input = NULL; + ctxt->inputNr = 0; + ctxt->inputMax = 1; + ctxt->encoding = NULL; + ctxt->progressive = 0; + ctxt->inputTab = xmlMalloc(sizeof(xmlParserInputPtr)); + if (ctxt->inputTab == NULL) { + xmlErrMemory(ctxt, NULL); + xmlFreeInputStream(input); + goto error; + } + + xmlBufResetInput(input->buf->buffer, input); + + inputPush(ctxt, input); + + xmlDetectEncoding(ctxt); + /* - * Push the entity as the current input, read char by char - * saving to the buffer until the end of the entity or an error + * Parse a possible text declaration first */ - if (xmlPushInput(ctxt, input) < 0) { - xmlBufferFree(buf); - xmlFreeInputStream(input); - return(-1); + if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) { + xmlParseTextDecl(ctxt); + /* + * An XML-1.0 document can't reference an entity not XML-1.0 + */ + if ((xmlStrEqual(ctxt->version, BAD_CAST "1.0")) && + (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) { + xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, + "Version mismatch between document and entity\n"); + } }
- GROW; - c = CUR_CHAR(l); - while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) && - (IS_CHAR(c))) { - xmlBufferAdd(buf, ctxt->input->cur, l); - NEXTL(l); - c = CUR_CHAR(l); + if (ctxt->instate == XML_PARSER_EOF) + goto error; + + length = input->cur - input->base; + xmlBufShrink(input->buf->buffer, length); + xmlSaturatedAdd(&ctxt->sizeentities, length); + + while ((res = xmlParserInputBufferGrow(input->buf, 4096)) > 0) + ; + + xmlBufResetInput(input->buf->buffer, input); + + if (res < 0) { + xmlFatalErr(ctxt, input->buf->error, NULL); + goto error; } - if (ctxt->instate == XML_PARSER_EOF) { - xmlBufferFree(buf); - return(-1); + + length = xmlBufUse(input->buf->buffer); + content = xmlBufDetach(input->buf->buffer); + + if (length > INT_MAX) { + xmlErrMemory(ctxt, NULL); + goto error; }
- if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) { - xmlSaturatedAdd(&ctxt->sizeentities, ctxt->input->consumed); - xmlPopInput(ctxt); - } else if (!IS_CHAR(c)) { - xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, - "xmlLoadEntityContent: invalid char value %d\n", - c); - xmlBufferFree(buf); - return(-1); + for (i = 0; i < length; ) { + int clen = length - i; + int c = xmlGetUTF8Char(content + i, &clen); + + if ((c < 0) || (!IS_CHAR(c))) { + xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, + "xmlLoadEntityContent: invalid char value %d\n", + content[i]); + goto error; + } + i += clen; } - entity->content = buf->content; - entity->length = buf->use; - buf->content = NULL; - xmlBufferFree(buf);
- return(0); + xmlSaturatedAdd(&ctxt->sizeentities, length); + entity->content = content; + entity->length = length; + content = NULL; + ret = 0; + +error: + while (ctxt->inputNr > 0) + xmlFreeInputStream(inputPop(ctxt)); + xmlFree(ctxt->inputTab); + xmlFree((xmlChar *) ctxt->encoding); + + ctxt->input = oldinput; + ctxt->inputNr = oldinputNr; + ctxt->inputMax = oldinputMax; + ctxt->inputTab = oldinputTab; + ctxt->encoding = oldencoding; + ctxt->progressive = oldprogressive; + + xmlFree(content); + + return(ret); }
/** @@ -8729,28 +8930,64 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) { * * ************************************************************************/
-/* - * xmlGetNamespace: +/** + * xmlParseQNameHashed: * @ctxt: an XML parser context - * @prefix: the prefix to lookup + * @prefix: pointer to store the prefix part * - * Lookup the namespace name for the @prefix (which ca be NULL) - * The prefix must come from the @ctxt->dict dictionary + * parse an XML Namespace QName * - * Returns the namespace name or NULL if not bound + * [6] QName ::= (Prefix ':')? LocalPart + * [7] Prefix ::= NCName + * [8] LocalPart ::= NCName + * + * Returns the Name parsed or NULL */ -static const xmlChar * -xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) { - int i;
- if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns); - for (i = ctxt->nsNr - 2;i >= 0;i-=2) - if (ctxt->nsTab[i] == prefix) { - if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0)) - return(NULL); - return(ctxt->nsTab[i + 1]); - } - return(NULL); +static xmlHashedString +xmlParseQNameHashed(xmlParserCtxtPtr ctxt, xmlHashedString *prefix) { + xmlHashedString l, p; + int start, isNCName = 0; + + l.name = NULL; + p.name = NULL; + + GROW; + if (ctxt->instate == XML_PARSER_EOF) + return(l); + start = CUR_PTR - BASE_PTR; + + l = xmlParseNCName(ctxt); + if (l.name != NULL) { + isNCName = 1; + if (CUR == ':') { + NEXT; + p = l; + l = xmlParseNCName(ctxt); + } + } + if ((l.name == NULL) || (CUR == ':')) { + xmlChar *tmp; + + l.name = NULL; + p.name = NULL; + if (ctxt->instate == XML_PARSER_EOF) + return(l); + if ((isNCName == 0) && (CUR != ':')) + return(l); + tmp = xmlParseNmtoken(ctxt); + if (tmp != NULL) + xmlFree(tmp); + if (ctxt->instate == XML_PARSER_EOF) + return(l); + l = xmlDictLookupHashed(ctxt->dict, BASE_PTR + start, + CUR_PTR - (BASE_PTR + start)); + xmlNsErr(ctxt, XML_NS_ERR_QNAME, + "Failed to parse QName '%s'\n", l.name, NULL, NULL); + } + + *prefix = p; + return(l); }
/** @@ -8769,76 +9006,13 @@ xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
static const xmlChar * xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) { - const xmlChar *l, *p; - - GROW; - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); + xmlHashedString n, p;
- l = xmlParseNCName(ctxt); - if (l == NULL) { - if (CUR == ':') { - l = xmlParseName(ctxt); - if (l != NULL) { - xmlNsErr(ctxt, XML_NS_ERR_QNAME, - "Failed to parse QName '%s'\n", l, NULL, NULL); - *prefix = NULL; - return(l); - } - } + n = xmlParseQNameHashed(ctxt, &p); + if (n.name == NULL) return(NULL); - } - if (CUR == ':') { - NEXT; - p = l; - l = xmlParseNCName(ctxt); - if (l == NULL) { - xmlChar *tmp; - - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); - xmlNsErr(ctxt, XML_NS_ERR_QNAME, - "Failed to parse QName '%s:'\n", p, NULL, NULL); - l = xmlParseNmtoken(ctxt); - if (l == NULL) { - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); - tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0); - } else { - tmp = xmlBuildQName(l, p, NULL, 0); - xmlFree((char *)l); - } - p = xmlDictLookup(ctxt->dict, tmp, -1); - if (tmp != NULL) xmlFree(tmp); - *prefix = NULL; - return(p); - } - if (CUR == ':') { - xmlChar *tmp; - - xmlNsErr(ctxt, XML_NS_ERR_QNAME, - "Failed to parse QName '%s:%s:'\n", p, l, NULL); - NEXT; - tmp = (xmlChar *) xmlParseName(ctxt); - if (tmp != NULL) { - tmp = xmlBuildQName(tmp, l, NULL, 0); - l = xmlDictLookup(ctxt->dict, tmp, -1); - if (tmp != NULL) xmlFree(tmp); - *prefix = p; - return(l); - } - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); - tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0); - l = xmlDictLookup(ctxt->dict, tmp, -1); - if (tmp != NULL) xmlFree(tmp); - *prefix = p; - return(l); - } - *prefix = p; - } else - *prefix = NULL; - return(l); + *prefix = p.name; + return(n.name); }
/** @@ -8890,6 +9064,8 @@ xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name, * all strings coms from the dictionary, equality can be done directly */ ret = xmlParseQName (ctxt, &prefix2); + if (ret == NULL) + return(NULL); if ((ret == name) && (prefix == prefix2)) return((const xmlChar*) 1); return ret; @@ -9106,24 +9282,30 @@ need_complex: * Returns the attribute name, and the value in *value, . */
-static const xmlChar * +static xmlHashedString xmlParseAttribute2(xmlParserCtxtPtr ctxt, const xmlChar * pref, const xmlChar * elem, - const xmlChar ** prefix, xmlChar ** value, + xmlHashedString * hprefix, xmlChar ** value, int *len, int *alloc) { - const xmlChar *name; + xmlHashedString hname; + const xmlChar *prefix, *name; xmlChar *val, *internal_val = NULL; int normalize = 0;
*value = NULL; GROW; - name = xmlParseQName(ctxt, prefix); - if (name == NULL) { + hname = xmlParseQNameHashed(ctxt, hprefix); + if (hname.name == NULL) { xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, "error parsing attribute name\n"); - return (NULL); + return(hname); } + name = hname.name; + if (hprefix->name != NULL) + prefix = hprefix->name; + else + prefix = NULL;
/* * get the type if needed @@ -9132,7 +9314,8 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt, int type;
type = (int) (ptrdiff_t) xmlHashQLookup2(ctxt->attsSpecial, - pref, elem, *prefix, name); + pref, elem, + prefix, name); if (type != 0) normalize = 1; } @@ -9145,8 +9328,10 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt, NEXT; SKIP_BLANKS; val = xmlParseAttValueInternal(ctxt, len, alloc, normalize); - if (val == NULL) - return (NULL); + if (val == NULL) { + hname.name = NULL; + return(hname); + } if (normalize) { /* * Sometimes a second normalisation pass for spaces is needed @@ -9169,10 +9354,10 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt, xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE, "Specification mandates value for attribute %s\n", name); - return (name); + return(hname); }
- if (*prefix == ctxt->str_xml) { + if (prefix == ctxt->str_xml) { /* * Check that xml:lang conforms to the specification * No more registered as an error, just generate a warning now @@ -9208,8 +9393,58 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt, }
*value = val; - return (name); + return (hname); } + +/** + * xmlAttrHashInsert: + * @ctxt: parser context + * @size: size of the hash table + * @name: attribute name + * @uri: namespace uri + * @hashValue: combined hash value of name and uri + * @aindex: attribute index (this is a multiple of 5) + * + * Inserts a new attribute into the hash table. + * + * Returns INT_MAX if no existing attribute was found, the attribute + * index if an attribute was found, -1 if a memory allocation failed. + */ +static int +xmlAttrHashInsert(xmlParserCtxtPtr ctxt, unsigned size, const xmlChar *name, + const xmlChar *uri, unsigned hashValue, int aindex) { + xmlAttrHashBucket *table = ctxt->attrHash; + xmlAttrHashBucket *bucket; + unsigned hindex; + + hindex = hashValue & (size - 1); + bucket = &table[hindex]; + + while (bucket->index >= 0) { + const xmlChar **atts = &ctxt->atts[bucket->index]; + + if (name == atts[0]) { + int nsIndex = (int) (ptrdiff_t) atts[2]; + + if ((nsIndex == NS_INDEX_EMPTY) ? (uri == NULL) : + (nsIndex == NS_INDEX_XML) ? (uri == ctxt->str_xml_ns) : + (uri == ctxt->nsTab[nsIndex * 2 + 1])) + return(bucket->index); + } + + hindex++; + bucket++; + if (hindex >= size) { + hindex = 0; + bucket = table; + } + } + + bucket->index = aindex; + + return(INT_MAX); +} + /** * xmlParseStartTag2: * @ctxt: an XML parser context @@ -9241,40 +9476,48 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt,
static const xmlChar * xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, - const xmlChar **URI, int *tlen) { + const xmlChar **URI, int *nbNsPtr) { + xmlHashedString hlocalname; + xmlHashedString hprefix; + xmlHashedString hattname; + xmlHashedString haprefix; const xmlChar *localname; const xmlChar *prefix; const xmlChar *attname; const xmlChar *aprefix; - const xmlChar *nsname; - xmlChar *attvalue; + const xmlChar *uri; + xmlChar *attvalue = NULL; const xmlChar **atts = ctxt->atts; + unsigned attrHashSize = 0; int maxatts = ctxt->maxatts; int nratts, nbatts, nbdef, inputid; - int i, j, nbNs, attval; - size_t cur; - int nsNr = ctxt->nsNr; + int i, j, nbNs, nbTotalDef, attval, nsIndex, maxAtts; + int alloc = 0;
if (RAW != '<') return(NULL); NEXT1;
- cur = ctxt->input->cur - ctxt->input->base; inputid = ctxt->input->id; nbatts = 0; nratts = 0; nbdef = 0; nbNs = 0; + nbTotalDef = 0; attval = 0; - /* Forget any namespaces added during an earlier parse of this element. */ - ctxt->nsNr = nsNr;
- localname = xmlParseQName(ctxt, &prefix); - if (localname == NULL) { + if (xmlParserNsStartElement(ctxt->nsdb) < 0) { + xmlErrMemory(ctxt, NULL); + return(NULL); + } + + hlocalname = xmlParseQNameHashed(ctxt, &hprefix); + if (hlocalname.name == NULL) { xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, "StartTag: invalid element name\n"); return(NULL); } - *tlen = ctxt->input->cur - ctxt->input->base - cur; + localname = hlocalname.name; + prefix = hprefix.name;
/* * Now parse the attributes, it ends up with the ending @@ -9284,48 +9527,74 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, SKIP_BLANKS; GROW;
+ /* + * The ctxt->atts array will be ultimately passed to the SAX callback + * containing five xmlChar pointers for each attribute: + * + * [0] attribute name + * [1] attribute prefix + * [2] namespace URI + * [3] attribute value + * [4] end of attribute value + * + * To save memory, we reuse this array temporarily and store integers + * in these pointer variables. + * + * [0] attribute name + * [1] attribute prefix + * [2] hash value of attribute prefix, and later namespace index + * [3] for non-allocated values: ptrdiff_t offset into input buffer + * [4] for non-allocated values: ptrdiff_t offset into input buffer + * + * The ctxt->attallocs array contains an additional unsigned int for + * each attribute, containing the hash value of the attribute name + * and the alloc flag in bit 31. + */ + while (((RAW != '>') && ((RAW != '/') || (NXT(1) != '>')) && (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) { - int len = -1, alloc = 0; + int len = -1;
- attname = xmlParseAttribute2(ctxt, prefix, localname, - &aprefix, &attvalue, &len, &alloc); - if (attname == NULL) { + hattname = xmlParseAttribute2(ctxt, prefix, localname, + &haprefix, &attvalue, &len, + &alloc); + if (hattname.name == NULL) { xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "xmlParseStartTag: problem parsing attributes\n"); break; } if (attvalue == NULL) goto next_attr; + attname = hattname.name; + aprefix = haprefix.name; if (len < 0) len = xmlStrlen(attvalue);
if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) { - const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len); - xmlURIPtr uri; - - if (URL == NULL) { - xmlErrMemory(ctxt, "dictionary allocation failure"); - if ((attvalue != NULL) && (alloc != 0)) - xmlFree(attvalue); - localname = NULL; - goto done; + xmlHashedString huri; + xmlURIPtr parsedUri; + + huri = xmlDictLookupHashed(ctxt->dict, attvalue, len); + uri = huri.name; + if (uri == NULL) { + xmlErrMemory(ctxt, NULL); + goto next_attr; } - if (*URL != 0) { - uri = xmlParseURI((const char *) URL); - if (uri == NULL) { + if (*uri != 0) { + parsedUri = xmlParseURI((const char *) uri); + if (parsedUri == NULL) { xmlNsErr(ctxt, XML_WAR_NS_URI, "xmlns: '%s' is not a valid URI\n", - URL, NULL, NULL); + uri, NULL, NULL); } else { - if (uri->scheme == NULL) { + if (parsedUri->scheme == NULL) { xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE, "xmlns: URI %s is not absolute\n", - URL, NULL, NULL); + uri, NULL, NULL); } - xmlFreeURI(uri); + xmlFreeURI(parsedUri); } - if (URL == ctxt->str_xml_ns) { + if (uri == ctxt->str_xml_ns) { if (attname != ctxt->str_xml) { xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, "xml namespace URI cannot be the default namespace\n", @@ -9334,7 +9603,7 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, goto next_attr; } if ((len == 29) && - (xmlStrEqual(URL, + (xmlStrEqual(uri, BAD_CAST "http://www.w3.org/2000/xmlns/"))) { xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, "reuse of the xmlns namespace name is forbidden\n", @@ -9342,23 +9611,22 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, goto next_attr; } } - /* - * check that it's not a defined namespace - */ - for (j = 1;j <= nbNs;j++) - if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL) - break; - if (j <= nbNs) - xmlErrAttributeDup(ctxt, NULL, attname); - else - if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
+ if (xmlParserNsPush(ctxt, NULL, &huri, NULL, 0) > 0) + nbNs++; } else if (aprefix == ctxt->str_xmlns) { - const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len); - xmlURIPtr uri; + xmlHashedString huri; + xmlURIPtr parsedUri; + + huri = xmlDictLookupHashed(ctxt->dict, attvalue, len); + uri = huri.name; + if (uri == NULL) { + xmlErrMemory(ctxt, NULL); + goto next_attr; + }
if (attname == ctxt->str_xml) { - if (URL != ctxt->str_xml_ns) { + if (uri != ctxt->str_xml_ns) { xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, "xml namespace prefix mapped to wrong URI\n", NULL, NULL, NULL); @@ -9368,7 +9636,7 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, */ goto next_attr; } - if (URL == ctxt->str_xml_ns) { + if (uri == ctxt->str_xml_ns) { if (attname != ctxt->str_xml) { xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, "xml namespace URI mapped to wrong prefix\n", @@ -9383,48 +9651,40 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, goto next_attr; } if ((len == 29) && - (xmlStrEqual(URL, + (xmlStrEqual(uri, BAD_CAST "http://www.w3.org/2000/xmlns/"))) { xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, "reuse of the xmlns namespace name is forbidden\n", NULL, NULL, NULL); goto next_attr; } - if ((URL == NULL) || (URL[0] == 0)) { + if ((uri == NULL) || (uri[0] == 0)) { xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE, "xmlns:%s: Empty XML namespace is not allowed\n", attname, NULL, NULL); goto next_attr; } else { - uri = xmlParseURI((const char *) URL); - if (uri == NULL) { + parsedUri = xmlParseURI((const char *) uri); + if (parsedUri == NULL) { xmlNsErr(ctxt, XML_WAR_NS_URI, "xmlns:%s: '%s' is not a valid URI\n", - attname, URL, NULL); + attname, uri, NULL); } else { - if ((ctxt->pedantic) && (uri->scheme == NULL)) { + if ((ctxt->pedantic) && (parsedUri->scheme == NULL)) { xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE, "xmlns:%s: URI %s is not absolute\n", - attname, URL, NULL); + attname, uri, NULL); } - xmlFreeURI(uri); + xmlFreeURI(parsedUri); } }
- /* - * check that it's not a defined namespace - */ - for (j = 1;j <= nbNs;j++) - if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname) - break; - if (j <= nbNs) - xmlErrAttributeDup(ctxt, aprefix, attname); - else - if (nsPush(ctxt, attname, URL) > 0) nbNs++; - + if (xmlParserNsPush(ctxt, &hattname, &huri, NULL, 0) > 0) + nbNs++; } else { /* - * Add the pair to atts + * Populate attributes array, see above for repurposing + * of xmlChar pointers. */ if ((atts == NULL) || (nbatts + 5 > maxatts)) { if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) { @@ -9433,22 +9693,25 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref, maxatts = ctxt->maxatts; atts = ctxt->atts; } - ctxt->attallocs[nratts++] = alloc; + ctxt->attallocs[nratts++] = (hattname.hashValue & 0x7FFFFFFF) | + ((unsigned) alloc << 31); atts[nbatts++] = attname; atts[nbatts++] = aprefix; - /* - * The namespace URI field is used temporarily to point at the - * base of the current input buffer for non-alloced attributes. - * When the input buffer is reallocated, all the pointers become - * invalid, but they can be reconstructed later. - */ - if (alloc) - atts[nbatts++] = NULL; - else - atts[nbatts++] = ctxt->input->base; - atts[nbatts++] = attvalue; - attvalue += len; - atts[nbatts++] = attvalue; + atts[nbatts++] = (const xmlChar *) (size_t) haprefix.hashValue; + if (alloc) { + atts[nbatts++] = attvalue; + attvalue += len; + atts[nbatts++] = attvalue; + } else { + /* + * attvalue points into the input buffer which can be + * reallocated. Store differences to input->base instead. + * The pointers will be reconstructed later. + */ + atts[nbatts++] = (void *) (attvalue - BASE_PTR); + attvalue += len; + atts[nbatts++] = (void *) (attvalue - BASE_PTR); + } /* * tag if some deallocation is needed */ @@ -9482,175 +9745,286 @@ next_attr: goto done; }
- /* Reconstruct attribute value pointers. */ - for (i = 0, j = 0; j < nratts; i += 5, j++) { - if (atts[i+2] != NULL) { + /* + * Namespaces from default attributes + */ + if (ctxt->attsDefault != NULL) { + xmlDefAttrsPtr defaults; + + defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix); + if (defaults != NULL) { + for (i = 0; i < defaults->nbAttrs; i++) { + xmlDefAttr *attr = &defaults->attrs[i]; + + attname = attr->name.name; + aprefix = attr->prefix.name; + + if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) { + xmlParserEntityCheck(ctxt, attr->expandedSize); + + if (xmlParserNsPush(ctxt, NULL, &attr->value, NULL, 1) > 0) + nbNs++; + } else if (aprefix == ctxt->str_xmlns) { + xmlParserEntityCheck(ctxt, attr->expandedSize); + + if (xmlParserNsPush(ctxt, &attr->name, &attr->value, + NULL, 1) > 0) + nbNs++; + } else { + nbTotalDef += 1; + } + } + } + } + + /* + * Resolve attribute namespaces + */ + for (i = 0; i < nbatts; i += 5) { + attname = atts[i]; + aprefix = atts[i+1]; + + /* + * The default namespace does not apply to attribute names. + */ + if (aprefix == NULL) { + nsIndex = NS_INDEX_EMPTY; + } else if (aprefix == ctxt->str_xml) { + nsIndex = NS_INDEX_XML; + } else { + haprefix.name = aprefix; + haprefix.hashValue = (size_t) atts[i+2]; + nsIndex = xmlParserNsLookup(ctxt, &haprefix, NULL); + if (nsIndex == INT_MAX) { + xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, + "Namespace prefix %s for %s on %s is not defined\n", + aprefix, attname, localname); + nsIndex = NS_INDEX_EMPTY; + } + } + + atts[i+2] = (const xmlChar *) (ptrdiff_t) nsIndex; + } + + /* + * Maximum number of attributes including default attributes. + */ + maxAtts = nratts + nbTotalDef; + + /* + * Verify that attribute names are unique. + */ + if (maxAtts > 1) { + attrHashSize = 4; + while (attrHashSize / 2 < (unsigned) maxAtts) + attrHashSize *= 2; + + if (attrHashSize > ctxt->attrHashMax) { + xmlAttrHashBucket *tmp; + + tmp = xmlRealloc(ctxt->attrHash, attrHashSize * sizeof(tmp[0])); + if (tmp == NULL) { + xmlErrMemory(ctxt, NULL); + goto done; + } + + ctxt->attrHash = tmp; + ctxt->attrHashMax = attrHashSize; + } + + memset(ctxt->attrHash, -1, attrHashSize * sizeof(ctxt->attrHash[0])); + + for (i = 0, j = 0; j < nratts; i += 5, j++) { + const xmlChar *nsuri; + unsigned hashValue, nameHashValue, uriHashValue; + int res; + + attname = atts[i]; + aprefix = atts[i+1]; + nsIndex = (ptrdiff_t) atts[i+2]; + /* Hash values always have bit 31 set, see dict.c */ + nameHashValue = ctxt->attallocs[j] | 0x80000000; + + if (nsIndex == NS_INDEX_EMPTY) { + nsuri = NULL; + uriHashValue = URI_HASH_EMPTY; + } else if (nsIndex == NS_INDEX_XML) { + nsuri = ctxt->str_xml_ns; + uriHashValue = URI_HASH_XML; + } else { + nsuri = ctxt->nsTab[nsIndex * 2 + 1]; + uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue; + } + + hashValue = xmlDictCombineHash(nameHashValue, uriHashValue); + res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri, + hashValue, i); + if (res < 0) + continue; + /* - * Arithmetic on dangling pointers is technically undefined - * behavior, but well... + * [ WFC: Unique Att Spec ] + * No attribute name may appear more than once in the same + * start-tag or empty-element tag. + * As extended by the Namespace in XML REC. */ - const xmlChar *old = atts[i+2]; - atts[i+2] = NULL; /* Reset repurposed namespace URI */ - atts[i+3] = ctxt->input->base + (atts[i+3] - old); /* value */ - atts[i+4] = ctxt->input->base + (atts[i+4] - old); /* valuend */ + if (res < INT_MAX) { + if (aprefix == atts[res+1]) { + xmlErrAttributeDup(ctxt, aprefix, attname); + } else { + xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED, + "Namespaced Attribute %s in '%s' redefined\n", + attname, nsuri, NULL); + } + } } }
/* - * The attributes defaulting + * Default attributes */ if (ctxt->attsDefault != NULL) { xmlDefAttrsPtr defaults;
defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix); if (defaults != NULL) { - for (i = 0;i < defaults->nbAttrs;i++) { - attname = defaults->values[5 * i]; - aprefix = defaults->values[5 * i + 1]; + for (i = 0; i < defaults->nbAttrs; i++) { + xmlDefAttr *attr = &defaults->attrs[i]; + const xmlChar *nsuri; + unsigned hashValue, uriHashValue; + int res; + + attname = attr->name.name; + aprefix = attr->prefix.name; + + if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) + continue; + if (aprefix == ctxt->str_xmlns) + continue; + + if (aprefix == NULL) { + nsIndex = NS_INDEX_EMPTY; + nsuri = NULL; + uriHashValue = URI_HASH_EMPTY; + } if (aprefix == ctxt->str_xml) { + nsIndex = NS_INDEX_XML; + nsuri = ctxt->str_xml_ns; + uriHashValue = URI_HASH_XML; + } else if (aprefix != NULL) { + nsIndex = xmlParserNsLookup(ctxt, &attr->prefix, NULL); + if (nsIndex == INT_MAX) { + xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, + "Namespace prefix %s for %s on %s is not " + "defined\n", + aprefix, attname, localname); + nsIndex = NS_INDEX_EMPTY; + nsuri = NULL; + uriHashValue = URI_HASH_EMPTY; + } else { + nsuri = ctxt->nsTab[nsIndex * 2 + 1]; + uriHashValue = ctxt->nsdb->extra[nsIndex].uriHashValue; + } + }
- /* - * special work for namespaces defaulted defs - */ - if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) { - /* - * check that it's not a defined namespace - */ - for (j = 1;j <= nbNs;j++) - if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL) - break; - if (j <= nbNs) continue; - - nsname = xmlGetNamespace(ctxt, NULL); - if (nsname != defaults->values[5 * i + 2]) { - if (nsPush(ctxt, NULL, - defaults->values[5 * i + 2]) > 0) - nbNs++; - } - } else if (aprefix == ctxt->str_xmlns) { - /* - * check that it's not a defined namespace - */ - for (j = 1;j <= nbNs;j++) - if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname) - break; - if (j <= nbNs) continue; - - nsname = xmlGetNamespace(ctxt, attname); - if (nsname != defaults->values[5 * i + 2]) { - if (nsPush(ctxt, attname, - defaults->values[5 * i + 2]) > 0) - nbNs++; - } - } else { - /* - * check that it's not a defined attribute - */ - for (j = 0;j < nbatts;j+=5) { - if ((attname == atts[j]) && (aprefix == atts[j+1])) - break; - } - if (j < nbatts) continue; + /* + * Check whether the attribute exists + */ + if (maxAtts > 1) { + hashValue = xmlDictCombineHash(attr->name.hashValue, + uriHashValue); + res = xmlAttrHashInsert(ctxt, attrHashSize, attname, nsuri, + hashValue, nbatts); + if (res < 0) + continue; + if (res < INT_MAX) { + if (aprefix == atts[res+1]) + continue; + xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED, + "Namespaced Attribute %s in '%s' redefined\n", + attname, nsuri, NULL); + } + }
- if ((atts == NULL) || (nbatts + 5 > maxatts)) { - if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) { - localname = NULL; - goto done; - } - maxatts = ctxt->maxatts; - atts = ctxt->atts; - } - atts[nbatts++] = attname; - atts[nbatts++] = aprefix; - if (aprefix == NULL) - atts[nbatts++] = NULL; - else - atts[nbatts++] = xmlGetNamespace(ctxt, aprefix); - atts[nbatts++] = defaults->values[5 * i + 2]; - atts[nbatts++] = defaults->values[5 * i + 3]; - if ((ctxt->standalone == 1) && - (defaults->values[5 * i + 4] != NULL)) { - xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED, - "standalone: attribute %s on %s defaulted from external subset\n", - attname, localname); - } - nbdef++; - } + xmlParserEntityCheck(ctxt, attr->expandedSize); + + if ((atts == NULL) || (nbatts + 5 > maxatts)) { + if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) { + localname = NULL; + goto done; + } + maxatts = ctxt->maxatts; + atts = ctxt->atts; + } + + atts[nbatts++] = attname; + atts[nbatts++] = aprefix; + atts[nbatts++] = (const xmlChar *) (ptrdiff_t) nsIndex; + atts[nbatts++] = attr->value.name; + atts[nbatts++] = attr->valueEnd; + if ((ctxt->standalone == 1) && (attr->external != 0)) { + xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED, + "standalone: attribute %s on %s defaulted " + "from external subset\n", + attname, localname); + } + nbdef++; } } }
/* - * The attributes checkings + * Reconstruct attribute pointers */ - for (i = 0; i < nbatts;i += 5) { - /* - * The default namespace does not apply to attribute names. - */ - if (atts[i + 1] != NULL) { - nsname = xmlGetNamespace(ctxt, atts[i + 1]); - if (nsname == NULL) { - xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, - "Namespace prefix %s for %s on %s is not defined\n", - atts[i + 1], atts[i], localname); - } - atts[i + 2] = nsname; - } else - nsname = NULL; - /* - * [ WFC: Unique Att Spec ] - * No attribute name may appear more than once in the same - * start-tag or empty-element tag. - * As extended by the Namespace in XML REC. - */ - for (j = 0; j < i;j += 5) { - if (atts[i] == atts[j]) { - if (atts[i+1] == atts[j+1]) { - xmlErrAttributeDup(ctxt, atts[i+1], atts[i]); - break; - } - if ((nsname != NULL) && (atts[j + 2] == nsname)) { - xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED, - "Namespaced Attribute %s in '%s' redefined\n", - atts[i], nsname, NULL); - break; - } - } - } + for (i = 0, j = 0; i < nbatts; i += 5, j++) { + /* namespace URI */ + nsIndex = (ptrdiff_t) atts[i+2]; + if (nsIndex == INT_MAX) + atts[i+2] = NULL; + else if (nsIndex == INT_MAX - 1) + atts[i+2] = ctxt->str_xml_ns; + else + atts[i+2] = ctxt->nsTab[nsIndex * 2 + 1]; + + if ((j < nratts) && (ctxt->attallocs[j] & 0x80000000) == 0) { + atts[i+3] = BASE_PTR + (ptrdiff_t) atts[i+3]; /* value */ + atts[i+4] = BASE_PTR + (ptrdiff_t) atts[i+4]; /* valuend */ + } }
- nsname = xmlGetNamespace(ctxt, prefix); - if ((prefix != NULL) && (nsname == NULL)) { + uri = xmlParserNsLookupUri(ctxt, &hprefix); + if ((prefix != NULL) && (uri == NULL)) { xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE, "Namespace prefix %s on %s is not defined\n", prefix, localname, NULL); } *pref = prefix; - *URI = nsname; + *URI = uri;
/* - * SAX: Start of Element ! + * SAX callback */ if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) && (!ctxt->disableSAX)) { if (nbNs > 0) - ctxt->sax->startElementNs(ctxt->userData, localname, prefix, - nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs], + ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri, + nbNs, ctxt->nsTab + 2 * (ctxt->nsNr - nbNs), nbatts / 5, nbdef, atts); else - ctxt->sax->startElementNs(ctxt->userData, localname, prefix, - nsname, 0, NULL, nbatts / 5, nbdef, atts); + ctxt->sax->startElementNs(ctxt->userData, localname, prefix, uri, + 0, NULL, nbatts / 5, nbdef, atts); }
done: /* - * Free up attribute allocated strings if needed + * Free allocated attribute values */ if (attval != 0) { - for (i = 3,j = 0; j < nratts;i += 5,j++) - if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL)) - xmlFree((xmlChar *) atts[i]); + for (i = 0, j = 0; j < nratts; i += 5, j++) + if (ctxt->attallocs[j] & 0x80000000) + xmlFree((xmlChar *) atts[i+3]); }
+ *nbNsPtr = nbNs; return(localname); }
@@ -9720,7 +10094,7 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
spacePop(ctxt); if (tag->nsNr != 0) - nsPop(ctxt, tag->nsNr); + xmlParserNsPop(ctxt, tag->nsNr); }
/** @@ -9791,7 +10165,7 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { buf = tmp; size *= 2; } - COPY_BUF(rl,buf,len,r); + COPY_BUF(buf, len, r); if (len > maxLength) { xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED, "CData section too big found\n"); @@ -9845,7 +10219,7 @@ xmlParseContentInternal(xmlParserCtxtPtr ctxt) { int nameNr = ctxt->nameNr;
GROW; - while ((RAW != 0) && + while ((ctxt->input->cur < ctxt->input->end) && (ctxt->instate != XML_PARSER_EOF)) { const xmlChar *cur = ctxt->input->cur;
@@ -9922,7 +10296,9 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
xmlParseContentInternal(ctxt);
- if ((ctxt->instate != XML_PARSER_EOF) && (ctxt->nameNr > nameNr)) { + if ((ctxt->instate != XML_PARSER_EOF) && + (ctxt->errNo == XML_ERR_OK) && + (ctxt->nameNr > nameNr)) { const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1]; int line = ctxt->pushTab[ctxt->nameNr - 1].line; xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED, @@ -9956,12 +10332,14 @@ xmlParseElement(xmlParserCtxtPtr ctxt) { if (ctxt->instate == XML_PARSER_EOF) return;
- if (CUR == 0) { - const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1]; - int line = ctxt->pushTab[ctxt->nameNr - 1].line; - xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED, - "Premature end of data in tag %s line %d\n", - name, line, NULL); + if (ctxt->input->cur >= ctxt->input->end) { + if (ctxt->errNo == XML_ERR_OK) { + const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1]; + int line = ctxt->pushTab[ctxt->nameNr - 1].line; + xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED, + "Premature end of data in tag %s line %d\n", + name, line, NULL); + } return; }
@@ -9983,9 +10361,9 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) { const xmlChar *prefix = NULL; const xmlChar *URI = NULL; xmlParserNodeInfo node_info; - int line, tlen = 0; + int line; xmlNodePtr cur; - int nsNr = ctxt->nsNr; + int nbNs = 0;
if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { @@ -10014,7 +10392,7 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) { #ifdef LIBXML_SAX1_ENABLED if (ctxt->sax2) #endif /* LIBXML_SAX1_ENABLED */ - name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen); + name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs); #ifdef LIBXML_SAX1_ENABLED else name = xmlParseStartTag(ctxt); @@ -10025,7 +10403,7 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) { spacePop(ctxt); return(-1); } - nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr); + nameNsPush(ctxt, name, prefix, URI, line, nbNs); cur = ctxt->node;
#ifdef LIBXML_VALID_ENABLED @@ -10057,8 +10435,8 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) { } namePop(ctxt); spacePop(ctxt); - if (nsNr != ctxt->nsNr) - nsPop(ctxt, ctxt->nsNr - nsNr); + if (nbNs > 0) + xmlParserNsPop(ctxt, nbNs); if (cur != NULL && ctxt->record_info) { node_info.node = cur; node_info.end_pos = ctxt->input->consumed + @@ -10087,8 +10465,8 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) { nodePop(ctxt); namePop(ctxt); spacePop(ctxt); - if (nsNr != ctxt->nsNr) - nsPop(ctxt, ctxt->nsNr - nsNr); + if (nbNs > 0) + xmlParserNsPop(ctxt, nbNs); return(-1); }
@@ -10336,101 +10714,45 @@ xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) { xmlChar *encoding = NULL;
SKIP_BLANKS; - if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) { - SKIP(8); - SKIP_BLANKS; - if (RAW != '=') { - xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL); - return(NULL); - } - NEXT; - SKIP_BLANKS; - if (RAW == '"') { - NEXT; - encoding = xmlParseEncName(ctxt); - if (RAW != '"') { - xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); - xmlFree((xmlChar *) encoding); - return(NULL); - } else - NEXT; - } else if (RAW == '''){ - NEXT; - encoding = xmlParseEncName(ctxt); - if (RAW != ''') { - xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); - xmlFree((xmlChar *) encoding); - return(NULL); - } else - NEXT; - } else { - xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL); - } + if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g') == 0) + return(NULL);
- /* - * Non standard parsing, allowing the user to ignore encoding - */ - if (ctxt->options & XML_PARSE_IGNORE_ENC) { - xmlFree((xmlChar *) encoding); + SKIP(8); + SKIP_BLANKS; + if (RAW != '=') { + xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL); + return(NULL); + } + NEXT; + SKIP_BLANKS; + if (RAW == '"') { + NEXT; + encoding = xmlParseEncName(ctxt); + if (RAW != '"') { + xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); + xmlFree((xmlChar *) encoding); return(NULL); - } - - /* - * UTF-16 encoding switch has already taken place at this stage, - * more over the little-endian/big-endian selection is already done - */ - if ((encoding != NULL) && - ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) || - (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) { - /* - * If no encoding was passed to the parser, that we are - * using UTF-16 and no decoder is present i.e. the - * document is apparently UTF-8 compatible, then raise an - * encoding mismatch fatal error - */ - if ((ctxt->encoding == NULL) && - (ctxt->input->buf != NULL) && - (ctxt->input->buf->encoder == NULL)) { - xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING, - "Document labelled UTF-16 but has UTF-8 content\n"); - } - if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = encoding; - } - /* - * UTF-8 encoding is handled natively - */ - else if ((encoding != NULL) && - ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) || - (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) { - /* TODO: Check for encoding mismatch. */ - if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = encoding; - } - else if (encoding != NULL) { - xmlCharEncodingHandlerPtr handler; - - if (ctxt->input->encoding != NULL) - xmlFree((xmlChar *) ctxt->input->encoding); - ctxt->input->encoding = encoding; - - handler = xmlFindCharEncodingHandler((const char *) encoding); - if (handler != NULL) { - if (xmlSwitchToEncoding(ctxt, handler) < 0) { - /* failed to convert */ - ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING; - return(NULL); - } - } else { - xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "Unsupported encoding %s\n", encoding); - return(NULL); - } - } + } else + NEXT; + } else if (RAW == '''){ + NEXT; + encoding = xmlParseEncName(ctxt); + if (RAW != ''') { + xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL); + xmlFree((xmlChar *) encoding); + return(NULL); + } else + NEXT; + } else { + xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL); } - return(encoding); + + if (encoding == NULL) + return(NULL); + + xmlSetDeclaredEncoding(ctxt, encoding); + + return(ctxt->encoding); }
/** @@ -10539,7 +10861,8 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { * XML declaration but it does not have a standalone attribute. * It will be overwritten later if a standalone attribute is found. */ - ctxt->input->standalone = -2; + + ctxt->standalone = -2;
/* * We know that '<?xml' is here. @@ -10606,7 +10929,7 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { /* * We may have the standalone status. */ - if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) { + if ((ctxt->encoding != NULL) && (!IS_BLANK_CH(RAW))) { if ((RAW == '?') && (NXT(1) == '>')) { SKIP(2); return; @@ -10620,7 +10943,7 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) { GROW;
SKIP_BLANKS; - ctxt->input->standalone = xmlParseSDDecl(ctxt); + ctxt->standalone = xmlParseSDDecl(ctxt);
SKIP_BLANKS; if ((RAW == '?') && (NXT(1) == '>')) { @@ -10684,9 +11007,6 @@ xmlParseMisc(xmlParserCtxtPtr ctxt) {
int xmlParseDocument(xmlParserCtxtPtr ctxt) { - xmlChar start[4]; - xmlCharEncoding enc; - xmlInitParser();
if ((ctxt == NULL) || (ctxt->input == NULL)) @@ -10707,23 +11027,7 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { if (ctxt->instate == XML_PARSER_EOF) return(-1);
- if ((ctxt->encoding == NULL) && - ((ctxt->input->end - ctxt->input->cur) >= 4)) { - /* - * Get the 4 first bytes and decode the charset - * if enc != XML_CHAR_ENCODING_NONE - * plug some encoding conversion routines. - */ - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(&start[0], 4); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } - } - + xmlDetectEncoding(ctxt);
if (CUR == 0) { xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); @@ -10744,7 +11048,6 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { */ return(-1); } - ctxt->standalone = ctxt->input->standalone; SKIP_BLANKS; } else { ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); @@ -10815,9 +11118,15 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) { */ xmlParseMisc(ctxt);
- if (RAW != 0) { - xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); - } + if (ctxt->input->cur < ctxt->input->end) { + if (ctxt->errNo == XML_ERR_OK) + xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); + } else if ((ctxt->input->buf != NULL) && + (ctxt->input->buf->encoder != NULL) && + (!xmlBufIsEmpty(ctxt->input->buf->raw))) { + xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, + "Truncated multi-byte sequence at EOF\n"); + } ctxt->instate = XML_PARSER_EOF; }
@@ -10868,38 +11177,18 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
int xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) { - xmlChar start[4]; - xmlCharEncoding enc; - if ((ctxt == NULL) || (ctxt->input == NULL)) return(-1);
xmlDetectSAX2(ctxt);
- GROW; - /* * SAX: beginning of the document processing. */ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
- /* - * Get the 4 first bytes and decode the charset - * if enc != XML_CHAR_ENCODING_NONE - * plug some encoding conversion routines. - */ - if ((ctxt->input->end - ctxt->input->cur) >= 4) { - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(start, 4); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } - } - + xmlDetectEncoding(ctxt);
if (CUR == 0) { xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); @@ -11303,66 +11592,12 @@ xmlCheckCdataPush(const xmlChar *utf, int len, int complete) { static int xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { int ret = 0; - int tlen; size_t avail; xmlChar cur, next;
if (ctxt->input == NULL) return(0);
-#ifdef DEBUG_PUSH - switch (ctxt->instate) { - case XML_PARSER_EOF: - xmlGenericError(xmlGenericErrorContext, - "PP: try EOF\n"); break; - case XML_PARSER_START: - xmlGenericError(xmlGenericErrorContext, - "PP: try START\n"); break; - case XML_PARSER_MISC: - xmlGenericError(xmlGenericErrorContext, - "PP: try MISC\n");break; - case XML_PARSER_COMMENT: - xmlGenericError(xmlGenericErrorContext, - "PP: try COMMENT\n");break; - case XML_PARSER_PROLOG: - xmlGenericError(xmlGenericErrorContext, - "PP: try PROLOG\n");break; - case XML_PARSER_START_TAG: - xmlGenericError(xmlGenericErrorContext, - "PP: try START_TAG\n");break; - case XML_PARSER_CONTENT: - xmlGenericError(xmlGenericErrorContext, - "PP: try CONTENT\n");break; - case XML_PARSER_CDATA_SECTION: - xmlGenericError(xmlGenericErrorContext, - "PP: try CDATA_SECTION\n");break; - case XML_PARSER_END_TAG: - xmlGenericError(xmlGenericErrorContext, - "PP: try END_TAG\n");break; - case XML_PARSER_ENTITY_DECL: - xmlGenericError(xmlGenericErrorContext, - "PP: try ENTITY_DECL\n");break; - case XML_PARSER_ENTITY_VALUE: - xmlGenericError(xmlGenericErrorContext, - "PP: try ENTITY_VALUE\n");break; - case XML_PARSER_ATTRIBUTE_VALUE: - xmlGenericError(xmlGenericErrorContext, - "PP: try ATTRIBUTE_VALUE\n");break; - case XML_PARSER_DTD: - xmlGenericError(xmlGenericErrorContext, - "PP: try DTD\n");break; - case XML_PARSER_EPILOG: - xmlGenericError(xmlGenericErrorContext, - "PP: try EPILOG\n");break; - case XML_PARSER_PI: - xmlGenericError(xmlGenericErrorContext, - "PP: try PI\n");break; - case XML_PARSER_IGNORE: - xmlGenericError(xmlGenericErrorContext, - "PP: try IGNORE\n");break; - } -#endif - if ((ctxt->input != NULL) && (ctxt->input->cur - ctxt->input->base > 4096)) { xmlParserShrink(ctxt); @@ -11372,24 +11607,6 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1)) return(0);
- if (ctxt->input == NULL) break; - if (ctxt->input->buf != NULL) { - /* - * If we are operating on converted input, try to flush - * remaining chars to avoid them stalling in the non-converted - * buffer. - */ - if ((ctxt->input->buf->raw != NULL) && - (xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) { - size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, - ctxt->input); - size_t current = ctxt->input->cur - ctxt->input->base; - - xmlParserInputBufferPush(ctxt->input->buf, 0, ""); - xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, - base, current); - } - } avail = ctxt->input->end - ctxt->input->cur; if (avail < 1) goto done; @@ -11400,75 +11617,41 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { */ goto done; case XML_PARSER_START: - if (ctxt->charset == XML_CHAR_ENCODING_NONE) { - xmlChar start[4]; - xmlCharEncoding enc; + /* + * Very first chars read from the document flow. + */ + if ((!terminate) && (avail < 4)) + goto done;
- /* - * Very first chars read from the document flow. - */ - if (avail < 4) - goto done; + /* + * We need more bytes to detect EBCDIC code pages. + * See xmlDetectEBCDIC. + */ + if ((CMP4(CUR_PTR, 0x4C, 0x6F, 0xA7, 0x94)) && + (!terminate) && (avail < 200)) + goto done;
- /* - * Get the 4 first bytes and decode the charset - * if enc != XML_CHAR_ENCODING_NONE - * plug some encoding conversion routines, - * else xmlSwitchEncoding will set to (default) - * UTF8. - */ - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(start, 4); - /* - * We need more bytes to detect EBCDIC code pages. - * See xmlDetectEBCDIC. - */ - if ((enc == XML_CHAR_ENCODING_EBCDIC) && - (!terminate) && (avail < 200)) - goto done; - xmlSwitchEncoding(ctxt, enc); - break; - } + xmlDetectEncoding(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; + ctxt->instate = XML_PARSER_XML_DECL; + break;
- if (avail < 2) + case XML_PARSER_XML_DECL: + if ((!terminate) && (avail < 2)) goto done; cur = ctxt->input->cur[0]; next = ctxt->input->cur[1]; - if (cur == 0) { - if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) - ctxt->sax->setDocumentLocator(ctxt->userData, - &xmlDefaultSAXLocator); - xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); - xmlHaltParser(ctxt); -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering EOF\n"); -#endif - if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) - ctxt->sax->endDocument(ctxt->userData); - goto done; - } if ((cur == '<') && (next == '?')) { /* PI or XML decl */ - if (avail < 5) goto done; if ((!terminate) && (!xmlParseLookupString(ctxt, 2, "?>", 2))) goto done; - if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) - ctxt->sax->setDocumentLocator(ctxt->userData, - &xmlDefaultSAXLocator); if ((ctxt->input->cur[2] == 'x') && (ctxt->input->cur[3] == 'm') && (ctxt->input->cur[4] == 'l') && (IS_BLANK_CH(ctxt->input->cur[5]))) { ret += 5; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: Parsing XML Decl\n"); -#endif xmlParseXMLDecl(ctxt); if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) { /* @@ -11478,60 +11661,39 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { xmlHaltParser(ctxt); return(0); } - ctxt->standalone = ctxt->input->standalone; - if ((ctxt->encoding == NULL) && - (ctxt->input->encoding != NULL)) - ctxt->encoding = xmlStrdup(ctxt->input->encoding); - if ((ctxt->sax) && (ctxt->sax->startDocument) && - (!ctxt->disableSAX)) - ctxt->sax->startDocument(ctxt->userData); - ctxt->instate = XML_PARSER_MISC; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering MISC\n"); -#endif } else { ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); - if ((ctxt->sax) && (ctxt->sax->startDocument) && - (!ctxt->disableSAX)) - ctxt->sax->startDocument(ctxt->userData); - ctxt->instate = XML_PARSER_MISC; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering MISC\n"); -#endif } } else { - if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) - ctxt->sax->setDocumentLocator(ctxt->userData, - &xmlDefaultSAXLocator); ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION); if (ctxt->version == NULL) { xmlErrMemory(ctxt, NULL); break; } - if ((ctxt->sax) && (ctxt->sax->startDocument) && - (!ctxt->disableSAX)) - ctxt->sax->startDocument(ctxt->userData); - ctxt->instate = XML_PARSER_MISC; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering MISC\n"); -#endif } + if ((ctxt->sax) && (ctxt->sax->setDocumentLocator)) + ctxt->sax->setDocumentLocator(ctxt->userData, + &xmlDefaultSAXLocator); + if ((ctxt->sax) && (ctxt->sax->startDocument) && + (!ctxt->disableSAX)) + ctxt->sax->startDocument(ctxt->userData); + if (ctxt->instate == XML_PARSER_EOF) + goto done; + ctxt->instate = XML_PARSER_MISC; break; case XML_PARSER_START_TAG: { const xmlChar *name; const xmlChar *prefix = NULL; const xmlChar *URI = NULL; int line = ctxt->input->line; - int nsNr = ctxt->nsNr; + int nbNs = 0;
- if ((avail < 2) && (ctxt->inputNr == 1)) + if ((!terminate) && (avail < 2)) goto done; cur = ctxt->input->cur[0]; if (cur != '<') { - xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); + xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY, + "Start tag expected, '<' not found"); xmlHaltParser(ctxt); if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) ctxt->sax->endDocument(ctxt->userData); @@ -11548,7 +11710,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { #ifdef LIBXML_SAX1_ENABLED if (ctxt->sax2) #endif /* LIBXML_SAX1_ENABLED */ - name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen); + name = xmlParseStartTag2(ctxt, &prefix, &URI, &nbNs); #ifdef LIBXML_SAX1_ENABLED else name = xmlParseStartTag(ctxt); @@ -11585,8 +11747,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { (!ctxt->disableSAX)) ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI); - if (ctxt->nsNr - nsNr > 0) - nsPop(ctxt, ctxt->nsNr - nsNr); + if (nbNs > 0) + xmlParserNsPop(ctxt, nbNs); #ifdef LIBXML_SAX1_ENABLED } else { if ((ctxt->sax != NULL) && @@ -11595,78 +11757,87 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { ctxt->sax->endElement(ctxt->userData, name); #endif /* LIBXML_SAX1_ENABLED */ } - if (ctxt->instate == XML_PARSER_EOF) - goto done; spacePop(ctxt); - if (ctxt->nameNr == 0) { - ctxt->instate = XML_PARSER_EPILOG; - } else { - ctxt->instate = XML_PARSER_CONTENT; - } - break; - } - if (RAW == '>') { + } else if (RAW == '>') { NEXT; + nameNsPush(ctxt, name, prefix, URI, line, nbNs); } else { xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED, "Couldn't find end of Start Tag %s\n", name); nodePop(ctxt); spacePop(ctxt); + if (nbNs > 0) + xmlParserNsPop(ctxt, nbNs); } - nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
- ctxt->instate = XML_PARSER_CONTENT; + if (ctxt->instate == XML_PARSER_EOF) + goto done; + if (ctxt->nameNr == 0) + ctxt->instate = XML_PARSER_EPILOG; + else + ctxt->instate = XML_PARSER_CONTENT; break; } case XML_PARSER_CONTENT: { - if ((avail < 2) && (ctxt->inputNr == 1)) - goto done; cur = ctxt->input->cur[0]; - next = ctxt->input->cur[1];
- if ((cur == '<') && (next == '/')) { - ctxt->instate = XML_PARSER_END_TAG; - break; - } else if ((cur == '<') && (next == '?')) { - if ((!terminate) && - (!xmlParseLookupString(ctxt, 2, "?>", 2))) - goto done; - xmlParsePI(ctxt); - ctxt->instate = XML_PARSER_CONTENT; - } else if ((cur == '<') && (next != '!')) { - ctxt->instate = XML_PARSER_START_TAG; - break; - } else if ((cur == '<') && (next == '!') && - (ctxt->input->cur[2] == '-') && - (ctxt->input->cur[3] == '-')) { - if ((!terminate) && - (!xmlParseLookupString(ctxt, 4, "-->", 3))) - goto done; - xmlParseComment(ctxt); - ctxt->instate = XML_PARSER_CONTENT; - } else if ((cur == '<') && (ctxt->input->cur[1] == '!') && - (ctxt->input->cur[2] == '[') && - (ctxt->input->cur[3] == 'C') && - (ctxt->input->cur[4] == 'D') && - (ctxt->input->cur[5] == 'A') && - (ctxt->input->cur[6] == 'T') && - (ctxt->input->cur[7] == 'A') && - (ctxt->input->cur[8] == '[')) { - SKIP(9); - ctxt->instate = XML_PARSER_CDATA_SECTION; - break; - } else if ((cur == '<') && (next == '!') && - (avail < 9)) { - goto done; - } else if (cur == '<') { - xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, - "detected an error in element content\n"); - SKIP(1); + if (cur == '<') { + if ((!terminate) && (avail < 2)) + goto done; + next = ctxt->input->cur[1]; + + if (next == '/') { + ctxt->instate = XML_PARSER_END_TAG; + break; + } else if (next == '?') { + if ((!terminate) && + (!xmlParseLookupString(ctxt, 2, "?>", 2))) + goto done; + xmlParsePI(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; + ctxt->instate = XML_PARSER_CONTENT; + break; + } else if (next == '!') { + if ((!terminate) && (avail < 3)) + goto done; + next = ctxt->input->cur[2]; + + if (next == '-') { + if ((!terminate) && (avail < 4)) + goto done; + if (ctxt->input->cur[3] == '-') { + if ((!terminate) && + (!xmlParseLookupString(ctxt, 4, "-->", 3))) + goto done; + xmlParseComment(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; + ctxt->instate = XML_PARSER_CONTENT; + break; + } + } else if (next == '[') { + if ((!terminate) && (avail < 9)) + goto done; + if ((ctxt->input->cur[2] == '[') && + (ctxt->input->cur[3] == 'C') && + (ctxt->input->cur[4] == 'D') && + (ctxt->input->cur[5] == 'A') && + (ctxt->input->cur[6] == 'T') && + (ctxt->input->cur[7] == 'A') && + (ctxt->input->cur[8] == '[')) { + SKIP(9); + ctxt->instate = XML_PARSER_CDATA_SECTION; + break; + } + } + } } else if (cur == '&') { if ((!terminate) && (!xmlParseLookupChar(ctxt, ';'))) goto done; xmlParseReference(ctxt); + break; } else { /* TODO Avoid the extra copy, handle directly !!! */ /* @@ -11680,19 +11851,19 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { * callbacks between the push and pull versions * of the parser. */ - if ((ctxt->inputNr == 1) && - (avail < XML_PARSER_BIG_BUFFER_SIZE)) { + if (avail < XML_PARSER_BIG_BUFFER_SIZE) { if ((!terminate) && (!xmlParseLookupCharData(ctxt))) goto done; } ctxt->checkIndex = 0; xmlParseCharDataInternal(ctxt, !terminate); + break; } + + ctxt->instate = XML_PARSER_START_TAG; break; } case XML_PARSER_END_TAG: - if (avail < 2) - goto done; if ((!terminate) && (!xmlParseLookupChar(ctxt, '>'))) goto done; if (ctxt->sax2) { @@ -11703,9 +11874,9 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { else xmlParseEndTag1(ctxt, 0); #endif /* LIBXML_SAX1_ENABLED */ - if (ctxt->instate == XML_PARSER_EOF) { - /* Nothing */ - } else if (ctxt->nameNr == 0) { + if (ctxt->instate == XML_PARSER_EOF) + goto done; + if (ctxt->nameNr == 0) { ctxt->instate = XML_PARSER_EPILOG; } else { ctxt->instate = XML_PARSER_CONTENT; @@ -11785,119 +11956,105 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { } else if ((ctxt->sax != NULL) && (base > 0) && (!ctxt->disableSAX)) { if (ctxt->sax->cdataBlock != NULL) - ctxt->sax->cdataBlock(ctxt->userData, - ctxt->input->cur, base); - else if (ctxt->sax->characters != NULL) - 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; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering CONTENT\n"); -#endif - } - break; - } - case XML_PARSER_MISC: - case XML_PARSER_PROLOG: - case XML_PARSER_EPILOG: - SKIP_BLANKS; - avail = ctxt->input->end - ctxt->input->cur; - if (avail < 2) - goto done; - cur = ctxt->input->cur[0]; - next = ctxt->input->cur[1]; - if ((cur == '<') && (next == '?')) { - if ((!terminate) && - (!xmlParseLookupString(ctxt, 2, "?>", 2))) - goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: Parsing PI\n"); -#endif - xmlParsePI(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; - } else if ((cur == '<') && (next == '!') && - (ctxt->input->cur[2] == '-') && - (ctxt->input->cur[3] == '-')) { - if ((!terminate) && - (!xmlParseLookupString(ctxt, 4, "-->", 3))) - goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: Parsing Comment\n"); -#endif - xmlParseComment(ctxt); - if (ctxt->instate == XML_PARSER_EOF) - goto done; - } else if ((ctxt->instate == XML_PARSER_MISC) && - (cur == '<') && (next == '!') && - (ctxt->input->cur[2] == 'D') && - (ctxt->input->cur[3] == 'O') && - (ctxt->input->cur[4] == 'C') && - (ctxt->input->cur[5] == 'T') && - (ctxt->input->cur[6] == 'Y') && - (ctxt->input->cur[7] == 'P') && - (ctxt->input->cur[8] == 'E')) { - if ((!terminate) && (!xmlParseLookupGt(ctxt))) - goto done; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: Parsing internal subset\n"); -#endif - ctxt->inSubset = 1; - xmlParseDocTypeDecl(ctxt); + ctxt->sax->cdataBlock(ctxt->userData, + ctxt->input->cur, base); + else if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, + ctxt->input->cur, base); + } if (ctxt->instate == XML_PARSER_EOF) goto done; - if (RAW == '[') { - ctxt->instate = XML_PARSER_DTD; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering DTD\n"); -#endif - } else { - /* - * Create and update the external subset. - */ - ctxt->inSubset = 2; - if ((ctxt->sax != NULL) && (!ctxt->disableSAX) && - (ctxt->sax->externalSubset != NULL)) - ctxt->sax->externalSubset(ctxt->userData, - ctxt->intSubName, ctxt->extSubSystem, - ctxt->extSubURI); - ctxt->inSubset = 0; - xmlCleanSpecialAttr(ctxt); - ctxt->instate = XML_PARSER_PROLOG; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering PROLOG\n"); -#endif - } - } else if ((cur == '<') && (next == '!') && - (avail < - (ctxt->instate == XML_PARSER_MISC ? 9 : 4))) { - goto done; - } else if (ctxt->instate == XML_PARSER_EPILOG) { - xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); - xmlHaltParser(ctxt); -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering EOF\n"); -#endif - if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) - ctxt->sax->endDocument(ctxt->userData); + SKIPL(base + 3); + ctxt->instate = XML_PARSER_CONTENT; + } + break; + } + case XML_PARSER_MISC: + case XML_PARSER_PROLOG: + case XML_PARSER_EPILOG: + SKIP_BLANKS; + avail = ctxt->input->end - ctxt->input->cur; + if (avail < 1) goto done; + if (ctxt->input->cur[0] == '<') { + if ((!terminate) && (avail < 2)) + goto done; + next = ctxt->input->cur[1]; + if (next == '?') { + if ((!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)) + goto done; + + if (ctxt->input->cur[2] == '-') { + if ((!terminate) && (avail < 4)) + goto done; + if (ctxt->input->cur[3] == '-') { + if ((!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) { + if ((!terminate) && (avail < 9)) + goto done; + if ((ctxt->input->cur[2] == 'D') && + (ctxt->input->cur[3] == 'O') && + (ctxt->input->cur[4] == 'C') && + (ctxt->input->cur[5] == 'T') && + (ctxt->input->cur[6] == 'Y') && + (ctxt->input->cur[7] == 'P') && + (ctxt->input->cur[8] == 'E')) { + if ((!terminate) && (!xmlParseLookupGt(ctxt))) + goto done; + ctxt->inSubset = 1; + xmlParseDocTypeDecl(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; + if (RAW == '[') { + ctxt->instate = XML_PARSER_DTD; + } else { + /* + * Create and update the external subset. + */ + ctxt->inSubset = 2; + if ((ctxt->sax != NULL) && + (!ctxt->disableSAX) && + (ctxt->sax->externalSubset != NULL)) + ctxt->sax->externalSubset( + ctxt->userData, + ctxt->intSubName, + ctxt->extSubSystem, + ctxt->extSubURI); + ctxt->inSubset = 0; + xmlCleanSpecialAttr(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + goto done; + ctxt->instate = XML_PARSER_PROLOG; + } + break; + } + } + } + } + + if (ctxt->instate == XML_PARSER_EPILOG) { + if (ctxt->errNo == XML_ERR_OK) + xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); + ctxt->instate = XML_PARSER_EOF; + if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) + ctxt->sax->endDocument(ctxt->userData); } else { ctxt->instate = XML_PARSER_START_TAG; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering START_TAG\n"); -#endif } break; case XML_PARSER_DTD: { @@ -11916,90 +12073,16 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { if (ctxt->instate == XML_PARSER_EOF) goto done; ctxt->instate = XML_PARSER_PROLOG; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering PROLOG\n"); -#endif break; } - case XML_PARSER_COMMENT: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == COMMENT\n"); - ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_IGNORE: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == IGNORE"); - ctxt->instate = XML_PARSER_DTD; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering DTD\n"); -#endif - break; - case XML_PARSER_PI: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == PI\n"); - ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering CONTENT\n"); -#endif - break; - case XML_PARSER_ENTITY_DECL: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == ENTITY_DECL\n"); - ctxt->instate = XML_PARSER_DTD; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering DTD\n"); -#endif - break; - case XML_PARSER_ENTITY_VALUE: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == ENTITY_VALUE\n"); - ctxt->instate = XML_PARSER_CONTENT; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering DTD\n"); -#endif - break; - case XML_PARSER_ATTRIBUTE_VALUE: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == ATTRIBUTE_VALUE\n"); - ctxt->instate = XML_PARSER_START_TAG; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering START_TAG\n"); -#endif - break; - case XML_PARSER_SYSTEM_LITERAL: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == SYSTEM_LITERAL\n"); - ctxt->instate = XML_PARSER_START_TAG; -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, - "PP: entering START_TAG\n"); -#endif - break; - case XML_PARSER_PUBLIC_LITERAL: - xmlGenericError(xmlGenericErrorContext, - "PP: internal error, state == PUBLIC_LITERAL\n"); - ctxt->instate = XML_PARSER_START_TAG; -#ifdef DEBUG_PUSH + default: xmlGenericError(xmlGenericErrorContext, - "PP: entering START_TAG\n"); -#endif + "PP: internal error\n"); + ctxt->instate = XML_PARSER_EOF; break; } } done: -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret); -#endif return(ret); encoding_error: if (ctxt->input->end - ctxt->input->cur < 4) { @@ -12055,40 +12138,15 @@ 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)) { - size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); - size_t cur = ctxt->input->cur - ctxt->input->base; + size_t pos = ctxt->input->cur - ctxt->input->base; int res;
res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur); + xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - ctxt->errNo = XML_PARSER_EOF; + xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); xmlHaltParser(ctxt); - return (XML_PARSER_EOF); - } -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size); -#endif - - } else if (ctxt->instate != XML_PARSER_EOF) { - if ((ctxt->input != NULL) && ctxt->input->buf != NULL) { - xmlParserInputBufferPtr in = ctxt->input->buf; - if ((in->encoder != NULL) && (in->buffer != NULL) && - (in->raw != NULL)) { - int nbchars; - size_t base = xmlBufGetInputBase(in->buffer, ctxt->input); - size_t current = ctxt->input->cur - ctxt->input->base; - - nbchars = xmlCharEncInput(in, terminate); - xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current); - if (nbchars < 0) { - /* TODO 2.6.0 */ - xmlGenericError(xmlGenericErrorContext, - "xmlParseChunk: encoder error\n"); - xmlHaltParser(ctxt); - return(XML_ERR_INVALID_ENCODING); - } - } + return(ctxt->errNo); } }
@@ -12108,27 +12166,41 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
if ((end_in_lf == 1) && (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { - size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, - ctxt->input); - size_t current = ctxt->input->cur - ctxt->input->base; + size_t pos = ctxt->input->cur - ctxt->input->base; + int res;
- xmlParserInputBufferPush(ctxt->input->buf, 1, "\r"); - - xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, - base, current); + res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r"); + xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); + if (res < 0) { + xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlHaltParser(ctxt); + return(ctxt->errNo); + } } if (terminate) { /* * Check for termination */ - if ((ctxt->instate != XML_PARSER_EOF) && - (ctxt->instate != XML_PARSER_EPILOG)) { - xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); - } - if ((ctxt->instate == XML_PARSER_EPILOG) && - (ctxt->input->cur < ctxt->input->end)) { - xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL); - } + if ((ctxt->instate != XML_PARSER_EOF) && + (ctxt->instate != XML_PARSER_EPILOG)) { + if (ctxt->nameNr > 0) { + const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1]; + int line = ctxt->pushTab[ctxt->nameNr - 1].line; + xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED, + "Premature end of data in tag %s line %d\n", + name, line, NULL); + } else if (ctxt->instate == XML_PARSER_START) { + xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL); + } else { + xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY, + "Start tag expected, '<' not found\n"); + } + } else if ((ctxt->input->buf != NULL) && + (ctxt->input->buf->encoder != NULL) && + (!xmlBufIsEmpty(ctxt->input->buf->raw))) { + xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR, + "Truncated multi-byte sequence at EOF\n"); + } if (ctxt->instate != XML_PARSER_EOF) { if ((ctxt->sax) && (ctxt->sax->endDocument != NULL)) ctxt->sax->endDocument(ctxt->userData); @@ -12212,24 +12284,17 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, xmlBufResetInput(inputStream->buf->buffer, inputStream); inputPush(ctxt, inputStream);
- /* - * If the caller didn't provide an initial 'chunk' for determining - * the encoding, we set the context to XML_CHAR_ENCODING_NONE so - * that it can be automatically determined later - */ - ctxt->charset = XML_CHAR_ENCODING_NONE; - if ((size != 0) && (chunk != NULL) && (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { - size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); - size_t cur = ctxt->input->cur - ctxt->input->base; - - xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + size_t pos = ctxt->input->cur - ctxt->input->base; + int res;
- xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur); -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size); -#endif + res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); + if (res < 0) { + xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlHaltParser(ctxt); + } }
return(ctxt); @@ -12322,7 +12387,6 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, xmlDtdPtr ret = NULL; xmlParserCtxtPtr ctxt; xmlParserInputPtr pinput = NULL; - xmlChar start[4];
if (input == NULL) return(NULL); @@ -12360,13 +12424,6 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, xmlSwitchEncoding(ctxt, enc); }
- pinput->filename = NULL; - pinput->line = 1; - pinput->col = 1; - pinput->base = ctxt->input->cur; - pinput->cur = ctxt->input->cur; - pinput->free = NULL; - /* * let's parse that entity knowing it's an external subset. */ @@ -12380,22 +12437,7 @@ xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none", BAD_CAST "none", BAD_CAST "none");
- if ((enc == XML_CHAR_ENCODING_NONE) && - ((ctxt->input->end - ctxt->input->cur) >= 4)) { - /* - * Get the 4 first bytes and decode the charset - * if enc != XML_CHAR_ENCODING_NONE - * plug some encoding conversion routines. - */ - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(start, 4); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } - } + xmlDetectEncoding(ctxt);
xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
@@ -12443,7 +12485,6 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, xmlDtdPtr ret = NULL; xmlParserCtxtPtr ctxt; xmlParserInputPtr input = NULL; - xmlCharEncoding enc; xmlChar* systemIdCanonic;
if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL); @@ -12488,20 +12529,13 @@ xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID, xmlFree(systemIdCanonic); return(NULL); } - if ((ctxt->input->end - ctxt->input->cur) >= 4) { - enc = xmlDetectCharEncoding(ctxt->input->cur, 4); - xmlSwitchEncoding(ctxt, enc); - } + + xmlDetectEncoding(ctxt);
if (input->filename == NULL) input->filename = (char *) systemIdCanonic; else xmlFree(systemIdCanonic); - input->line = 1; - input->col = 1; - input->base = ctxt->input->cur; - input->cur = ctxt->input->cur; - input->free = NULL;
/* * let's parse that entity knowing it's an external subset. @@ -12629,8 +12663,6 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, xmlDocPtr newDoc; xmlNodePtr newRoot; xmlParserErrors ret = XML_ERR_OK; - xmlChar start[4]; - xmlCharEncoding enc;
if (((depth > 40) && ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) || @@ -12691,22 +12723,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, newRoot->doc = doc; }
- /* - * Get the 4 first bytes and decode the charset - * if enc != XML_CHAR_ENCODING_NONE - * plug some encoding conversion routines. - */ - GROW; - if ((ctxt->input->end - ctxt->input->cur) >= 4) { - start[0] = RAW; - start[1] = NXT(1); - start[2] = NXT(2); - start[3] = NXT(3); - enc = xmlDetectCharEncoding(start, 4); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } - } + xmlDetectEncoding(ctxt);
/* * Parse a possible text declaration first @@ -12923,11 +12940,9 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, xmlSAXHandlerPtr oldsax = NULL; xmlNodePtr content = NULL; xmlNodePtr last = NULL; - int size; xmlParserErrors ret = XML_ERR_OK; -#ifdef SAX2 - int i; -#endif + xmlHashedString hprefix, huri; + unsigned i;
if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) || (oldctxt->depth > 100)) { @@ -12942,9 +12957,7 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, if (string == NULL) return(XML_ERR_INTERNAL_ERROR);
- size = xmlStrlen(string); - - ctxt = xmlCreateMemoryParserCtxt((char *) string, size); + ctxt = xmlCreateDocParserCtxt(string); if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY); ctxt->nbErrors = oldctxt->nbErrors; ctxt->nbWarnings = oldctxt->nbWarnings; @@ -12959,12 +12972,44 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
-#ifdef SAX2 - /* propagate namespaces down the entity */ - for (i = 0;i < oldctxt->nsNr;i += 2) { - nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]); + /* + * Propagate namespaces down the entity + * + * Making entities and namespaces work correctly requires additional + * changes, see xmlParseReference. + */ + + /* Default namespace */ + hprefix.name = NULL; + hprefix.hashValue = 0; + huri.name = xmlParserNsLookupUri(oldctxt, &hprefix); + huri.hashValue = 0; + if (huri.name != NULL) + xmlParserNsPush(ctxt, NULL, &huri, NULL, 0); + + for (i = 0; i < oldctxt->nsdb->hashSize; i++) { + xmlParserNsBucket *bucket = &oldctxt->nsdb->hash[i]; + const xmlChar **ns; + xmlParserNsExtra *extra; + unsigned nsIndex; + + if ((bucket->hashValue != 0) && + (bucket->index != INT_MAX)) { + nsIndex = bucket->index; + ns = &oldctxt->nsTab[nsIndex * 2]; + extra = &oldctxt->nsdb->extra[nsIndex]; + + hprefix.name = ns[0]; + hprefix.hashValue = bucket->hashValue; + huri.name = ns[1]; + huri.hashValue = extra->uriHashValue; + /* + * Don't copy SAX data to avoid a use-after-free with XML reader. + * This matches the pre-2.12 behavior. + */ + xmlParserNsPush(ctxt, &hprefix, &huri, NULL, 0); + } } -#endif
oldsax = ctxt->sax; ctxt->sax = oldctxt->sax; @@ -12976,10 +13021,8 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, if (oldctxt->myDoc == NULL) { newDoc = xmlNewDoc(BAD_CAST "1.0"); if (newDoc == NULL) { - ctxt->sax = oldsax; - ctxt->dict = NULL; - xmlFreeParserCtxt(ctxt); - return(XML_ERR_INTERNAL_ERROR); + ret = XML_ERR_INTERNAL_ERROR; + goto error; } newDoc->properties = XML_DOC_INTERNAL; newDoc->dict = ctxt->dict; @@ -12992,13 +13035,8 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, } newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL); if (newRoot == NULL) { - ctxt->sax = oldsax; - ctxt->dict = NULL; - xmlFreeParserCtxt(ctxt); - if (newDoc != NULL) { - xmlFreeDoc(newDoc); - } - return(XML_ERR_INTERNAL_ERROR); + ret = XML_ERR_INTERNAL_ERROR; + goto error; } ctxt->myDoc->children = NULL; ctxt->myDoc->last = NULL; @@ -13081,6 +13119,8 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
oldctxt->nbErrors = ctxt->nbErrors; oldctxt->nbWarnings = ctxt->nbWarnings; + +error: ctxt->sax = oldsax; ctxt->dict = NULL; ctxt->attsDefault = NULL; @@ -13115,7 +13155,6 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt, xmlParserErrors xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, int options, xmlNodePtr *lst) { -#ifdef SAX2 xmlParserCtxtPtr ctxt; xmlDocPtr doc = NULL; xmlNodePtr fake, cur; @@ -13193,10 +13232,6 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, if (doc->encoding != NULL) { xmlCharEncodingHandlerPtr hdlr;
- if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding); - hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding); if (hdlr != NULL) { xmlSwitchToEncoding(ctxt, hdlr); @@ -13205,7 +13240,7 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, } }
- xmlCtxtUseOptionsInternal(ctxt, options, NULL); + xmlCtxtUseOptionsInternal(ctxt, options); xmlDetectSAX2(ctxt); ctxt->myDoc = doc; /* parsing in context, i.e. as within existing content */ @@ -13219,29 +13254,23 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, } xmlAddChild(node, fake);
- if (node->type == XML_ELEMENT_NODE) { + if (node->type == XML_ELEMENT_NODE) nodePush(ctxt, node); + + if ((ctxt->html == 0) && (node->type == XML_ELEMENT_NODE)) { /* * initialize the SAX2 namespaces stack */ cur = node; while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) { xmlNsPtr ns = cur->nsDef; - const xmlChar *iprefix, *ihref; + xmlHashedString hprefix, huri;
while (ns != NULL) { - if (ctxt->dict) { - iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1); - ihref = xmlDictLookup(ctxt->dict, ns->href, -1); - } else { - iprefix = ns->prefix; - ihref = ns->href; - } - - if (xmlGetNamespace(ctxt, iprefix) == NULL) { - nsPush(ctxt, iprefix, ihref); - nsnr++; - } + hprefix = xmlDictLookupHashed(ctxt->dict, ns->prefix, -1); + huri = xmlDictLookupHashed(ctxt->dict, ns->href, -1); + if (xmlParserNsPush(ctxt, &hprefix, &huri, ns, 1) > 0) + nsnr++; ns = ns->next; } cur = cur->parent; @@ -13262,7 +13291,7 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, #endif xmlParseContent(ctxt);
- nsPop(ctxt, nsnr); + xmlParserNsPop(ctxt, nsnr); if ((RAW == '<') && (NXT(1) == '/')) { xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL); } else if (RAW != 0) { @@ -13316,9 +13345,6 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, xmlFreeParserCtxt(ctxt);
return(ret); -#else /* !SAX2 */ - return(XML_ERR_INTERNAL_ERROR); -#endif }
#ifdef LIBXML_SAX1_ENABLED @@ -13355,7 +13381,6 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, xmlDocPtr newDoc; xmlSAXHandlerPtr oldsax = NULL; xmlNodePtr content, newRoot; - int size; int ret = 0;
if (depth > 40) { @@ -13368,9 +13393,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, if (string == NULL) return(-1);
- size = xmlStrlen(string); - - ctxt = xmlCreateMemoryParserCtxt((char *) string, size); + ctxt = xmlCreateDocParserCtxt(string); if (ctxt == NULL) return(-1); ctxt->userData = ctxt; if (sax != NULL) { @@ -13393,8 +13416,10 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); ctxt->dictNames = 1; + newDoc->dict = ctxt->dict; + xmlDictReference(newDoc->dict); } else { - xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL); + xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT); } /* doc == NULL is only supported for historic reasons */ if (doc != NULL) { @@ -13418,7 +13443,6 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, ctxt->myDoc = newDoc; } else { ctxt->myDoc = newDoc; - newDoc->children->doc = doc; /* Ensure that doc has XML spec namespace */ xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE); newDoc->oldNs = doc->oldNs; @@ -13680,7 +13704,7 @@ xmlCreateURLParserCtxt(const char *filename, int options) }
if (options) - xmlCtxtUseOptionsInternal(ctxt, options, NULL); + xmlCtxtUseOptionsInternal(ctxt, options); ctxt->linenumbers = 1;
inputStream = xmlLoadExternalEntity(filename, NULL, ctxt); @@ -14173,20 +14197,44 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
/** * xmlCreateDocParserCtxt: - * @cur: a pointer to an array of xmlChar + * @str: a pointer to an array of xmlChar * * Creates a parser context for an XML in-memory document. * * Returns the new parser context or NULL */ xmlParserCtxtPtr -xmlCreateDocParserCtxt(const xmlChar *cur) { - int len; +xmlCreateDocParserCtxt(const xmlChar *str) { + xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlParserInputBufferPtr buf;
- if (cur == NULL) + if (str == NULL) + return(NULL); + + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) + return(NULL); + + buf = xmlParserInputBufferCreateString(str); + if (buf == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + + input = xmlNewInputStream(ctxt); + if (input == NULL) { + xmlFreeParserInputBuffer(buf); + xmlFreeParserCtxt(ctxt); return(NULL); - len = xmlStrlen(cur); - return(xmlCreateMemoryParserCtxt((const char *)cur, len)); + } + + input->filename = NULL; + input->buf = buf; + xmlBufResetInput(input->buf->buffer, input); + + inputPush(ctxt, input); + return(ctxt); }
#ifdef LIBXML_SAX1_ENABLED @@ -14296,122 +14344,6 @@ xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func) } #endif /* LIBXML_LEGACY_ENABLED */
-/************************************************************************ - * * - * Miscellaneous * - * * - ************************************************************************/ - -static int xmlParserInitialized = 0; - -/** - * xmlInitParser: - * - * Initialization function for the XML parser. - * This is not reentrant. Call once before processing in case of - * use in multithreaded programs. - */ - -void -xmlInitParser(void) { - /* - * Note that the initialization code must not make memory allocations. - */ - if (xmlParserInitialized != 0) - return; - -#ifdef LIBXML_THREAD_ENABLED - __xmlGlobalInitMutexLock(); - if (xmlParserInitialized == 0) { -#endif -#if defined(_WIN32) && \ - !defined(LIBXML_THREAD_ALLOC_ENABLED) && \ - (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) - if (xmlFree == free) - atexit(xmlCleanupParser); -#endif - - xmlInitThreadsInternal(); - xmlInitGlobalsInternal(); - xmlInitMemoryInternal(); - __xmlInitializeDict(); - xmlInitEncodingInternal(); - xmlRegisterDefaultInputCallbacks(); -#ifdef LIBXML_OUTPUT_ENABLED - xmlRegisterDefaultOutputCallbacks(); -#endif /* LIBXML_OUTPUT_ENABLED */ -#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) - xmlInitXPathInternal(); -#endif - xmlParserInitialized = 1; -#ifdef LIBXML_THREAD_ENABLED - } - __xmlGlobalInitMutexUnlock(); -#endif -} - -/** - * xmlCleanupParser: - * - * This function name is somewhat misleading. It does not clean up - * parser state, it cleans up memory allocated by the library itself. - * It is a cleanup function for the XML library. It tries to reclaim all - * related global memory allocated for the library processing. - * It doesn't deallocate any document related memory. One should - * call xmlCleanupParser() only when the process has finished using - * the library and all XML/HTML documents built with it. - * See also xmlInitParser() which has the opposite function of preparing - * the library for operations. - * - * WARNING: if your application is multithreaded or has plugin support - * calling this may crash the application if another thread or - * a plugin is still using libxml2. It's sometimes very hard to - * guess if libxml2 is in use in the application, some libraries - * or plugins may use it without notice. In case of doubt abstain - * from calling this function or do it just before calling exit() - * to avoid leak reports from valgrind ! - */ - -void -xmlCleanupParser(void) { - if (!xmlParserInitialized) - return; - - xmlCleanupCharEncodingHandlers(); -#ifdef LIBXML_CATALOG_ENABLED - xmlCatalogCleanup(); -#endif - xmlCleanupDictInternal(); - xmlCleanupInputCallbacks(); -#ifdef LIBXML_OUTPUT_ENABLED - xmlCleanupOutputCallbacks(); -#endif -#ifdef LIBXML_SCHEMAS_ENABLED - xmlSchemaCleanupTypes(); - xmlRelaxNGCleanupTypes(); -#endif - xmlCleanupGlobalsInternal(); - xmlCleanupThreadsInternal(); - xmlCleanupMemoryInternal(); - xmlParserInitialized = 0; -} - -#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && \ - !defined(LIBXML_THREAD_ALLOC_ENABLED) && \ - !defined(LIBXML_STATIC) && \ - !defined(_WIN32) -static void -ATTRIBUTE_DESTRUCTOR -xmlDestructor(void) { - /* - * Calling custom deallocation functions in a destructor can cause - * problems, for example with Nokogiri. - */ - if (xmlFree == free) - xmlCleanupParser(); -} -#endif - /************************************************************************ * * * New set (2.6.0) of simpler and more flexible APIs * @@ -14469,6 +14401,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt) ctxt->name = NULL;
ctxt->nsNr = 0; + xmlParserNsReset(ctxt->nsdb);
DICT_FREE(ctxt->version); ctxt->version = NULL; @@ -14507,7 +14440,6 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt) ctxt->inSubset = 0; ctxt->errNo = XML_ERR_OK; ctxt->depth = 0; - ctxt->charset = XML_CHAR_ENCODING_UTF8; ctxt->catalogs = NULL; ctxt->sizeentities = 0; ctxt->sizeentcopy = 0; @@ -14550,15 +14482,11 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, { xmlParserInputPtr inputStream; xmlParserInputBufferPtr buf; - xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
if (ctxt == NULL) return(1);
- if ((encoding == NULL) && (chunk != NULL) && (size >= 4)) - enc = xmlDetectCharEncoding((const xmlChar *) chunk, size); - - buf = xmlAllocParserInputBuffer(enc); + buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); if (buf == NULL) return(1);
@@ -14593,24 +14521,21 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { - size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input); - size_t cur = ctxt->input->cur - ctxt->input->base; + size_t pos = ctxt->input->cur - ctxt->input->base; + int res;
- xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - - xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur); -#ifdef DEBUG_PUSH - xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size); -#endif + res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); + xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); + if (res < 0) { + xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlHaltParser(ctxt); + return(1); + } }
if (encoding != NULL) { xmlCharEncodingHandlerPtr hdlr;
- if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = xmlStrdup((const xmlChar *) encoding); - hdlr = xmlFindCharEncodingHandler(encoding); if (hdlr != NULL) { xmlSwitchToEncoding(ctxt, hdlr); @@ -14618,8 +14543,6 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING, "Unsupported encoding %s\n", BAD_CAST encoding); } - } else if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); }
return(0); @@ -14638,15 +14561,10 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, * in case of error. */ static int -xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding) +xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options) { if (ctxt == NULL) return(-1); - if (encoding != NULL) { - if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = xmlStrdup((const xmlChar *) encoding); - } if (options & XML_PARSE_RECOVER) { ctxt->recovery = 1; options -= XML_PARSE_RECOVER; @@ -14705,8 +14623,6 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi } #ifdef LIBXML_SAX1_ENABLED if (options & XML_PARSE_SAX1) { - ctxt->sax->startElement = xmlSAX2StartElement; - ctxt->sax->endElement = xmlSAX2EndElement; ctxt->sax->startElementNs = NULL; ctxt->sax->endElementNs = NULL; ctxt->sax->initialized = 1; @@ -14781,7 +14697,26 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi int xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options) { - return(xmlCtxtUseOptionsInternal(ctxt, options, NULL)); + return(xmlCtxtUseOptionsInternal(ctxt, options)); +} + +/** + * xmlCtxtSetMaxAmplification: + * @ctxt: an XML parser context + * @maxAmpl: maximum amplification factor + * + * To protect against exponential entity expansion ("billion laughs"), the + * size of serialized output is (roughly) limited to the input size + * multiplied by this factor. The default value is 5. + * + * When working with documents making heavy use of entity expansion, it can + * be necessary to increase the value. For security reasons, this should only + * be considered when processing trusted input. + */ +void +xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl) +{ + ctxt->maxAmpl = maxAmpl; }
/** @@ -14802,7 +14737,7 @@ xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding, { xmlDocPtr ret;
- xmlCtxtUseOptionsInternal(ctxt, options, encoding); + xmlCtxtUseOptionsInternal(ctxt, options); if (encoding != NULL) { xmlCharEncodingHandlerPtr hdlr;
@@ -15001,7 +14936,7 @@ xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, /** * xmlCtxtReadDoc: * @ctxt: an XML parser context - * @cur: a pointer to a zero terminated string + * @str: a pointer to a zero terminated string * @URL: the base URL to use for the document * @encoding: the document encoding, or NULL * @options: a combination of xmlParserOption @@ -15012,13 +14947,33 @@ xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, * Returns the resulting document tree */ xmlDocPtr -xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur, +xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str, const char *URL, const char *encoding, int options) { - if (cur == NULL) + xmlParserInputBufferPtr input; + xmlParserInputPtr stream; + + if (ctxt == NULL) + return (NULL); + if (str == NULL) return (NULL); - return (xmlCtxtReadMemory(ctxt, (const char *) cur, xmlStrlen(cur), URL, - encoding, options)); + xmlInitParser(); + + xmlCtxtReset(ctxt); + + input = xmlParserInputBufferCreateString(str); + if (input == NULL) { + return(NULL); + } + + stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); + if (stream == NULL) { + xmlFreeParserInputBuffer(input); + return(NULL); + } + + inputPush(ctxt, stream); + return (xmlDoRead(ctxt, URL, encoding, options, 1)); }
/** @@ -15084,7 +15039,8 @@ xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
xmlCtxtReset(ctxt);
- input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); + input = xmlParserInputBufferCreateStatic(buffer, size, + XML_CHAR_ENCODING_NONE); if (input == NULL) { return(NULL); } diff --git a/libs/xml2/parserInternals.c b/libs/xml2/parserInternals.c index c36bbfb62c6..fca46c7feae 100644 --- a/libs/xml2/parserInternals.c +++ b/libs/xml2/parserInternals.c @@ -24,24 +24,20 @@ #include <libxml/tree.h> #include <libxml/parser.h> #include <libxml/parserInternals.h> -#include <libxml/valid.h> #include <libxml/entities.h> #include <libxml/xmlerror.h> #include <libxml/encoding.h> -#include <libxml/valid.h> #include <libxml/xmlIO.h> #include <libxml/uri.h> #include <libxml/dict.h> -#include <libxml/SAX.h> +#include <libxml/xmlsave.h> #ifdef LIBXML_CATALOG_ENABLED #include <libxml/catalog.h> #endif -#include <libxml/globals.h> #include <libxml/chvalid.h>
#define CUR(ctxt) ctxt->input->cur #define END(ctxt) ctxt->input->end -#define VALID_CTXT(ctxt) (CUR(ctxt) <= END(ctxt))
#include "private/buf.h" #include "private/enc.h" @@ -49,6 +45,12 @@ #include "private/io.h" #include "private/parser.h"
+/* + * XML_MAX_AMPLIFICATION_DEFAULT is the default maximum allowed amplification + * factor of serialized output after entity expansion. + */ +#define XML_MAX_AMPLIFICATION_DEFAULT 5 + /* * Various global defaults for parsing */ @@ -175,6 +177,228 @@ xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str) } }
+/** + * xmlFatalErr: + * @ctxt: an XML parser context + * @error: the error number + * @info: extra information string + * + * Handle a fatal parser error, i.e. violating Well-Formedness constraints + */ +void +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"; + break; + case XML_ERR_INVALID_DEC_CHARREF: + errmsg = "CharRef: invalid decimal value"; + break; + case XML_ERR_INVALID_CHARREF: + errmsg = "CharRef: invalid value"; + break; + case XML_ERR_INTERNAL_ERROR: + errmsg = "internal error"; + break; + case XML_ERR_PEREF_AT_EOF: + errmsg = "PEReference at end of document"; + break; + case XML_ERR_PEREF_IN_PROLOG: + errmsg = "PEReference in prolog"; + break; + case XML_ERR_PEREF_IN_EPILOG: + errmsg = "PEReference in epilog"; + break; + case XML_ERR_PEREF_NO_NAME: + errmsg = "PEReference: no name"; + break; + case XML_ERR_PEREF_SEMICOL_MISSING: + errmsg = "PEReference: expecting ';'"; + break; + case XML_ERR_ENTITY_LOOP: + errmsg = "Detected an entity reference loop"; + break; + case XML_ERR_ENTITY_NOT_STARTED: + errmsg = "EntityValue: " or ' expected"; + break; + case XML_ERR_ENTITY_PE_INTERNAL: + errmsg = "PEReferences forbidden in internal subset"; + break; + case XML_ERR_ENTITY_NOT_FINISHED: + errmsg = "EntityValue: " or ' expected"; + break; + case XML_ERR_ATTRIBUTE_NOT_STARTED: + errmsg = "AttValue: " or ' expected"; + break; + case XML_ERR_LT_IN_ATTRIBUTE: + errmsg = "Unescaped '<' not allowed in attributes values"; + break; + case XML_ERR_LITERAL_NOT_STARTED: + errmsg = "SystemLiteral " or ' expected"; + break; + case XML_ERR_LITERAL_NOT_FINISHED: + errmsg = "Unfinished System or Public ID " or ' expected"; + break; + case XML_ERR_MISPLACED_CDATA_END: + errmsg = "Sequence ']]>' not allowed in content"; + break; + case XML_ERR_URI_REQUIRED: + errmsg = "SYSTEM or PUBLIC, the URI is missing"; + break; + case XML_ERR_PUBID_REQUIRED: + errmsg = "PUBLIC, the Public Identifier is missing"; + break; + case XML_ERR_HYPHEN_IN_COMMENT: + errmsg = "Comment must not contain '--' (double-hyphen)"; + break; + case XML_ERR_PI_NOT_STARTED: + errmsg = "xmlParsePI : no target name"; + break; + case XML_ERR_RESERVED_XML_NAME: + errmsg = "Invalid PI name"; + break; + case XML_ERR_NOTATION_NOT_STARTED: + errmsg = "NOTATION: Name expected here"; + break; + case XML_ERR_NOTATION_NOT_FINISHED: + errmsg = "'>' required to close NOTATION declaration"; + break; + case XML_ERR_VALUE_REQUIRED: + errmsg = "Entity value required"; + break; + case XML_ERR_URI_FRAGMENT: + errmsg = "Fragment not allowed"; + break; + case XML_ERR_ATTLIST_NOT_STARTED: + errmsg = "'(' required to start ATTLIST enumeration"; + break; + case XML_ERR_NMTOKEN_REQUIRED: + errmsg = "NmToken expected in ATTLIST enumeration"; + break; + case XML_ERR_ATTLIST_NOT_FINISHED: + errmsg = "')' required to finish ATTLIST enumeration"; + break; + case XML_ERR_MIXED_NOT_STARTED: + errmsg = "MixedContentDecl : '|' or ')*' expected"; + break; + case XML_ERR_PCDATA_REQUIRED: + errmsg = "MixedContentDecl : '#PCDATA' expected"; + break; + case XML_ERR_ELEMCONTENT_NOT_STARTED: + errmsg = "ContentDecl : Name or '(' expected"; + break; + case XML_ERR_ELEMCONTENT_NOT_FINISHED: + errmsg = "ContentDecl : ',' '|' or ')' expected"; + break; + case XML_ERR_PEREF_IN_INT_SUBSET: + errmsg = + "PEReference: forbidden within markup decl in internal subset"; + break; + case XML_ERR_GT_REQUIRED: + errmsg = "expected '>'"; + break; + case XML_ERR_CONDSEC_INVALID: + errmsg = "XML conditional section '[' expected"; + break; + case XML_ERR_EXT_SUBSET_NOT_FINISHED: + errmsg = "Content error in the external subset"; + break; + case XML_ERR_CONDSEC_INVALID_KEYWORD: + errmsg = + "conditional section INCLUDE or IGNORE keyword expected"; + break; + case XML_ERR_CONDSEC_NOT_FINISHED: + errmsg = "XML conditional section not closed"; + break; + case XML_ERR_XMLDECL_NOT_STARTED: + errmsg = "Text declaration '<?xml' required"; + break; + case XML_ERR_XMLDECL_NOT_FINISHED: + errmsg = "parsing XML declaration: '?>' expected"; + break; + case XML_ERR_EXT_ENTITY_STANDALONE: + errmsg = "external parsed entities cannot be standalone"; + break; + case XML_ERR_ENTITYREF_SEMICOL_MISSING: + errmsg = "EntityRef: expecting ';'"; + break; + case XML_ERR_DOCTYPE_NOT_FINISHED: + errmsg = "DOCTYPE improperly terminated"; + break; + case XML_ERR_LTSLASH_REQUIRED: + errmsg = "EndTag: '</' not found"; + break; + case XML_ERR_EQUAL_REQUIRED: + errmsg = "expected '='"; + break; + case XML_ERR_STRING_NOT_CLOSED: + errmsg = "String not closed expecting " or '"; + break; + case XML_ERR_STRING_NOT_STARTED: + errmsg = "String not started expecting ' or ""; + break; + case XML_ERR_ENCODING_NAME: + errmsg = "Invalid XML encoding name"; + break; + case XML_ERR_STANDALONE_VALUE: + errmsg = "standalone accepts only 'yes' or 'no'"; + break; + case XML_ERR_DOCUMENT_EMPTY: + errmsg = "Document is empty"; + break; + case XML_ERR_DOCUMENT_END: + errmsg = "Extra content at the end of the document"; + break; + case XML_ERR_NOT_WELL_BALANCED: + errmsg = "chunk is not well balanced"; + break; + case XML_ERR_EXTRA_CONTENT: + errmsg = "extra content at the end of well balanced chunk"; + break; + case XML_ERR_VERSION_MISSING: + errmsg = "Malformed declaration expecting version"; + break; + case XML_ERR_NAME_TOO_LONG: + errmsg = "Name too long"; + break; + case XML_ERR_INVALID_ENCODING: + errmsg = "Invalid bytes in character encoding"; + break; + case XML_IO_UNKNOWN: + errmsg = "I/O error"; + break; +#if 0 + case: + errmsg = ""; + break; +#endif + 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); + } 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; + } +} + /** * xmlErrEncodingInt: * @ctxt: an XML parser context @@ -223,41 +447,9 @@ xmlIsLetter(int c) { * * ************************************************************************/
-/* #define DEBUG_INPUT */ -/* #define DEBUG_STACK */ -/* #define DEBUG_PUSH */ - - /* we need to keep enough input to show errors in context */ #define LINE_LEN 80
-#ifdef DEBUG_INPUT -#define CHECK_BUFFER(in) check_buffer(in) - -static -void check_buffer(xmlParserInputPtr in) { - if (in->base != xmlBufContent(in->buf->buffer)) { - xmlGenericError(xmlGenericErrorContext, - "xmlParserInput: base mismatch problem\n"); - } - if (in->cur < in->base) { - xmlGenericError(xmlGenericErrorContext, - "xmlParserInput: cur < base problem\n"); - } - if (in->cur > in->base + xmlBufUse(in->buf->buffer)) { - xmlGenericError(xmlGenericErrorContext, - "xmlParserInput: cur > base + use problem\n"); - } - xmlGenericError(xmlGenericErrorContext,"buffer %p : content %x, cur %d, use %d\n", - (void *) in, (int) xmlBufContent(in->buf->buffer), - in->cur - in->base, xmlBufUse(in->buf->buffer)); -} - -#else -#define CHECK_BUFFER(in) -#endif - - /** * xmlHaltParser: * @ctxt: an XML parser context @@ -310,6 +502,10 @@ xmlParserInputRead(xmlParserInputPtr in ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUS /** * xmlParserGrow: * @ctxt: an XML parser context + * + * Grow the input buffer. + * + * Returns the number of bytes read or -1 in case of error. */ int xmlParserGrow(xmlParserCtxtPtr ctxt) { @@ -322,16 +518,18 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) { if (buf == NULL) return(0); /* Don't grow push parser buffer. */ - if (ctxt->progressive) + if ((ctxt->progressive) && (ctxt->inputNr <= 1)) return(0); /* Don't grow memory buffers. */ if ((buf->encoder == NULL) && (buf->readcallback == NULL)) return(0); + if (buf->error != 0) + return(-1);
if (((curEnd > XML_MAX_LOOKUP_LIMIT) || (curBase > XML_MAX_LOOKUP_LIMIT)) && ((ctxt->options & XML_PARSE_HUGE) == 0)) { - xmlErrInternal(ctxt, "Huge input lookup", NULL); + xmlErrMemory(ctxt, "Huge input lookup"); xmlHaltParser(ctxt); return(-1); } @@ -340,12 +538,13 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) { return(0);
ret = xmlParserInputBufferGrow(buf, INPUT_CHUNK); - xmlBufSetInputBaseCur(buf->buffer, in, 0, curBase); + xmlBufUpdateInput(buf->buffer, in, curBase);
- /* TODO: Get error code from xmlParserInputBufferGrow */ if (ret < 0) { - xmlErrInternal(ctxt, "Growing input buffer", NULL); - xmlHaltParser(ctxt); + 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); @@ -370,9 +569,6 @@ xmlParserInputGrow(xmlParserInputPtr in, int len) { size_t indx;
if ((in == NULL) || (len < 0)) return(-1); -#ifdef DEBUG_INPUT - xmlGenericError(xmlGenericErrorContext, "Grow\n"); -#endif if (in->buf == NULL) return(-1); if (in->base == NULL) return(-1); if (in->cur == NULL) return(-1); @@ -382,13 +578,8 @@ xmlParserInputGrow(xmlParserInputPtr in, int len) { if ((in->buf->encoder == NULL) && (in->buf->readcallback == NULL)) return(0);
- CHECK_BUFFER(in); - indx = in->cur - in->base; if (xmlBufUse(in->buf->buffer) > (unsigned int) indx + INPUT_CHUNK) { - - CHECK_BUFFER(in); - return(0); } ret = xmlParserInputBufferGrow(in->buf, len); @@ -403,14 +594,14 @@ xmlParserInputGrow(xmlParserInputPtr in, int len) { in->cur = in->base + indx; in->end = xmlBufEnd(in->buf->buffer);
- CHECK_BUFFER(in); - return(ret); }
/** * xmlParserShrink: * @ctxt: an XML parser context + * + * Shrink the input buffer. */ void xmlParserShrink(xmlParserCtxtPtr ctxt) { @@ -418,10 +609,12 @@ xmlParserShrink(xmlParserCtxtPtr ctxt) { xmlParserInputBufferPtr buf = in->buf; size_t used;
+ if (buf == NULL) + return; /* Don't shrink pull parser memory buffers. */ - if ((buf == NULL) || - ((ctxt->progressive == 0) && - (buf->encoder == NULL) && (buf->readcallback == NULL))) + if (((ctxt->progressive == 0) || (ctxt->inputNr > 1)) && + (buf->encoder == NULL) && + (buf->readcallback == NULL)) return;
used = in->cur - in->base; @@ -442,7 +635,7 @@ xmlParserShrink(xmlParserCtxtPtr ctxt) { } }
- xmlBufSetInputBaseCur(buf->buffer, in, 0, used); + xmlBufUpdateInput(buf->buffer, in, used); }
/** @@ -458,17 +651,12 @@ xmlParserInputShrink(xmlParserInputPtr in) { size_t used; size_t ret;
-#ifdef DEBUG_INPUT - xmlGenericError(xmlGenericErrorContext, "Shrink\n"); -#endif if (in == NULL) return; if (in->buf == NULL) return; if (in->base == NULL) return; if (in->cur == NULL) return; if (in->buf->buffer == NULL) return;
- CHECK_BUFFER(in); - used = in->cur - in->base; /* * Do not shrink on large buffers whose only a tiny fraction @@ -500,8 +688,6 @@ xmlParserInputShrink(xmlParserInputPtr in) { } in->cur = in->base + used; in->end = xmlBufEnd(in->buf->buffer); - - CHECK_BUFFER(in); }
/************************************************************************ @@ -522,136 +708,103 @@ xmlParserInputShrink(xmlParserInputPtr in) { void xmlNextChar(xmlParserCtxtPtr ctxt) { + const unsigned char *cur; + size_t avail; + int c; + if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) || (ctxt->input == NULL)) return;
- if (!(VALID_CTXT(ctxt))) { - xmlErrInternal(ctxt, "Parser input data memory error\n", NULL); - ctxt->errNo = XML_ERR_INTERNAL_ERROR; - xmlStopParser(ctxt); - return; - } + avail = ctxt->input->end - ctxt->input->cur;
- if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) { - if (xmlParserGrow(ctxt) < 0) - return; - if (ctxt->input->cur >= ctxt->input->end) + if (avail < INPUT_CHUNK) { + xmlParserGrow(ctxt); + if ((ctxt->instate == XML_PARSER_EOF) || + (ctxt->input->cur >= ctxt->input->end)) return; + avail = ctxt->input->end - ctxt->input->cur; }
- if (ctxt->charset == XML_CHAR_ENCODING_UTF8) { - const unsigned char *cur; - unsigned char c; + cur = ctxt->input->cur; + c = *cur;
- /* - * 2.11 End-of-Line Handling - * the literal two-character sequence "#xD#xA" or a standalone - * literal #xD, an XML processor must pass to the application - * the single character #xA. - */ - if (*(ctxt->input->cur) == '\n') { - ctxt->input->line++; ctxt->input->col = 1; - } else + if (c < 0x80) { + if (c == '\n') { + ctxt->input->cur++; + ctxt->input->line++; + ctxt->input->col = 1; + } else if (c == '\r') { + /* + * 2.11 End-of-Line Handling + * the literal two-character sequence "#xD#xA" or a standalone + * literal #xD, an XML processor must pass to the application + * the single character #xA. + */ + ctxt->input->cur += ((cur[1] == '\n') ? 2 : 1); + ctxt->input->line++; + ctxt->input->col = 1; + return; + } else { + ctxt->input->cur++; ctxt->input->col++; + } + } else { + ctxt->input->col++;
- /* - * We are supposed to handle UTF8, check it's valid - * From rfc2044: encoding of the Unicode values on UTF-8: - * - * UCS-4 range (hex.) UTF-8 octet sequence (binary) - * 0000 0000-0000 007F 0xxxxxxx - * 0000 0080-0000 07FF 110xxxxx 10xxxxxx - * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - * - * Check for the 0x110000 limit too - */ - cur = ctxt->input->cur; - - c = *cur; - if (c & 0x80) { - size_t avail; - - if (c == 0xC0) - goto encoding_error; + if ((avail < 2) || (cur[1] & 0xc0) != 0x80) + goto encoding_error;
- avail = ctxt->input->end - ctxt->input->cur; + if (c < 0xe0) { + /* 2-byte code */ + if (c < 0xc2) + goto encoding_error; + ctxt->input->cur += 2; + } else { + unsigned int val = (c << 8) | cur[1];
- if ((avail < 2) || (cur[1] & 0xc0) != 0x80) + if ((avail < 3) || (cur[2] & 0xc0) != 0x80) goto encoding_error; - if ((c & 0xe0) == 0xe0) { - unsigned int val;
- if ((avail < 3) || (cur[2] & 0xc0) != 0x80) + if (c < 0xf0) { + /* 3-byte code */ + if ((val < 0xe0a0) || ((val >= 0xeda0) && (val < 0xee00))) + goto encoding_error; + ctxt->input->cur += 3; + } else { + if ((avail < 4) || ((cur[3] & 0xc0) != 0x80)) goto encoding_error; - if ((c & 0xf0) == 0xf0) { - if (((c & 0xf8) != 0xf0) || - (avail < 4) || ((cur[3] & 0xc0) != 0x80)) - goto encoding_error; - /* 4-byte code */ - ctxt->input->cur += 4; - val = (cur[0] & 0x7) << 18; - val |= (cur[1] & 0x3f) << 12; - val |= (cur[2] & 0x3f) << 6; - val |= cur[3] & 0x3f; - } else { - /* 3-byte code */ - ctxt->input->cur += 3; - val = (cur[0] & 0xf) << 12; - val |= (cur[1] & 0x3f) << 6; - val |= cur[2] & 0x3f; - } - if (((val > 0xd7ff) && (val < 0xe000)) || - ((val > 0xfffd) && (val < 0x10000)) || - (val >= 0x110000)) { - xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, - "Char 0x%X out of allowed range\n", - val); - } - } else - /* 2-byte code */ - ctxt->input->cur += 2; - } else - /* 1-byte code */ - ctxt->input->cur++; - } else { - /* - * Assume it's a fixed length encoding (1) with - * a compatible encoding for the ASCII set, since - * XML constructs only use < 128 chars - */
- if (*(ctxt->input->cur) == '\n') { - ctxt->input->line++; ctxt->input->col = 1; - } else - ctxt->input->col++; - ctxt->input->cur++; + /* 4-byte code */ + if ((val < 0xf090) || (val >= 0xf490)) + goto encoding_error; + ctxt->input->cur += 4; + } + } } + return; -encoding_error: - /* - * If we detect an UTF8 error that probably mean that the - * input encoding didn't get properly advertised in the - * declaration header. Report the error and switch the encoding - * to ISO-Latin-1 (if you don't like this policy, just declare the - * encoding !) - */ - if ((ctxt == NULL) || (ctxt->input == NULL) || - (ctxt->input->end - ctxt->input->cur < 4)) { - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n", - NULL, NULL); - } else { - char buffer[150];
- snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - ctxt->input->cur[0], ctxt->input->cur[1], - ctxt->input->cur[2], ctxt->input->cur[3]); - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n%s", - BAD_CAST buffer, NULL); +encoding_error: + /* Only report the first error */ + if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) { + if ((ctxt == NULL) || (ctxt->input == NULL) || + (ctxt->input->end - ctxt->input->cur < 4)) { + __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, + "Input is not proper UTF-8, indicate encoding !\n", + NULL, NULL); + } else { + char buffer[150]; + + snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", + ctxt->input->cur[0], ctxt->input->cur[1], + ctxt->input->cur[2], ctxt->input->cur[3]); + __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, + "Input is not proper UTF-8, indicate encoding !\n%s", + BAD_CAST buffer, NULL); + } + ctxt->input->flags |= XML_INPUT_ENCODING_ERROR; } - ctxt->charset = XML_CHAR_ENCODING_8859_1; ctxt->input->cur++; return; } @@ -678,144 +831,135 @@ encoding_error:
int xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) { + const unsigned char *cur; + size_t avail; + int c; + if ((ctxt == NULL) || (len == NULL) || (ctxt->input == NULL)) return(0); if (ctxt->instate == XML_PARSER_EOF) return(0);
- if ((ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) && - (xmlParserGrow(ctxt) < 0)) - return(0); + avail = ctxt->input->end - ctxt->input->cur;
- if ((*ctxt->input->cur >= 0x20) && (*ctxt->input->cur <= 0x7F)) { - *len = 1; - return(*ctxt->input->cur); - } - if (ctxt->charset == XML_CHAR_ENCODING_UTF8) { - /* - * We are supposed to handle UTF8, check it's valid - * From rfc2044: encoding of the Unicode values on UTF-8: - * - * UCS-4 range (hex.) UTF-8 octet sequence (binary) - * 0000 0000-0000 007F 0xxxxxxx - * 0000 0080-0000 07FF 110xxxxx 10xxxxxx - * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - * - * Check for the 0x110000 limit too - */ - const unsigned char *cur = ctxt->input->cur; - unsigned char c; - unsigned int val; + if (avail < INPUT_CHUNK) { + xmlParserGrow(ctxt); + if (ctxt->instate == XML_PARSER_EOF) + return(0); + avail = ctxt->input->end - ctxt->input->cur; + } + + cur = ctxt->input->cur; + c = *cur;
- c = *cur; - if (c & 0x80) { - size_t avail; + if (c < 0x80) { + /* 1-byte code */ + if (c < 0x20) { + /* + * 2.11 End-of-Line Handling + * the literal two-character sequence "#xD#xA" or a standalone + * literal #xD, an XML processor must pass to the application + * the single character #xA. + */ + if (c == '\r') { + /* + * TODO: This function shouldn't change the 'cur' pointer + * as side effect, but the NEXTL macro in parser.c relies + * on this behavior when incrementing line numbers. + */ + if (cur[1] == '\n') + ctxt->input->cur++; + *len = 1; + c = '\n'; + } else if (c == 0) { + if (ctxt->input->cur >= ctxt->input->end) { + *len = 0; + } else { + *len = 1; + /* + * TODO: Null bytes should be handled by callers, + * but this can be tricky. + */ + xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, + "Char 0x0 out of allowed range\n", c); + } + } else { + *len = 1; + } + } else { + *len = 1; + }
- if (((c & 0x40) == 0) || (c == 0xC0)) - goto encoding_error; + return(c); + } else { + int val;
- avail = ctxt->input->end - ctxt->input->cur; + if (avail < 2) + goto incomplete_sequence; + if ((cur[1] & 0xc0) != 0x80) + goto encoding_error;
- if (avail < 2) + if (c < 0xe0) { + /* 2-byte code */ + if (c < 0xc2) + goto encoding_error; + val = (c & 0x1f) << 6; + val |= cur[1] & 0x3f; + *len = 2; + } else { + if (avail < 3) goto incomplete_sequence; - if ((cur[1] & 0xc0) != 0x80) - goto encoding_error; - if ((c & 0xe0) == 0xe0) { - if (avail < 3) + if ((cur[2] & 0xc0) != 0x80) + goto encoding_error; + + if (c < 0xf0) { + /* 3-byte code */ + val = (c & 0xf) << 12; + val |= (cur[1] & 0x3f) << 6; + val |= cur[2] & 0x3f; + if ((val < 0x800) || ((val >= 0xd800) && (val < 0xe000))) + goto encoding_error; + *len = 3; + } else { + if (avail < 4) goto incomplete_sequence; - if ((cur[2] & 0xc0) != 0x80) - goto encoding_error; - if ((c & 0xf0) == 0xf0) { - if (avail < 4) - goto incomplete_sequence; - if (((c & 0xf8) != 0xf0) || - ((cur[3] & 0xc0) != 0x80)) - goto encoding_error; - /* 4-byte code */ - *len = 4; - val = (cur[0] & 0x7) << 18; - val |= (cur[1] & 0x3f) << 12; - val |= (cur[2] & 0x3f) << 6; - val |= cur[3] & 0x3f; - if (val < 0x10000) - goto encoding_error; - } else { - /* 3-byte code */ - *len = 3; - val = (cur[0] & 0xf) << 12; - val |= (cur[1] & 0x3f) << 6; - val |= cur[2] & 0x3f; - if (val < 0x800) - goto encoding_error; - } - } else { - /* 2-byte code */ - *len = 2; - val = (cur[0] & 0x1f) << 6; - val |= cur[1] & 0x3f; - if (val < 0x80) - goto encoding_error; - } - if (!IS_CHAR(val)) { - xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, - "Char 0x%X out of allowed range\n", val); - } - return(val); - } else { - /* 1-byte code */ - *len = 1; - if ((*ctxt->input->cur == 0) && - (ctxt->input->end > ctxt->input->cur)) { - xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, - "Char 0x0 out of allowed range\n", 0); - } - if (*ctxt->input->cur == 0xD) { - if (ctxt->input->cur[1] == 0xA) { - ctxt->input->cur++; - } - return(0xA); - } - return(*ctxt->input->cur); - } - } - /* - * Assume it's a fixed length encoding (1) with - * a compatible encoding for the ASCII set, since - * XML constructs only use < 128 chars - */ - *len = 1; - if (*ctxt->input->cur == 0xD) { - if (ctxt->input->cur[1] == 0xA) { - ctxt->input->cur++; - } - return(0xA); + if ((cur[3] & 0xc0) != 0x80) + goto encoding_error; + + /* 4-byte code */ + val = (c & 0x0f) << 18; + val |= (cur[1] & 0x3f) << 12; + val |= (cur[2] & 0x3f) << 6; + val |= cur[3] & 0x3f; + if ((val < 0x10000) || (val >= 0x110000)) + goto encoding_error; + *len = 4; + } + } + + return(val); } - return(*ctxt->input->cur);
encoding_error: - /* - * If we detect an UTF8 error that probably mean that the - * input encoding didn't get properly advertised in the - * declaration header. Report the error and switch the encoding - * to ISO-Latin-1 (if you don't like this policy, just declare the - * encoding !) - */ - if (ctxt->input->end - ctxt->input->cur < 4) { - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n", - NULL, NULL); - } else { - char buffer[150]; - - snprintf(&buffer[0], 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - ctxt->input->cur[0], ctxt->input->cur[1], - ctxt->input->cur[2], ctxt->input->cur[3]); - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n%s", - BAD_CAST buffer, NULL); + /* Only report the first error */ + if ((ctxt->input->flags & XML_INPUT_ENCODING_ERROR) == 0) { + if (ctxt->input->end - ctxt->input->cur < 4) { + __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, + "Input is not proper UTF-8, indicate encoding !\n", + NULL, NULL); + } else { + char buffer[150]; + + snprintf(&buffer[0], 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", + ctxt->input->cur[0], ctxt->input->cur[1], + ctxt->input->cur[2], ctxt->input->cur[3]); + __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, + "Input is not proper UTF-8, indicate encoding !\n%s", + BAD_CAST buffer, NULL); + } + ctxt->input->flags |= XML_INPUT_ENCODING_ERROR; } - ctxt->charset = XML_CHAR_ENCODING_8859_1; *len = 1; - return(*ctxt->input->cur); + return(0xFFFD); /* U+FFFD Replacement Character */
incomplete_sequence: /* @@ -843,103 +987,18 @@ incomplete_sequence: */
int -xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar * cur, int *len) -{ - if ((len == NULL) || (cur == NULL)) return(0); - if ((ctxt == NULL) || (ctxt->charset == XML_CHAR_ENCODING_UTF8)) { - /* - * We are supposed to handle UTF8, check it's valid - * From rfc2044: encoding of the Unicode values on UTF-8: - * - * UCS-4 range (hex.) UTF-8 octet sequence (binary) - * 0000 0000-0000 007F 0xxxxxxx - * 0000 0080-0000 07FF 110xxxxx 10xxxxxx - * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - * - * Check for the 0x110000 limit too - */ - unsigned char c; - unsigned int val; - - c = *cur; - if (c & 0x80) { - if ((cur[1] & 0xc0) != 0x80) - goto encoding_error; - if ((c & 0xe0) == 0xe0) { +xmlStringCurrentChar(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED, + const xmlChar *cur, int *len) { + int c;
- if ((cur[2] & 0xc0) != 0x80) - goto encoding_error; - if ((c & 0xf0) == 0xf0) { - if (((c & 0xf8) != 0xf0) || ((cur[3] & 0xc0) != 0x80)) - goto encoding_error; - /* 4-byte code */ - *len = 4; - val = (cur[0] & 0x7) << 18; - val |= (cur[1] & 0x3f) << 12; - val |= (cur[2] & 0x3f) << 6; - val |= cur[3] & 0x3f; - } else { - /* 3-byte code */ - *len = 3; - val = (cur[0] & 0xf) << 12; - val |= (cur[1] & 0x3f) << 6; - val |= cur[2] & 0x3f; - } - } else { - /* 2-byte code */ - *len = 2; - val = (cur[0] & 0x1f) << 6; - val |= cur[1] & 0x3f; - } - if (!IS_CHAR(val)) { - xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR, - "Char 0x%X out of allowed range\n", val); - } - return (val); - } else { - /* 1-byte code */ - *len = 1; - return (*cur); - } - } - /* - * Assume it's a fixed length encoding (1) with - * a compatible encoding for the ASCII set, since - * XML constructs only use < 128 chars - */ - *len = 1; - return (*cur); -encoding_error: + if ((cur == NULL) || (len == NULL)) + return(0);
- /* - * An encoding problem may arise from a truncated input buffer - * splitting a character in the middle. In that case do not raise - * an error but return 0 to indicate an end of stream problem - */ - if ((ctxt == NULL) || (ctxt->input == NULL) || - (ctxt->input->end - ctxt->input->cur < 4)) { - *len = 0; - return(0); - } - /* - * If we detect an UTF8 error that probably mean that the - * input encoding didn't get properly advertised in the - * declaration header. Report the error and switch the encoding - * to ISO-Latin-1 (if you don't like this policy, just declare the - * encoding !) - */ - { - char buffer[150]; + /* cur is zero-terminated, so we can lie about its length. */ + *len = 4; + c = xmlGetUTF8Char(cur, len);
- snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n", - ctxt->input->cur[0], ctxt->input->cur[1], - ctxt->input->cur[2], ctxt->input->cur[3]); - __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR, - "Input is not proper UTF-8, indicate encoding !\n%s", - BAD_CAST buffer, NULL); - } - *len = 1; - return (*cur); + return((c < 0) ? 0 : c); }
/** @@ -1026,7 +1085,7 @@ xmlDetectEBCDIC(xmlParserInputPtr input) { return(NULL); outlen = sizeof(out) - 1; inlen = input->end - input->cur; - res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen, 0); + res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen); if (res < 0) return(handler); out[outlen] = 0; @@ -1060,12 +1119,15 @@ xmlDetectEBCDIC(xmlParserInputPtr input) { break; out[i] = 0; xmlCharEncCloseFunc(handler); - handler = xmlFindCharEncodingHandler((char *) out + start); - break; + return(xmlFindCharEncodingHandler((char *) out + start)); } }
- return(handler); + /* + * ICU handlers are stateful, so we have to recreate them. + */ + xmlCharEncCloseFunc(handler); + return(xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC)); }
/** @@ -1073,58 +1135,29 @@ xmlDetectEBCDIC(xmlParserInputPtr input) { * @ctxt: the parser context * @enc: the encoding value (number) * - * change the input functions when discovering the character encoding - * of a given entity. + * Use encoding specified by enum to decode input data. + * + * This function can be used to enforce the encoding of chunks passed + * to xmlParseChunk. * * Returns 0 in case of success, -1 otherwise */ int xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) { - xmlCharEncodingHandlerPtr handler; + xmlCharEncodingHandlerPtr handler = NULL; + int check = 1; int ret;
- if (ctxt == NULL) return(-1); - - /* - * FIXME: The BOM shouldn't be skipped here, but in the parsing code. - * - * Note that we look for a decoded UTF-8 BOM when switching to UTF-16. - * This is mostly useless but Webkit/Chromium relies on this behavior. - * See https://bugs.chromium.org/p/chromium/issues/detail?id=1451026 - */ - if ((ctxt->input != NULL) && - (ctxt->input->consumed == 0) && - (ctxt->input->cur != NULL) && - (ctxt->input->cur == ctxt->input->base) && - ((enc == XML_CHAR_ENCODING_UTF8) || - (enc == XML_CHAR_ENCODING_UTF16LE) || - (enc == XML_CHAR_ENCODING_UTF16BE))) { - /* - * Errata on XML-1.0 June 20 2001 - * Specific handling of the Byte Order Mark for - * UTF-8 - */ - if ((ctxt->input->cur[0] == 0xEF) && - (ctxt->input->cur[1] == 0xBB) && - (ctxt->input->cur[2] == 0xBF)) { - ctxt->input->cur += 3; - } - } + if ((ctxt == NULL) || (ctxt->input == NULL)) + return(-1);
switch (enc) { - case XML_CHAR_ENCODING_ERROR: - __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING, - "encoding unknown\n", NULL, NULL); - return(-1); case XML_CHAR_ENCODING_NONE: - /* let's assume it's UTF-8 without the XML decl */ - ctxt->charset = XML_CHAR_ENCODING_UTF8; - return(0); case XML_CHAR_ENCODING_UTF8: - /* default encoding, no conversion should be needed */ - ctxt->charset = XML_CHAR_ENCODING_UTF8; - return(0); + case XML_CHAR_ENCODING_ASCII: + check = 0; + break; case XML_CHAR_ENCODING_EBCDIC: handler = xmlDetectEBCDIC(ctxt->input); break; @@ -1132,45 +1165,28 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) handler = xmlGetCharEncodingHandler(enc); break; } - if (handler == NULL) { - /* - * Default handlers. - */ - switch (enc) { - case XML_CHAR_ENCODING_ASCII: - /* default encoding, no conversion should be needed */ - ctxt->charset = XML_CHAR_ENCODING_UTF8; - return(0); - case XML_CHAR_ENCODING_8859_1: - if ((ctxt->inputNr == 1) && - (ctxt->encoding == NULL) && - (ctxt->input != NULL) && - (ctxt->input->encoding != NULL)) { - ctxt->encoding = xmlStrdup(ctxt->input->encoding); - } - ctxt->charset = enc; - return(0); - default: - __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING, - "encoding not supported: %s\n", - BAD_CAST xmlGetCharEncodingName(enc), 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); - return(-1); - } - } - ret = xmlSwitchInputEncoding(ctxt, ctxt->input, handler); - if ((ret < 0) || (ctxt->errNo == XML_I18N_CONV_FAILED)) { + + if ((check) && (handler == NULL)) { + const char *name = xmlGetCharEncodingName(enc); + + __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING, + "encoding not supported: %s\n", + BAD_CAST (name ? name : "<null>"), NULL); /* - * on encoding conversion errors, stop the parser - */ + * 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); - ctxt->errNo = XML_I18N_CONV_FAILED; + return(-1); + } + + ret = xmlSwitchInputEncoding(ctxt, ctxt->input, handler); + + if ((ret >= 0) && (enc == XML_CHAR_ENCODING_NONE)) { + ctxt->input->flags &= ~XML_INPUT_HAS_ENCODING; } + return(ret); }
@@ -1180,8 +1196,9 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) * @input: the input stream * @handler: the encoding handler * - * change the input functions when discovering the character encoding - * of a given entity. + * DEPRECATED: Internal function, don't use. + * + * Use encoding handler to decode input data. * * Returns 0 in case of success, -1 otherwise */ @@ -1192,27 +1209,27 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, int nbchars; xmlParserInputBufferPtr in;
- if (handler == NULL) - return (-1); - if (input == NULL) - return (-1); - in = input->buf; - if (in == NULL) { - xmlErrInternal(ctxt, - "static memory buffer doesn't support encoding\n", NULL); - /* - * Callers assume that the input buffer takes ownership of the - * encoding handler. xmlCharEncCloseFunc frees unregistered - * handlers and avoids a memory leak. - */ + if ((input == NULL) || (input->buf == NULL)) { xmlCharEncCloseFunc(handler); return (-1); } + in = input->buf;
- if (in->encoder != NULL) { - if (in->encoder == handler) - return (0); + input->flags |= XML_INPUT_HAS_ENCODING;
+ /* + * UTF-8 requires no encoding handler. + */ + if ((handler != NULL) && + (xmlStrcasecmp(BAD_CAST handler->name, BAD_CAST "UTF-8") == 0)) { + xmlCharEncCloseFunc(handler); + handler = NULL; + } + + if (in->encoder == handler) + return (0); + + if (in->encoder != NULL) { /* * Switching encodings during parsing is a really bad idea, * but Chromium can switch between ISO-8859-1 and UTF-16 before @@ -1227,45 +1244,13 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, return (0); }
- ctxt->charset = XML_CHAR_ENCODING_UTF8; in->encoder = handler;
/* * Is there already some content down the pipe to convert ? */ if (xmlBufIsEmpty(in->buffer) == 0) { - size_t processed, use, consumed; - - /* - * FIXME: The BOM shouldn't be skipped here, but in the parsing code. - */ - - /* - * Specific handling of the Byte Order Mark for - * UTF-16 - */ - if ((handler->name != NULL) && - (!strcmp(handler->name, "UTF-16LE") || - !strcmp(handler->name, "UTF-16")) && - (input->cur[0] == 0xFF) && (input->cur[1] == 0xFE)) { - input->cur += 2; - } - if ((handler->name != NULL) && - (!strcmp(handler->name, "UTF-16BE")) && - (input->cur[0] == 0xFE) && (input->cur[1] == 0xFF)) { - input->cur += 2; - } - /* - * Errata on XML-1.0 June 20 2001 - * Specific handling of the Byte Order Mark for - * UTF-8 - */ - if ((handler->name != NULL) && - (!strcmp(handler->name, "UTF-8")) && - (input->cur[0] == 0xEF) && - (input->cur[1] == 0xBB) && (input->cur[2] == 0xBF)) { - input->cur += 3; - } + size_t processed;
/* * Shrink the current input buffer. @@ -1277,19 +1262,8 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, in->raw = in->buffer; in->buffer = xmlBufCreate(); in->rawconsumed = processed; - use = xmlBufUse(in->raw);
- /* - * TODO: We must flush and decode the whole buffer to make functions - * like xmlReadMemory work with a user-provided encoding. If the - * encoding is specified directly, we should probably set - * XML_PARSE_IGNORE_ENC in xmlDoRead to avoid switching encodings - * twice. Then we could set "flush" to false which should save - * a considerable amount of memory when parsing from memory. - * It's probably even possible to remove this whole if-block - * completely. - */ - nbchars = xmlCharEncInput(in, 1); + nbchars = xmlCharEncInput(in); xmlBufResetInput(in->buffer, input); if (nbchars < 0) { /* TODO: This could be an out of memory or an encoding error. */ @@ -1299,12 +1273,6 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, xmlHaltParser(ctxt); return (-1); } - consumed = use - xmlBufUse(in->raw); - if ((consumed > ULONG_MAX) || - (in->rawconsumed > ULONG_MAX - (unsigned long)consumed)) - in->rawconsumed = ULONG_MAX; - else - in->rawconsumed += consumed; } return (0); } @@ -1314,8 +1282,10 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, * @ctxt: the parser context * @handler: the encoding handler * - * change the input functions when discovering the character encoding - * of a given entity. + * Use encoding handler to decode input data. + * + * This function can be used to enforce the encoding of chunks passed + * to xmlParseChunk. * * Returns 0 in case of success, -1 otherwise */ @@ -1327,6 +1297,212 @@ xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler) return(xmlSwitchInputEncoding(ctxt, ctxt->input, handler)); }
+/** + * xmlDetectEncoding: + * @ctxt: the parser context + * + * Handle optional BOM, detect and switch to encoding. + * + * Assumes that there are at least four bytes in the input buffer. + */ +void +xmlDetectEncoding(xmlParserCtxtPtr ctxt) { + const xmlChar *in; + xmlCharEncoding enc; + int bomSize; + int autoFlag = 0; + + if (xmlParserGrow(ctxt) < 0) + return; + in = ctxt->input->cur; + if (ctxt->input->end - in < 4) + return; + + if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) { + /* + * If the encoding was already set, only skip the BOM which was + * possibly decoded to UTF-8. + */ + if ((in[0] == 0xEF) && (in[1] == 0xBB) && (in[2] == 0xBF)) { + ctxt->input->cur += 3; + } + + return; + } + + enc = XML_CHAR_ENCODING_NONE; + bomSize = 0; + + switch (in[0]) { + case 0x00: + if ((in[1] == 0x00) && (in[2] == 0x00) && (in[3] == 0x3C)) { + enc = XML_CHAR_ENCODING_UCS4BE; + autoFlag = XML_INPUT_AUTO_OTHER; + } else if ((in[1] == 0x3C) && (in[2] == 0x00) && (in[3] == 0x3F)) { + enc = XML_CHAR_ENCODING_UTF16BE; + autoFlag = XML_INPUT_AUTO_UTF16BE; + } + break; + + case 0x3C: + if (in[1] == 0x00) { + if ((in[2] == 0x00) && (in[3] == 0x00)) { + enc = XML_CHAR_ENCODING_UCS4LE; + autoFlag = XML_INPUT_AUTO_OTHER; + } else if ((in[2] == 0x3F) && (in[3] == 0x00)) { + enc = XML_CHAR_ENCODING_UTF16LE; + autoFlag = XML_INPUT_AUTO_UTF16LE; + } + } + break; + + case 0x4C: + if ((in[1] == 0x6F) && (in[2] == 0xA7) && (in[3] == 0x94)) { + enc = XML_CHAR_ENCODING_EBCDIC; + autoFlag = XML_INPUT_AUTO_OTHER; + } + break; + + case 0xEF: + if ((in[1] == 0xBB) && (in[2] == 0xBF)) { + enc = XML_CHAR_ENCODING_UTF8; + autoFlag = XML_INPUT_AUTO_UTF8; + bomSize = 3; + } + break; + + case 0xFE: + if (in[1] == 0xFF) { + enc = XML_CHAR_ENCODING_UTF16BE; + autoFlag = XML_INPUT_AUTO_UTF16BE; + bomSize = 2; + } + break; + + case 0xFF: + if (in[1] == 0xFE) { + enc = XML_CHAR_ENCODING_UTF16LE; + autoFlag = XML_INPUT_AUTO_UTF16LE; + bomSize = 2; + } + break; + } + + if (bomSize > 0) { + ctxt->input->cur += bomSize; + } + + if (enc != XML_CHAR_ENCODING_NONE) { + ctxt->input->flags |= autoFlag; + xmlSwitchEncoding(ctxt, enc); + } +} + +/** + * xmlSetDeclaredEncoding: + * @ctxt: the parser context + * @encoding: declared encoding + * + * Set the encoding from a declaration in the document. + * + * If no encoding was set yet, switch the encoding. Otherwise, only warn + * about encoding mismatches. + * + * Takes ownership of 'encoding'. + */ +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); + ctxt->input->flags |= XML_INPUT_USES_ENC_DECL; + } else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) { + static const char *allowedUTF8[] = { + "UTF-8", "UTF8", NULL + }; + static const char *allowedUTF16LE[] = { + "UTF-16", "UTF-16LE", "UTF16", NULL + }; + static const char *allowedUTF16BE[] = { + "UTF-16", "UTF-16BE", "UTF16", NULL + }; + const char **allowed = NULL; + const char *autoEnc = NULL; + + switch (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) { + case XML_INPUT_AUTO_UTF8: + allowed = allowedUTF8; + autoEnc = "UTF-8"; + break; + case XML_INPUT_AUTO_UTF16LE: + allowed = allowedUTF16LE; + autoEnc = "UTF-16LE"; + break; + case XML_INPUT_AUTO_UTF16BE: + allowed = allowedUTF16BE; + autoEnc = "UTF-16BE"; + break; + } + + if (allowed != NULL) { + const char **p; + int match = 0; + + for (p = allowed; *p != NULL; p++) { + if (xmlStrcasecmp(encoding, BAD_CAST *p) == 0) { + match = 1; + break; + } + } + + if (match == 0) { + xmlWarningMsg(ctxt, XML_WAR_ENCODING_MISMATCH, + "Encoding '%s' doesn't match " + "auto-detected '%s'\n", + encoding, BAD_CAST autoEnc); + } + } + } +} + +/** + * xmlGetActualEncoding: + * @ctxt: the parser context + * + * Returns the actual used to parse the document. This can differ from + * the declared encoding. + */ +const xmlChar * +xmlGetActualEncoding(xmlParserCtxtPtr ctxt) { + const xmlChar *encoding = NULL; + + if ((ctxt->input->flags & XML_INPUT_USES_ENC_DECL) || + (ctxt->input->flags & XML_INPUT_AUTO_ENCODING)) { + /* Preserve encoding exactly */ + encoding = ctxt->encoding; + } else if ((ctxt->input->buf) && (ctxt->input->buf->encoder)) { + encoding = BAD_CAST ctxt->input->buf->encoder->name; + } else if (ctxt->input->flags & XML_INPUT_HAS_ENCODING) { + encoding = BAD_CAST "UTF-8"; + } + + return(encoding); +} + /************************************************************************ * * * Commodity functions to handle entities processing * @@ -1345,7 +1521,6 @@ xmlFreeInputStream(xmlParserInputPtr input) {
if (input->filename != NULL) xmlFree((char *) input->filename); if (input->directory != NULL) xmlFree((char *) input->directory); - if (input->encoding != NULL) xmlFree((char *) input->encoding); if (input->version != NULL) xmlFree((char *) input->version); if ((input->free != NULL) && (input->base != NULL)) input->free((xmlChar *) input->base); @@ -1374,7 +1549,6 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) { memset(input, 0, sizeof(xmlParserInput)); input->line = 1; input->col = 1; - input->standalone = -1;
/* * If the context is NULL the id cannot be initialized, but that @@ -1517,9 +1691,7 @@ xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) { if (xmlParserDebugEntities) xmlGenericError(xmlGenericErrorContext, "new fixed input: %.30s\n", buffer); - buf = xmlParserInputBufferCreateMem((const char *) buffer, - xmlStrlen(buffer), - XML_CHAR_ENCODING_NONE); + buf = xmlParserInputBufferCreateString(buffer); if (buf == NULL) { xmlErrMemory(ctxt, NULL); return(NULL); @@ -1789,12 +1961,21 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, ctxt->inSubset = 0; ctxt->errNo = XML_ERR_OK; ctxt->depth = 0; - ctxt->charset = XML_CHAR_ENCODING_UTF8; ctxt->catalogs = NULL; ctxt->sizeentities = 0; ctxt->sizeentcopy = 0; ctxt->input_id = 1; + ctxt->maxAmpl = XML_MAX_AMPLIFICATION_DEFAULT; xmlInitNodeInfoSeq(&ctxt->node_seq); + + if (ctxt->nsdb == NULL) { + ctxt->nsdb = xmlParserNsCreate(); + if (ctxt->nsdb == NULL) { + xmlErrMemory(ctxt, NULL); + return(-1); + } + } + return(0); }
@@ -1854,7 +2035,9 @@ xmlFreeParserCtxt(xmlParserCtxtPtr ctxt) if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab); if (ctxt->atts != NULL) xmlFree((xmlChar * *)ctxt->atts); if (ctxt->dict != NULL) xmlDictFree(ctxt->dict); - if (ctxt->nsTab != NULL) xmlFree((char *) ctxt->nsTab); + if (ctxt->nsTab != NULL) xmlFree(ctxt->nsTab); + if (ctxt->nsdb != NULL) xmlParserNsFree(ctxt->nsdb); + if (ctxt->attrHash != NULL) xmlFree(ctxt->attrHash); if (ctxt->pushTab != NULL) xmlFree(ctxt->pushTab); if (ctxt->attallocs != NULL) xmlFree(ctxt->attallocs); if (ctxt->attsDefault != NULL) @@ -2244,6 +2427,9 @@ xmlKeepBlanksDefault(int val) { int old = xmlKeepBlanksDefaultValue;
xmlKeepBlanksDefaultValue = val; - if (!val) xmlIndentTreeOutput = 1; +#ifdef LIBXML_OUTPUT_ENABLED + if (!val) + xmlIndentTreeOutput = 1; +#endif return(old); } diff --git a/libs/xml2/pattern.c b/libs/xml2/pattern.c index 04a4eb797fe..55ae2d3e5cf 100644 --- a/libs/xml2/pattern.c +++ b/libs/xml2/pattern.c @@ -27,18 +27,15 @@ #include "libxml.h"
#include <string.h> +#include <libxml/pattern.h> #include <libxml/xmlmemory.h> #include <libxml/tree.h> -#include <libxml/hash.h> #include <libxml/dict.h> #include <libxml/xmlerror.h> #include <libxml/parserInternals.h> -#include <libxml/pattern.h>
#ifdef LIBXML_PATTERN_ENABLED
-/* #define DEBUG_STREAMING */ - #ifdef ERROR #undef ERROR #endif @@ -935,7 +932,6 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
if (IS_BLANK_CH(CUR)) { ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); - XML_PAT_FREE_STRING(ctxt, prefix); ctxt->error = 1; goto error; } @@ -960,12 +956,12 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { ERROR5(NULL, NULL, NULL, "xmlCompileAttributeTest : no namespace bound to prefix %s\n", prefix); - XML_PAT_FREE_STRING(ctxt, prefix); ctxt->error = 1; goto error; } } - XML_PAT_FREE_STRING(ctxt, prefix); + XML_PAT_FREE_STRING(ctxt, name); + name = NULL; if (token == NULL) { if (CUR == '*') { NEXT; @@ -984,6 +980,8 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { } return; error: + if (name != NULL) + XML_PAT_FREE_STRING(ctxt, name); if (URL != NULL) XML_PAT_FREE_STRING(ctxt, URL) if (token != NULL) @@ -1415,62 +1413,6 @@ error_unfinished: * * ************************************************************************/
-#ifdef DEBUG_STREAMING -static void -xmlDebugStreamComp(xmlStreamCompPtr stream) { - int i; - - if (stream == NULL) { - printf("Stream: NULL\n"); - return; - } - printf("Stream: %d steps\n", stream->nbStep); - for (i = 0;i < stream->nbStep;i++) { - if (stream->steps[i].ns != NULL) { - printf("{%s}", stream->steps[i].ns); - } - if (stream->steps[i].name == NULL) { - printf("* "); - } else { - printf("%s ", stream->steps[i].name); - } - if (stream->steps[i].flags & XML_STREAM_STEP_ROOT) - printf("root "); - if (stream->steps[i].flags & XML_STREAM_STEP_DESC) - printf("// "); - if (stream->steps[i].flags & XML_STREAM_STEP_FINAL) - printf("final "); - printf("\n"); - } -} -static void -xmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) { - int i; - - if (ctxt == NULL) { - printf("Stream: NULL\n"); - return; - } - printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState); - if (match) - printf("matches\n"); - else - printf("\n"); - for (i = 0;i < ctxt->nbState;i++) { - if (ctxt->states[2 * i] < 0) - printf(" %d: free\n", i); - else { - printf(" %d: step %d, level %d", i, ctxt->states[2 * i], - ctxt->states[(2 * i) + 1]); - if (ctxt->comp->steps[ctxt->states[2 * i]].flags & - XML_STREAM_STEP_DESC) - printf(" //\n"); - else - printf("\n"); - } - } -} -#endif /** * xmlNewStreamComp: * @size: the number of expected steps @@ -1729,9 +1671,6 @@ xmlStreamCompile(xmlPatternPtr comp) { stream->steps[s].flags |= XML_STREAM_STEP_FINAL; if (root) stream->steps[0].flags |= XML_STREAM_STEP_ROOT; -#ifdef DEBUG_STREAMING - xmlDebugStreamComp(stream); -#endif comp->stream = stream; return(0); error: @@ -1852,9 +1791,6 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc; xmlStreamCompPtr comp; xmlStreamStep step; -#ifdef DEBUG_STREAMING - xmlStreamCtxtPtr orig = stream; -#endif
if ((stream == NULL) || (stream->nbState < 0)) return(-1); @@ -2172,9 +2108,6 @@ stream_next:
if (err > 0) ret = -1; -#ifdef DEBUG_STREAMING - xmlDebugStreamCtxt(orig, ret); -#endif return(ret); }
diff --git a/libs/xml2/relaxng.c b/libs/xml2/relaxng.c index acf536a53de..d7c407d1981 100644 --- a/libs/xml2/relaxng.c +++ b/libs/xml2/relaxng.c @@ -51,30 +51,6 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *) (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
-#if 0 -#define DEBUG 1 - -#define DEBUG_GRAMMAR 1 - -#define DEBUG_CONTENT 1 - -#define DEBUG_TYPE 1 - -#define DEBUG_VALID 1 - -#define DEBUG_INTERLEAVE 1 - -#define DEBUG_LIST 1 - -#define DEBUG_INCLUDE 1 - -#define DEBUG_ERROR 1 - -#define DEBUG_COMPILE 1 - -#define DEBUG_PROGRESSIVE 1 -#endif - #define MAX_ERROR 5
#define TODO \ @@ -1527,15 +1503,6 @@ xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr tmp, tmp2; xmlChar *name2;
-#ifdef DEBUG_INCLUDE - if (name == NULL) - xmlGenericError(xmlGenericErrorContext, - "Elimination of <include> start from %s\n", URL); - else - xmlGenericError(xmlGenericErrorContext, - "Elimination of <include> define %s from %s\n", - name, URL); -#endif tmp = target; while (tmp != NULL) { tmp2 = tmp->next; @@ -1563,18 +1530,11 @@ xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
if (xmlStrEqual (inc->doc->children->name, BAD_CAST "grammar")) { -#ifdef DEBUG_INCLUDE - href = xmlGetProp(tmp, BAD_CAST "href"); -#endif if (xmlRelaxNGRemoveRedefine(ctxt, href, xmlDocGetRootElement(inc->doc)->children, name) == 1) { found = 1; } -#ifdef DEBUG_INCLUDE - if (href != NULL) - xmlFree(href); -#endif } } if (xmlRelaxNGRemoveRedefine(ctxt, URL, tmp->children, name) == 1) { @@ -1608,11 +1568,6 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, int i; xmlNodePtr root, cur;
-#ifdef DEBUG_INCLUDE - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGLoadInclude(%s)\n", URL); -#endif - /* * check against recursion in the stack */ @@ -1634,9 +1589,6 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, "xmlRelaxNG: could not load %s\n", URL, NULL); return (NULL); } -#ifdef DEBUG_INCLUDE - xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL); -#endif
/* * Allocate the document structures and register it first. @@ -1674,9 +1626,6 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, * Some preprocessing of the document content, this include recursing * in the include stack. */ -#ifdef DEBUG_INCLUDE - xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL); -#endif
doc = xmlRelaxNGCleanupDoc(ctxt, doc); if (doc == NULL) { @@ -1689,9 +1638,6 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, */ xmlRelaxNGIncludePop(ctxt);
-#ifdef DEBUG_INCLUDE - xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL); -#endif /* * Check that the top element is a grammar */ @@ -1783,10 +1729,6 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, { xmlRelaxNGValidErrorPtr cur;
-#ifdef DEBUG_ERROR - xmlGenericError(xmlGenericErrorContext, - "Pushing error %d at %d on stack\n", err, ctxt->errNr); -#endif if (ctxt->errTab == NULL) { ctxt->errMax = 8; ctxt->errNr = 0; @@ -2261,9 +2203,6 @@ xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt, if (ctxt->flags & FLAGS_NOERROR) return;
-#ifdef DEBUG_ERROR - xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err); -#endif msg = xmlRelaxNGGetErrorString(err, arg1, arg2); if (msg == NULL) return; @@ -2288,10 +2227,6 @@ xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level) int i; xmlRelaxNGValidErrorPtr err;
-#ifdef DEBUG_ERROR - xmlGenericError(xmlGenericErrorContext, - "Pop errors till level %d\n", level); -#endif for (i = level; i < ctxt->errNr; i++) { err = &ctxt->errTab[i]; if (err->flags & ERROR_IS_DUP) { @@ -2321,10 +2256,6 @@ xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt) int i, j, k; xmlRelaxNGValidErrorPtr err, dup;
-#ifdef DEBUG_ERROR - xmlGenericError(xmlGenericErrorContext, - "Dumping error stack %d errors\n", ctxt->errNr); -#endif for (i = 0, k = 0; i < ctxt->errNr; i++) { err = &ctxt->errTab[i]; if (k < MAX_ERROR) { @@ -2375,9 +2306,6 @@ xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, if (ctxt->flags & FLAGS_NOERROR) return;
-#ifdef DEBUG_ERROR - xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err); -#endif /* * generate the error directly */ @@ -2937,21 +2865,6 @@ xmlRelaxNGIsCompilable(xmlRelaxNGDefinePtr def) } if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE)) def->dflags |= IS_COMPILABLE; -#ifdef DEBUG_COMPILE - if (ret == 1) { - xmlGenericError(xmlGenericErrorContext, - "element content for %s is compilable\n", - def->name); - } else if (ret == 0) { - xmlGenericError(xmlGenericErrorContext, - "element content for %s is not compilable\n", - def->name); - } else { - xmlGenericError(xmlGenericErrorContext, - "Problem in RelaxNGIsCompilable for element %s\n", - def->name); - } -#endif } /* * All elements return a compilable status unless they @@ -3013,21 +2926,6 @@ xmlRelaxNGIsCompilable(xmlRelaxNGDefinePtr def) def->dflags |= IS_NOT_COMPILABLE; if (ret == 1) def->dflags |= IS_COMPILABLE; -#ifdef DEBUG_COMPILE - if (ret == 1) { - xmlGenericError(xmlGenericErrorContext, - "RelaxNGIsCompilable %s : true\n", - xmlRelaxNGDefName(def)); - } else if (ret == 0) { - xmlGenericError(xmlGenericErrorContext, - "RelaxNGIsCompilable %s : false\n", - xmlRelaxNGDefName(def)); - } else { - xmlGenericError(xmlGenericErrorContext, - "Problem in RelaxNGIsCompilable %s\n", - xmlRelaxNGDefName(def)); - } -#endif return (ret); }
@@ -3113,11 +3011,6 @@ xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) xmlAutomataSetFinalState(ctxt->am, ctxt->state); def->contModel = xmlAutomataCompile(ctxt->am); if (!xmlRegexpIsDeterminist(def->contModel)) { -#ifdef DEBUG_COMPILE - xmlGenericError(xmlGenericErrorContext, - "Content model not determinist %s\n", - def->name); -#endif /* * we can only use the automata if it is determinist */ @@ -3282,24 +3175,6 @@ xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) { ctxt->am = NULL; ret = xmlRelaxNGCompile(ctxt, def); -#ifdef DEBUG_PROGRESSIVE - if (ret == 0) { - if (def->type == XML_RELAXNG_START) - xmlGenericError(xmlGenericErrorContext, - "compiled the start\n"); - else - xmlGenericError(xmlGenericErrorContext, - "compiled element %s\n", def->name); - } else { - if (def->type == XML_RELAXNG_START) - xmlGenericError(xmlGenericErrorContext, - "failed to compile the start\n"); - else - xmlGenericError(xmlGenericErrorContext, - "failed to compile element %s\n", - def->name); - } -#endif return (ret); } } @@ -4359,19 +4234,12 @@ xmlRelaxNGComputeInterleaves(void *payload, void *data, if (ctxt->nbErrors != 0) return;
-#ifdef DEBUG_INTERLEAVE - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGComputeInterleaves(%s)\n", name); -#endif cur = def->content; while (cur != NULL) { nbchild++; cur = cur->next; }
-#ifdef DEBUG_INTERLEAVE - xmlGenericError(xmlGenericErrorContext, " %d child\n", nbchild); -#endif groups = (xmlRelaxNGInterleaveGroupPtr *) xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr)); if (groups == NULL) @@ -4390,9 +4258,6 @@ xmlRelaxNGComputeInterleaves(void *payload, void *data, nbgroups++; cur = cur->next; } -#ifdef DEBUG_INTERLEAVE - xmlGenericError(xmlGenericErrorContext, " %d groups\n", nbgroups); -#endif
/* * Let's check that all rules makes a partitions according to 7.4 @@ -5019,11 +4884,6 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) xmlRelaxNGGrammarPtr grammar, old; xmlRelaxNGGrammarPtr oldparent;
-#ifdef DEBUG_GRAMMAR - xmlGenericError(xmlGenericErrorContext, - "Found <grammar> pattern\n"); -#endif - oldparent = ctxt->parentgrammar; old = ctxt->grammar; ctxt->parentgrammar = old; @@ -5809,11 +5669,6 @@ xmlRelaxNGCheckCombine(void *payload, void *data, const xmlChar * name)
cur = cur->nextHash; } -#ifdef DEBUG - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGCheckCombine(): merging %s defines: %d\n", - name, choiceOrInterleave); -#endif if (choiceOrInterleave == -1) choiceOrInterleave = 0; cur = xmlRelaxNGNewDefine(ctxt, define->node); @@ -5939,11 +5794,6 @@ xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,
cur = cur->next; } -#ifdef DEBUG - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGCombineStart(): merging <start>: %d\n", - choiceOrInterleave); -#endif if (choiceOrInterleave == -1) choiceOrInterleave = 0; cur = xmlRelaxNGNewDefine(ctxt, starts->node); @@ -6609,10 +6459,6 @@ xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) { xmlRelaxNGGrammarPtr ret, tmp, old;
-#ifdef DEBUG_GRAMMAR - xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n"); -#endif - ret = xmlRelaxNGNewGrammar(ctxt); if (ret == NULL) return (NULL); @@ -6741,11 +6587,6 @@ xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) XML_RELAXNG_IN_START, XML_RELAXNG_NOOP); } } -#ifdef DEBUG - if (schema == NULL) - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGParseDocument() failed\n"); -#endif
return (schema); } @@ -7971,10 +7812,6 @@ xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata; int ret;
-#ifdef DEBUG_COMPILE - xmlGenericError(xmlGenericErrorContext, - "Compiled callback for: '%s'\n", token); -#endif if (ctxt == NULL) { fprintf(stderr, "callback on %s missing context\n", token); return; @@ -8181,10 +8018,6 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec xmlNodePtr node; int ret = 0, oldflags;
-#ifdef DEBUG_PROGRESSIVE - xmlGenericError(xmlGenericErrorContext, - "Progressive callback for: '%s'\n", token); -#endif if (ctxt == NULL) { fprintf(stderr, "callback on %s missing context\n", token); return; @@ -8224,11 +8057,6 @@ xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec /* * this node cannot be validated in a streamable fashion */ -#ifdef DEBUG_PROGRESSIVE - xmlGenericError(xmlGenericErrorContext, - "Element '%s' validation is not streamable\n", - token); -#endif ctxt->pstate = 0; ctxt->pdef = define; return; @@ -8325,9 +8153,6 @@ xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt, if ((ctxt == NULL) || (elem == NULL)) return (-1);
-#ifdef DEBUG_PROGRESSIVE - xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name); -#endif if (ctxt->elem == 0) { xmlRelaxNGPtr schema; xmlRelaxNGGrammarPtr grammar; @@ -8376,11 +8201,6 @@ xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt, else ret = 1; } -#ifdef DEBUG_PROGRESSIVE - if (ret < 0) - xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n", - elem->name); -#endif return (ret); }
@@ -8403,10 +8223,6 @@ xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt, if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL)) return (-1);
-#ifdef DEBUG_PROGRESSIVE - xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len); -#endif - while (*data != 0) { if (!IS_BLANK_CH(*data)) break; @@ -8418,9 +8234,6 @@ xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt, ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt); if (ret < 0) { VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO "); -#ifdef DEBUG_PROGRESSIVE - xmlGenericError(xmlGenericErrorContext, "CDATA failed\n"); -#endif
return (-1); } @@ -8447,9 +8260,6 @@ xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL)) return (-1); -#ifdef DEBUG_PROGRESSIVE - xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name); -#endif /* * verify that we reached a terminal state of the content model. */ @@ -8467,11 +8277,6 @@ xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt, ret = 1; } xmlRegFreeExecCtxt(exec); -#ifdef DEBUG_PROGRESSIVE - if (ret < 0) - xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n", - elem->name); -#endif return (ret); }
@@ -8496,9 +8301,6 @@ xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,
if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL)) return (-1); -#ifdef DEBUG_PROGRESSIVE - xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name); -#endif state = xmlRelaxNGNewValidState(ctxt, elem->parent); if (state == NULL) { return (-1); @@ -8513,11 +8315,6 @@ xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt, ret = 1; xmlRelaxNGFreeValidState(ctxt, ctxt->state); ctxt->state = NULL; -#ifdef DEBUG_PROGRESSIVE - if (ret < 0) - xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n", - elem->name); -#endif return (ret); }
@@ -8847,10 +8644,6 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr list = define->content; xmlChar *oldvalue, *oldend, *val, *cur;
-#ifdef DEBUG_LIST - int nb_values = 0; -#endif - oldvalue = ctxt->state->value; oldend = ctxt->state->endvalue;
@@ -8867,20 +8660,11 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, if (IS_BLANK_CH(*cur)) { *cur = 0; cur++; -#ifdef DEBUG_LIST - nb_values++; -#endif while (IS_BLANK_CH(*cur)) *cur++ = 0; } else cur++; } -#ifdef DEBUG_LIST - xmlGenericError(xmlGenericErrorContext, - "list value: '%s' found %d items\n", - oldvalue, nb_values); - nb_values = 0; -#endif ctxt->state->endvalue = cur; cur = val; while ((*cur == 0) && (cur != ctxt->state->endvalue)) @@ -8893,16 +8677,8 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, ctxt->state->value = NULL; ret = xmlRelaxNGValidateValue(ctxt, list); if (ret != 0) { -#ifdef DEBUG_LIST - xmlGenericError(xmlGenericErrorContext, - "Failed to validate value: '%s' with %d rule\n", - ctxt->state->value, nb_values); -#endif break; } -#ifdef DEBUG_LIST - nb_values++; -#endif list = list->next; }
@@ -9166,11 +8942,6 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt, } else { ret = -1; } -#ifdef DEBUG - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGValidateAttribute(%s): %d\n", - define->name, ret); -#endif } else { for (i = 0; i < ctxt->state->nbAttrs; i++) { tmp = ctxt->state->attrs[i]; @@ -9203,17 +8974,6 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt, } else { ret = -1; } -#ifdef DEBUG - if (define->ns != NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n", - define->ns, ret); - } else { - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGValidateAttribute(anyName): %d\n", - ret); - } -#endif }
return (ret); @@ -9895,18 +9655,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, } else { node = NULL; } -#ifdef DEBUG - for (i = 0; i < ctxt->depth; i++) - xmlGenericError(xmlGenericErrorContext, " "); - xmlGenericError(xmlGenericErrorContext, - "Start validating %s ", xmlRelaxNGDefName(define)); - if (define->name != NULL) - xmlGenericError(xmlGenericErrorContext, "%s ", define->name); - if ((node != NULL) && (node->name != NULL)) - xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name); - else - xmlGenericError(xmlGenericErrorContext, "\n"); -#endif ctxt->depth++; switch (define->type) { case XML_RELAXNG_EMPTY: @@ -10025,11 +9773,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, ctxt->states = tmpstates; xmlRelaxNGFreeValidState(ctxt, nstate);
-#ifdef DEBUG_COMPILE - xmlGenericError(xmlGenericErrorContext, - "Validating content of '%s' : %d\n", - define->name, tmp); -#endif if (tmp != 0) ret = -1;
@@ -10147,21 +9890,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGPopErrors(ctxt, errNr); }
-#ifdef DEBUG - xmlGenericError(xmlGenericErrorContext, - "xmlRelaxNGValidateDefinition(): validated %s : %d", - node->name, ret); - if (oldstate == NULL) - xmlGenericError(xmlGenericErrorContext, ": no state\n"); - else if (oldstate->seq == NULL) - xmlGenericError(xmlGenericErrorContext, ": done\n"); - else if (oldstate->seq->type == XML_ELEMENT_NODE) - xmlGenericError(xmlGenericErrorContext, ": next elem %s\n", - oldstate->seq->name); - else - xmlGenericError(xmlGenericErrorContext, ": next %s %d\n", - oldstate->seq->name, oldstate->seq->type); -#endif break; case XML_RELAXNG_OPTIONAL:{ errNr = ctxt->errNr; @@ -10620,18 +10348,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, break; } ctxt->depth--; -#ifdef DEBUG - for (i = 0; i < ctxt->depth; i++) - xmlGenericError(xmlGenericErrorContext, " "); - xmlGenericError(xmlGenericErrorContext, - "Validating %s ", xmlRelaxNGDefName(define)); - if (define->name != NULL) - xmlGenericError(xmlGenericErrorContext, "%s ", define->name); - if (ret == 0) - xmlGenericError(xmlGenericErrorContext, "succeeded\n"); - else - xmlGenericError(xmlGenericErrorContext, "failed\n"); -#endif return (ret); }
@@ -10830,14 +10546,6 @@ xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) } if (ret != 0) xmlRelaxNGDumpValidError(ctxt); -#ifdef DEBUG - else if (ctxt->errNr != 0) { - ctxt->error(ctxt->userData, - "%d Extra error messages left on stack !\n", - ctxt->errNr); - xmlRelaxNGDumpValidError(ctxt); - } -#endif #ifdef LIBXML_VALID_ENABLED if (ctxt->idref == 1) { xmlValidCtxt vctxt; diff --git a/libs/xml2/threads.c b/libs/xml2/threads.c index 60dbce4c736..82c794b53eb 100644 --- a/libs/xml2/threads.c +++ b/libs/xml2/threads.c @@ -14,16 +14,25 @@ #include <stdlib.h>
#include <libxml/threads.h> -#include <libxml/globals.h> +#include <libxml/parser.h> +#ifdef LIBXML_CATALOG_ENABLED +#include <libxml/catalog.h> +#endif +#ifdef LIBXML_SCHEMAS_ENABLED +#include <libxml/xmlschemastypes.h> +#include <libxml/relaxng.h> +#endif
#if defined(SOLARIS) #include <note.h> #endif
#include "private/dict.h" +#include "private/enc.h" +#include "private/globals.h" +#include "private/memory.h" #include "private/threads.h" - -/* #define DEBUG_THREADS */ +#include "private/xpath.h"
#if defined(HAVE_POSIX_THREADS) && \ defined(__GLIBC__) && \ @@ -60,10 +69,6 @@ * configure.ac can probably be removed. */
-#pragma weak pthread_getspecific -#pragma weak pthread_setspecific -#pragma weak pthread_key_create -#pragma weak pthread_key_delete #pragma weak pthread_mutex_init #pragma weak pthread_mutex_destroy #pragma weak pthread_mutex_lock @@ -73,8 +78,6 @@ #pragma weak pthread_cond_wait #pragma weak pthread_equal #pragma weak pthread_self -#pragma weak pthread_key_create -#pragma weak pthread_key_delete #pragma weak pthread_cond_signal
#define XML_PTHREAD_WEAK @@ -113,27 +116,6 @@ struct _xmlRMutex { #endif };
-/* - * This module still has some internal static data. - * - xmlLibraryLock a global lock - * - globalkey used for per-thread data - */ - -#ifdef HAVE_POSIX_THREADS -static pthread_key_t globalkey; -static pthread_t mainthread; -static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER; -#elif defined HAVE_WIN32_THREADS -#if defined(HAVE_COMPILER_TLS) -static __declspec(thread) xmlGlobalState tlstate; -static __declspec(thread) int tlstate_inited = 0; -#else /* HAVE_COMPILER_TLS */ -static DWORD globalkey = TLS_OUT_OF_INDEXES; -#endif /* HAVE_COMPILER_TLS */ -static DWORD mainthread; -static volatile LPCRITICAL_SECTION global_init_lock = NULL; -#endif - static xmlRMutexPtr xmlLibraryLock = NULL;
/** @@ -369,275 +351,6 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED) #endif }
-/** - * xmlGlobalInitMutexLock - * - * Makes sure that the global initialization mutex is initialized and - * locks it. - */ -void -__xmlGlobalInitMutexLock(void) -{ - /* Make sure the global init lock is initialized and then lock it. */ -#ifdef HAVE_POSIX_THREADS -#ifdef XML_PTHREAD_WEAK - if (pthread_mutex_lock == NULL) - return; -#else - if (XML_IS_THREADED() == 0) - return; -#endif - /* The mutex is statically initialized, so we just lock it. */ - pthread_mutex_lock(&global_init_lock); -#elif defined HAVE_WIN32_THREADS - LPCRITICAL_SECTION cs; - - /* Create a new critical section */ - if (global_init_lock == NULL) { - cs = malloc(sizeof(CRITICAL_SECTION)); - if (cs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGlobalInitMutexLock: out of memory\n"); - return; - } - InitializeCriticalSection(cs); - - /* Swap it into the global_init_lock */ -#ifdef InterlockedCompareExchangePointer - InterlockedCompareExchangePointer((void **) &global_init_lock, - cs, NULL); -#else /* Use older void* version */ - InterlockedCompareExchange((void **) &global_init_lock, - (void *) cs, NULL); -#endif /* InterlockedCompareExchangePointer */ - - /* If another thread successfully recorded its critical - * section in the global_init_lock then discard the one - * allocated by this thread. */ - if (global_init_lock != cs) { - DeleteCriticalSection(cs); - free(cs); - } - } - - /* Lock the chosen critical section */ - EnterCriticalSection(global_init_lock); -#endif -} - -void -__xmlGlobalInitMutexUnlock(void) -{ -#ifdef HAVE_POSIX_THREADS -#ifdef XML_PTHREAD_WEAK - if (pthread_mutex_lock == NULL) - return; -#else - if (XML_IS_THREADED() == 0) - return; -#endif - pthread_mutex_unlock(&global_init_lock); -#elif defined HAVE_WIN32_THREADS - if (global_init_lock != NULL) { - LeaveCriticalSection(global_init_lock); - } -#endif -} - -/** - * xmlGlobalInitMutexDestroy - * - * Makes sure that the global initialization mutex is destroyed before - * application termination. - */ -void -__xmlGlobalInitMutexDestroy(void) -{ -#ifdef HAVE_POSIX_THREADS -#elif defined HAVE_WIN32_THREADS - if (global_init_lock != NULL) { - DeleteCriticalSection(global_init_lock); - free(global_init_lock); - global_init_lock = NULL; - } -#endif -} - -/************************************************************************ - * * - * Per thread global state handling * - * * - ************************************************************************/ - -#ifdef LIBXML_THREAD_ENABLED -#ifdef xmlLastError -#undef xmlLastError -#endif - -/** - * xmlFreeGlobalState: - * @state: a thread global state - * - * xmlFreeGlobalState() is called when a thread terminates with a non-NULL - * global state. It is is used here to reclaim memory resources. - */ -static void -xmlFreeGlobalState(void *state) -{ - xmlGlobalState *gs = (xmlGlobalState *) state; - - /* free any memory allocated in the thread's xmlLastError */ - xmlResetError(&(gs->xmlLastError)); - free(state); -} - -/** - * xmlNewGlobalState: - * - * xmlNewGlobalState() allocates a global state. This structure is used to - * hold all data for use by a thread when supporting backwards compatibility - * of libxml2 to pre-thread-safe behaviour. - * - * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error - */ -static xmlGlobalStatePtr -xmlNewGlobalState(void) -{ - xmlGlobalState *gs; - - gs = malloc(sizeof(xmlGlobalState)); - if (gs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGetGlobalState: out of memory\n"); - return (NULL); - } - - memset(gs, 0, sizeof(xmlGlobalState)); - xmlInitializeGlobalState(gs); - return (gs); -} -#endif /* LIBXML_THREAD_ENABLED */ - -#ifdef HAVE_POSIX_THREADS -#elif defined HAVE_WIN32_THREADS -#if !defined(HAVE_COMPILER_TLS) -#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) -typedef struct _xmlGlobalStateCleanupHelperParams { - HANDLE thread; - void *memory; -} xmlGlobalStateCleanupHelperParams; - -static void -xmlGlobalStateCleanupHelper(void *p) -{ - xmlGlobalStateCleanupHelperParams *params = - (xmlGlobalStateCleanupHelperParams *) p; - WaitForSingleObject(params->thread, INFINITE); - CloseHandle(params->thread); - xmlFreeGlobalState(params->memory); - free(params); - _endthread(); -} -#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */ - -typedef struct _xmlGlobalStateCleanupHelperParams { - void *memory; - struct _xmlGlobalStateCleanupHelperParams *prev; - struct _xmlGlobalStateCleanupHelperParams *next; -} xmlGlobalStateCleanupHelperParams; - -static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL; -static CRITICAL_SECTION cleanup_helpers_cs; - -#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */ -#endif /* HAVE_COMPILER_TLS */ -#endif /* HAVE_WIN32_THREADS */ - -/** - * xmlGetGlobalState: - * - * DEPRECATED: Internal function, do not use. - * - * xmlGetGlobalState() is called to retrieve the global state for a thread. - * - * Returns the thread global state or NULL in case of error - */ -xmlGlobalStatePtr -xmlGetGlobalState(void) -{ -#ifdef HAVE_POSIX_THREADS - xmlGlobalState *globalval; - - if (XML_IS_THREADED() == 0) - return (NULL); - - if ((globalval = (xmlGlobalState *) - pthread_getspecific(globalkey)) == NULL) { - xmlGlobalState *tsd = xmlNewGlobalState(); - if (tsd == NULL) - return(NULL); - - pthread_setspecific(globalkey, tsd); - return (tsd); - } - return (globalval); -#elif defined HAVE_WIN32_THREADS -#if defined(HAVE_COMPILER_TLS) - if (!tlstate_inited) { - tlstate_inited = 1; - xmlInitializeGlobalState(&tlstate); - } - return &tlstate; -#else /* HAVE_COMPILER_TLS */ - xmlGlobalState *globalval; - xmlGlobalStateCleanupHelperParams *p; -#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) - globalval = (xmlGlobalState *) TlsGetValue(globalkey); -#else - p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey); - globalval = (xmlGlobalState *) (p ? p->memory : NULL); -#endif - if (globalval == NULL) { - xmlGlobalState *tsd = xmlNewGlobalState(); - - if (tsd == NULL) - return(NULL); - p = (xmlGlobalStateCleanupHelperParams *) - malloc(sizeof(xmlGlobalStateCleanupHelperParams)); - if (p == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGetGlobalState: out of memory\n"); - xmlFreeGlobalState(tsd); - return(NULL); - } - p->memory = tsd; -#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) - DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &p->thread, 0, TRUE, - DUPLICATE_SAME_ACCESS); - TlsSetValue(globalkey, tsd); - _beginthread(xmlGlobalStateCleanupHelper, 0, p); -#else - EnterCriticalSection(&cleanup_helpers_cs); - if (cleanup_helpers_head != NULL) { - cleanup_helpers_head->prev = p; - } - p->next = cleanup_helpers_head; - p->prev = NULL; - cleanup_helpers_head = p; - TlsSetValue(globalkey, p); - LeaveCriticalSection(&cleanup_helpers_cs); -#endif - - return (tsd); - } - return (globalval); -#endif /* HAVE_COMPILER_TLS */ -#else - return (NULL); -#endif -} - /************************************************************************ * * * Library wide thread interfaces * @@ -675,34 +388,6 @@ xmlGetThreadId(void) #endif }
-/** - * xmlIsMainThread: - * - * DEPRECATED: Internal function, do not use. - * - * xmlIsMainThread() check whether the current thread is the main thread. - * - * Returns 1 if the current thread is the main thread, 0 otherwise - */ -int -xmlIsMainThread(void) -{ - xmlInitParser(); - -#ifdef DEBUG_THREADS - xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n"); -#endif -#ifdef HAVE_POSIX_THREADS - if (XML_IS_THREADED() == 0) - return (1); - return (pthread_equal(mainthread,pthread_self())); -#elif defined HAVE_WIN32_THREADS - return (mainthread == GetCurrentThreadId()); -#else - return (1); -#endif -} - /** * xmlLockLibrary: * @@ -712,9 +397,6 @@ xmlIsMainThread(void) void xmlLockLibrary(void) { -#ifdef DEBUG_THREADS - xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n"); -#endif xmlRMutexLock(xmlLibraryLock); }
@@ -727,9 +409,6 @@ xmlLockLibrary(void) void xmlUnlockLibrary(void) { -#ifdef DEBUG_THREADS - xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n"); -#endif xmlRMutexUnlock(xmlLibraryLock); }
@@ -745,14 +424,44 @@ xmlInitThreads(void) }
/** - * xmlInitThreadsInternal: + * xmlCleanupThreads: * - * Used to to initialize all the thread related data. + * DEPRECATED: This function is a no-op. Call xmlCleanupParser + * to free global state but see the warnings there. xmlCleanupParser + * should be only called once at program exit. In most cases, you don't + * have call cleanup functions at all. */ void -xmlInitThreadsInternal(void) +xmlCleanupThreads(void) { +} + +/************************************************************************ + * * + * Library wide initialization * + * * + ************************************************************************/ + +static int xmlParserInitialized = 0; +static int xmlParserInnerInitialized = 0; + + +#ifdef HAVE_POSIX_THREADS +static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER; +#elif defined HAVE_WIN32_THREADS +static volatile LPCRITICAL_SECTION global_init_lock = NULL; +#endif + +/** + * xmlGlobalInitMutexLock + * + * Makes sure that the global initialization mutex is initialized and + * locks it. + */ +static void +xmlGlobalInitMutexLock(void) { #ifdef HAVE_POSIX_THREADS + #ifdef XML_PTHREAD_WEAK /* * This is somewhat unreliable since libpthread could be loaded @@ -761,10 +470,6 @@ xmlInitThreadsInternal(void) */ if (libxml_is_threaded == -1) libxml_is_threaded = - (pthread_getspecific != NULL) && - (pthread_setspecific != NULL) && - (pthread_key_create != NULL) && - (pthread_key_delete != NULL) && (pthread_mutex_init != NULL) && (pthread_mutex_destroy != NULL) && (pthread_mutex_lock != NULL) && @@ -779,136 +484,198 @@ xmlInitThreadsInternal(void) /* (pthread_equal != NULL) && */ (pthread_self != NULL) && (pthread_cond_signal != NULL); - if (libxml_is_threaded == 0) - return; -#endif /* XML_PTHREAD_WEAK */ - pthread_key_create(&globalkey, xmlFreeGlobalState); - mainthread = pthread_self(); -#elif defined(HAVE_WIN32_THREADS) -#if !defined(HAVE_COMPILER_TLS) -#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL) - InitializeCriticalSection(&cleanup_helpers_cs); #endif - globalkey = TlsAlloc(); + + /* The mutex is statically initialized, so we just lock it. */ + if (XML_IS_THREADED() != 0) + pthread_mutex_lock(&global_init_lock); + +#elif defined HAVE_WIN32_THREADS + + LPCRITICAL_SECTION cs; + + /* Create a new critical section */ + if (global_init_lock == NULL) { + cs = malloc(sizeof(CRITICAL_SECTION)); + if (cs == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlGlobalInitMutexLock: out of memory\n"); + return; + } + InitializeCriticalSection(cs); + + /* Swap it into the global_init_lock */ +#ifdef InterlockedCompareExchangePointer + InterlockedCompareExchangePointer((void **) &global_init_lock, + cs, NULL); +#else /* Use older void* version */ + InterlockedCompareExchange((void **) &global_init_lock, + (void *) cs, NULL); +#endif /* InterlockedCompareExchangePointer */ + + /* If another thread successfully recorded its critical + * section in the global_init_lock then discard the one + * allocated by this thread. */ + if (global_init_lock != cs) { + DeleteCriticalSection(cs); + free(cs); + } + } + + /* Lock the chosen critical section */ + EnterCriticalSection(global_init_lock); + #endif - mainthread = GetCurrentThreadId(); +} + +static void +xmlGlobalInitMutexUnlock(void) { +#ifdef HAVE_POSIX_THREADS + if (XML_IS_THREADED() != 0) + pthread_mutex_unlock(&global_init_lock); +#elif defined HAVE_WIN32_THREADS + if (global_init_lock != NULL) + LeaveCriticalSection(global_init_lock); #endif }
/** - * xmlCleanupThreads: + * xmlGlobalInitMutexDestroy * - * DEPRECATED: This function is a no-op. Call xmlCleanupParser - * to free global state but see the warnings there. xmlCleanupParser - * should be only called once at program exit. In most cases, you don't - * have call cleanup functions at all. + * Makes sure that the global initialization mutex is destroyed before + * application termination. */ -void -xmlCleanupThreads(void) -{ +static void +xmlGlobalInitMutexDestroy(void) { +#ifdef HAVE_POSIX_THREADS +#elif defined HAVE_WIN32_THREADS + if (global_init_lock != NULL) { + DeleteCriticalSection(global_init_lock); + free(global_init_lock); + global_init_lock = NULL; + } +#endif }
/** - * xmlCleanupThreadsInternal: + * xmlInitParser: + * + * Initialization function for the XML parser. * - * Used to to cleanup all the thread related data. + * Call once from the main thread before using the library in + * multithreaded programs. */ void -xmlCleanupThreadsInternal(void) -{ -#ifdef HAVE_POSIX_THREADS -#ifdef XML_PTHREAD_WEAK - if (libxml_is_threaded == 0) +xmlInitParser(void) { + /* + * Note that the initialization code must not make memory allocations. + */ + if (xmlParserInitialized != 0) return; -#endif /* XML_PTHREAD_WEAK */ - pthread_key_delete(globalkey); -#elif defined(HAVE_WIN32_THREADS) -#if !defined(HAVE_COMPILER_TLS) - if (globalkey != TLS_OUT_OF_INDEXES) { -#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL) - xmlGlobalStateCleanupHelperParams *p; - - EnterCriticalSection(&cleanup_helpers_cs); - p = cleanup_helpers_head; - while (p != NULL) { - xmlGlobalStateCleanupHelperParams *temp = p; - - p = p->next; - xmlFreeGlobalState(temp->memory); - free(temp); - } - cleanup_helpers_head = 0; - LeaveCriticalSection(&cleanup_helpers_cs); -#endif - TlsFree(globalkey); - globalkey = TLS_OUT_OF_INDEXES; - } -#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL) - DeleteCriticalSection(&cleanup_helpers_cs); -#endif + + xmlGlobalInitMutexLock(); + + if (xmlParserInnerInitialized == 0) { +#if defined(_WIN32) && \ + !defined(LIBXML_THREAD_ALLOC_ENABLED) && \ + (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) + if (xmlFree == free) + atexit(xmlCleanupParser); #endif + + xmlInitMemoryInternal(); /* Should come second */ + xmlInitGlobalsInternal(); + xmlInitRandom(); + xmlInitDictInternal(); + xmlInitEncodingInternal(); +#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) + xmlInitXPathInternal(); #endif + + xmlRegisterDefaultInputCallbacks(); +#ifdef LIBXML_OUTPUT_ENABLED + xmlRegisterDefaultOutputCallbacks(); +#endif /* LIBXML_OUTPUT_ENABLED */ + + xmlParserInnerInitialized = 1; + } + + xmlGlobalInitMutexUnlock(); + + xmlParserInitialized = 1; }
/** - * DllMain: - * @hinstDLL: handle to DLL instance - * @fdwReason: Reason code for entry - * @lpvReserved: generic pointer (depends upon reason code) - * - * Entry point for Windows library. It is being used to free thread-specific - * storage. - * - * Returns TRUE always + * xmlCleanupParser: + * + * This function name is somewhat misleading. It does not clean up + * parser state, it cleans up memory allocated by the library itself. + * It is a cleanup function for the XML library. It tries to reclaim all + * related global memory allocated for the library processing. + * It doesn't deallocate any document related memory. One should + * call xmlCleanupParser() only when the process has finished using + * the library and all XML/HTML documents built with it. + * See also xmlInitParser() which has the opposite function of preparing + * the library for operations. + * + * WARNING: if your application is multithreaded or has plugin support + * calling this may crash the application if another thread or + * a plugin is still using libxml2. It's sometimes very hard to + * guess if libxml2 is in use in the application, some libraries + * or plugins may use it without notice. In case of doubt abstain + * from calling this function or do it just before calling exit() + * to avoid leak reports from valgrind ! */ -#ifdef HAVE_POSIX_THREADS -#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) -#if defined(LIBXML_STATIC_FOR_DLL) -int -xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason, - ATTRIBUTE_UNUSED void *lpvReserved) -#else -/* declare to avoid "no previous prototype for 'DllMain'" warning */ -/* Note that we do NOT want to include this function declaration in - a public header because it's meant to be called by Windows itself, - not a program that uses this library. This also has to be exported. */ - -XMLPUBFUN BOOL WINAPI -DllMain (HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved); - -BOOL WINAPI -DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason, - ATTRIBUTE_UNUSED LPVOID lpvReserved) +void +xmlCleanupParser(void) { + if (!xmlParserInitialized) + return; + + /* These functions can call xmlFree. */ + + xmlCleanupCharEncodingHandlers(); +#ifdef LIBXML_CATALOG_ENABLED + xmlCatalogCleanup(); #endif -{ - switch (fdwReason) { - case DLL_THREAD_DETACH: - if (globalkey != TLS_OUT_OF_INDEXES) { - xmlGlobalState *globalval = NULL; - xmlGlobalStateCleanupHelperParams *p = - (xmlGlobalStateCleanupHelperParams *) - TlsGetValue(globalkey); - globalval = (xmlGlobalState *) (p ? p->memory : NULL); - if (globalval) { - xmlFreeGlobalState(globalval); - TlsSetValue(globalkey, NULL); - } - if (p) { - EnterCriticalSection(&cleanup_helpers_cs); - if (p == cleanup_helpers_head) - cleanup_helpers_head = p->next; - else - p->prev->next = p->next; - if (p->next != NULL) - p->next->prev = p->prev; - LeaveCriticalSection(&cleanup_helpers_cs); - free(p); - } - } - break; - } - return TRUE; +#ifdef LIBXML_SCHEMAS_ENABLED + xmlSchemaCleanupTypes(); + xmlRelaxNGCleanupTypes(); +#endif + + /* These functions should never call xmlFree. */ + + xmlCleanupInputCallbacks(); +#ifdef LIBXML_OUTPUT_ENABLED + xmlCleanupOutputCallbacks(); +#endif + + xmlCleanupDictInternal(); + xmlCleanupRandom(); + xmlCleanupGlobalsInternal(); + /* + * Must come last. On Windows, xmlCleanupGlobalsInternal can call + * xmlFree which uses xmlMemMutex in debug mode. + */ + xmlCleanupMemoryInternal(); + + xmlGlobalInitMutexDestroy(); + + xmlParserInitialized = 0; + xmlParserInnerInitialized = 0; +} + +#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && \ + !defined(LIBXML_THREAD_ALLOC_ENABLED) && \ + !defined(LIBXML_STATIC) && \ + !defined(_WIN32) +static void +ATTRIBUTE_DESTRUCTOR +xmlDestructor(void) { + /* + * Calling custom deallocation functions in a destructor can cause + * problems, for example with Nokogiri. + */ + if (xmlFree == free) + xmlCleanupParser(); } #endif diff --git a/libs/xml2/tree.c b/libs/xml2/tree.c index eae778d6541..9f261407dcc 100644 --- a/libs/xml2/tree.c +++ b/libs/xml2/tree.c @@ -28,15 +28,13 @@ #include <zlib.h> #endif
-#include <libxml/xmlmemory.h> #include <libxml/tree.h> +#include <libxml/xmlmemory.h> #include <libxml/parser.h> #include <libxml/uri.h> #include <libxml/entities.h> -#include <libxml/valid.h> #include <libxml/xmlerror.h> #include <libxml/parserInternals.h> -#include <libxml/globals.h> #ifdef LIBXML_HTML_ENABLED #include <libxml/HTMLtree.h> #endif @@ -142,9 +140,6 @@ static int xmlCheckDTD = 1; #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \ (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
-/* #define DEBUG_BUFFER */ -/* #define DEBUG_TREE */ - /************************************************************************ * * * Functions to move to entities.c once the * @@ -357,7 +352,6 @@ xmlSplitQName3(const xmlChar *name, int *len) {
#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
-#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED) /** * xmlValidateNCName: * @value: the value to check @@ -429,7 +423,6 @@ try_complex:
return(0); } -#endif
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) /** @@ -805,10 +798,6 @@ xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { void xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { if (node == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlSetNs: node == NULL\n"); -#endif return; } if ((node->type == XML_ELEMENT_NODE) || @@ -825,10 +814,6 @@ xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { void xmlFreeNs(xmlNsPtr cur) { if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeNs : ns == NULL\n"); -#endif return; } if (cur->href != NULL) xmlFree((char *) cur->href); @@ -846,10 +831,6 @@ void xmlFreeNsList(xmlNsPtr cur) { xmlNsPtr next; if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeNsList : ns == NULL\n"); -#endif return; } while (cur != NULL) { @@ -877,12 +858,6 @@ xmlNewDtd(xmlDocPtr doc, const xmlChar *name, xmlDtdPtr cur;
if ((doc != NULL) && (doc->extSubset != NULL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewDtd(%s): document %s already have a DTD %s\n", - /* !!! */ (char *) name, doc->name, - /* !!! */ (char *)doc->extSubset->name); -#endif return(NULL); }
@@ -951,12 +926,6 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, xmlDtdPtr cur;
if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - - "xmlCreateIntSubset(): document %s already have an internal subset\n", - doc->name); -#endif return(NULL); }
@@ -1210,10 +1179,6 @@ xmlFreeDoc(xmlDocPtr cur) { xmlDictPtr dict = NULL;
if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeDoc : document == NULL\n"); -#endif return; }
@@ -1965,10 +1930,6 @@ xmlAttrPtr xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewProp : name == NULL\n"); -#endif return(NULL); }
@@ -1991,10 +1952,6 @@ xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, const xmlChar *value) {
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNsProp : name == NULL\n"); -#endif return(NULL); }
@@ -2016,10 +1973,6 @@ xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name, const xmlChar *value) {
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNsPropEatName : name == NULL\n"); -#endif return(NULL); }
@@ -2045,10 +1998,6 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { xmlAttrPtr cur;
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewDocProp : name == NULL\n"); -#endif return(NULL); }
@@ -2143,17 +2092,9 @@ int xmlRemoveProp(xmlAttrPtr cur) { xmlAttrPtr tmp; if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlRemoveProp : cur == NULL\n"); -#endif return(-1); } if (cur->parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlRemoveProp : cur->parent == NULL\n"); -#endif return(-1); } tmp = cur->parent->properties; @@ -2174,10 +2115,6 @@ xmlRemoveProp(xmlAttrPtr cur) { } tmp = tmp->next; } -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlRemoveProp : attribute not owned by its node\n"); -#endif return(-1); }
@@ -2195,10 +2132,6 @@ xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) { xmlNodePtr cur;
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewPI : name == NULL\n"); -#endif return(NULL); }
@@ -2260,10 +2193,6 @@ xmlNewNode(xmlNsPtr ns, const xmlChar *name) { xmlNodePtr cur;
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNode : name == NULL\n"); -#endif return(NULL); }
@@ -2304,10 +2233,6 @@ xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) { xmlNodePtr cur;
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNode : name == NULL\n"); -#endif return(NULL); }
@@ -2526,18 +2451,10 @@ xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns, xmlNodePtr cur, prev;
if (parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextChild : parent == NULL\n"); -#endif return(NULL); }
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextChild : name == NULL\n"); -#endif return(NULL); }
@@ -2961,18 +2878,10 @@ xmlNewChild(xmlNodePtr parent, xmlNsPtr ns, xmlNodePtr cur, prev;
if (parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewChild : parent == NULL\n"); -#endif return(NULL); }
if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewChild : name == NULL\n"); -#endif return(NULL); }
@@ -3089,25 +2998,13 @@ xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) { xmlNodePtr xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) { if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddNextSibling : cur == NULL\n"); -#endif return(NULL); } if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddNextSibling : elem == NULL\n"); -#endif return(NULL); }
if (cur == elem) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddNextSibling : cur == elem\n"); -#endif return(NULL); }
@@ -3169,25 +3066,13 @@ xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) { xmlNodePtr xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) { if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddPrevSibling : cur == NULL\n"); -#endif return(NULL); } if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddPrevSibling : elem == NULL\n"); -#endif return(NULL); }
if (cur == elem) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddPrevSibling : cur == elem\n"); -#endif return(NULL); }
@@ -3249,26 +3134,14 @@ xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) { xmlNodePtr parent;
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddSibling : cur == NULL\n"); -#endif return(NULL); }
if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddSibling : elem == NULL\n"); -#endif return(NULL); }
if (cur == elem) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddSibling : cur == elem\n"); -#endif return(NULL); }
@@ -3327,27 +3200,15 @@ xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { xmlNodePtr prev;
if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChildList : parent == NULL\n"); -#endif return(NULL); }
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChildList : child == NULL\n"); -#endif return(NULL); }
if ((cur->doc != NULL) && (parent->doc != NULL) && (cur->doc != parent->doc)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "Elements moved to a different document\n"); -#endif }
/* @@ -3419,26 +3280,14 @@ xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { xmlNodePtr prev;
if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChild : parent == NULL\n"); -#endif return(NULL); }
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChild : child == NULL\n"); -#endif return(NULL); }
if (parent == cur) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChild : parent == cur\n"); -#endif return(NULL); } /* @@ -3541,10 +3390,6 @@ xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { xmlNodePtr xmlGetLastChild(const xmlNode *parent) { if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlGetLastChild : parent == NULL\n"); -#endif return(NULL); } return(parent->last); @@ -3909,10 +3754,6 @@ xmlFreeNode(xmlNodePtr cur) { void xmlUnlinkNode(xmlNodePtr cur) { if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlUnlinkNode : node == NULL\n"); -#endif return; } if (cur->type == XML_NAMESPACE_DECL) @@ -3989,10 +3830,6 @@ xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { if (old == cur) return(NULL); if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) || (old->parent == NULL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : old == NULL or without parent\n"); -#endif return(NULL); } if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { @@ -4003,17 +3840,9 @@ xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { return(old); } if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : Trying to replace attribute node with other node type\n"); -#endif return(old); } if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n"); -#endif return(old); } xmlUnlinkNode(cur); @@ -4066,10 +3895,6 @@ xmlCopyNamespace(xmlNsPtr cur) { ret = xmlNewNs(NULL, cur->href, cur->prefix); break; default: -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlCopyNamespace: invalid type %d\n", cur->type); -#endif return(NULL); } return(ret); @@ -4381,7 +4206,10 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, /* * Humm, we are copying an element whose namespace is defined * out of the new tree scope. Search it in the original tree - * and add it at the top of the new tree + * and add it at the top of the new tree. + * + * TODO: Searching the original tree seems unnecessary. We + * already have a namespace URI. */ ns = xmlSearchNs(node->doc, node, node->ns->prefix); if (ns != NULL) { @@ -4389,8 +4217,8 @@ xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
while (root->parent != NULL) root = root->parent; ret->ns = xmlNewNs(root, ns->href, ns->prefix); - } else { - ret->ns = xmlNewReconciledNs(doc, ret, node->ns); + } else { + ret->ns = xmlNewReconciledNs(doc, ret, node->ns); } } else { /* @@ -4473,6 +4301,8 @@ xmlNodePtr xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { xmlNodePtr ret = NULL; xmlNodePtr p = NULL,q; + xmlDtdPtr newSubset = NULL; + int linkedSubset = 0;
while (node != NULL) { #ifdef LIBXML_TREE_ENABLED @@ -4481,14 +4311,15 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { node = node->next; continue; } - if (doc->intSubset == NULL) { + if ((doc->intSubset == NULL) && (newSubset == NULL)) { q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node ); if (q == NULL) goto error; q->doc = doc; q->parent = parent; - doc->intSubset = (xmlDtdPtr) q; + newSubset = (xmlDtdPtr) q; xmlAddChild(parent, q); } else { + linkedSubset = 1; q = (xmlNodePtr) doc->intSubset; xmlAddChild(parent, q); } @@ -4507,8 +4338,12 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { } node = node->next; } + if ((doc != NULL) && (newSubset != NULL)) + doc->intSubset = newSubset; return(ret); error: + if (linkedSubset != 0) + xmlUnlinkNode((xmlNodePtr) doc->intSubset); xmlFreeNodeList(ret); return(NULL); } @@ -5771,10 +5606,6 @@ xmlNodeGetContent(const xmlNode *cur) void xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeSetContent : node == NULL\n"); -#endif return; } switch (cur->type) { @@ -5844,10 +5675,6 @@ xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { void xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeSetContentLen : node == NULL\n"); -#endif return; } switch (cur->type) { @@ -5914,10 +5741,6 @@ xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { void xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeAddContentLen : node == NULL\n"); -#endif return; } if (len <= 0) return; @@ -5988,10 +5811,6 @@ xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) { int len;
if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeAddContent : node == NULL\n"); -#endif return; } if (content == NULL) return; @@ -6357,17 +6176,9 @@ xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { int counter = 1;
if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewReconciledNs : tree == NULL\n"); -#endif return(NULL); } if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewReconciledNs : ns == NULL\n"); -#endif return(NULL); } /* @@ -7114,10 +6925,6 @@ xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) { (node->type != XML_CDATA_SECTION_NODE) && (node->type != XML_COMMENT_NODE) && (node->type != XML_PI_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlTextConcat: node is not text nor CDATA\n"); -#endif return(-1); } /* need to check if content is currently in the dictionary */ @@ -7235,7 +7042,7 @@ xmlBufferDetach(xmlBufferPtr buf) { * @mem: the memory area * @size: the size in byte * - * Create an XML buffer initialized with bytes. + * Returns an XML buffer initialized with bytes. */ xmlBufferPtr xmlBufferCreateStatic(void *mem, size_t size) { @@ -7256,10 +7063,6 @@ void xmlBufferSetAllocationScheme(xmlBufferPtr buf, xmlBufferAllocationScheme scheme) { if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferSetAllocationScheme: buf == NULL\n"); -#endif return; } if (buf->alloc == XML_BUFFER_ALLOC_IO) return; @@ -7279,10 +7082,6 @@ xmlBufferSetAllocationScheme(xmlBufferPtr buf, void xmlBufferFree(xmlBufferPtr buf) { if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferFree: buf == NULL\n"); -#endif return; }
@@ -7426,17 +7225,9 @@ xmlBufferDump(FILE *file, xmlBufferPtr buf) { size_t ret;
if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferDump: buf == NULL\n"); -#endif return(0); } if (buf->content == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferDump: buf->content == NULL\n"); -#endif return(0); } if (file == NULL) @@ -7618,10 +7409,6 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { return -1; } if (len < -1) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAdd: len < 0\n"); -#endif return -1; } if (len == 0) return 0; @@ -7670,17 +7457,9 @@ xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) { if (buf == NULL) return(-1); if (str == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAddHead: str == NULL\n"); -#endif return -1; } if (len < -1) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAddHead: len < 0\n"); -#endif return -1; } if (len == 0) return 0; @@ -7805,10 +7584,6 @@ xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) { return; if (xmlStrchr(string, '"')) { if (xmlStrchr(string, ''')) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n"); -#endif xmlBufferCCat(buf, """); base = cur = string; while(*cur != 0){ @@ -10270,3 +10045,44 @@ xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) { return(0); }
+/************************************************************************ + * * + * Node callbacks * + * * + ************************************************************************/ + +/** + * xmlRegisterNodeDefault: + * @func: function pointer to the new RegisterNodeFunc + * + * Registers a callback for node creation + * + * Returns the old value of the registration function + */ +xmlRegisterNodeFunc +xmlRegisterNodeDefault(xmlRegisterNodeFunc func) +{ + xmlRegisterNodeFunc old = xmlRegisterNodeDefaultValue; + + __xmlRegisterCallbacks = 1; + xmlRegisterNodeDefaultValue = func; + return(old); +} + +/** + * xmlDeregisterNodeDefault: + * @func: function pointer to the new DeregisterNodeFunc + * + * Registers a callback for node destruction + * + * Returns the previous value of the deregistration function + */ +xmlDeregisterNodeFunc +xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func) +{ + xmlDeregisterNodeFunc old = xmlDeregisterNodeDefaultValue; + + __xmlRegisterCallbacks = 1; + xmlDeregisterNodeDefaultValue = func; + return(old); +} diff --git a/libs/xml2/uri.c b/libs/xml2/uri.c index c3d4871f02a..03b5a31aa60 100644 --- a/libs/xml2/uri.c +++ b/libs/xml2/uri.c @@ -16,7 +16,6 @@
#include <libxml/xmlmemory.h> #include <libxml/uri.h> -#include <libxml/globals.h> #include <libxml/xmlerror.h>
#include "private/error.h" diff --git a/libs/xml2/valid.c b/libs/xml2/valid.c index 5ee9906cf25..886485d67ea 100644 --- a/libs/xml2/valid.c +++ b/libs/xml2/valid.c @@ -21,7 +21,6 @@ #include <libxml/parserInternals.h> #include <libxml/xmlerror.h> #include <libxml/list.h> -#include <libxml/globals.h>
#include "private/error.h" #include "private/parser.h" @@ -29,8 +28,6 @@ static xmlElementPtr xmlGetDtdElementDesc2(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, int create); -/* #define DEBUG_VALID_ALGO */ -/* #define DEBUG_REGEXP_ALGO */
#define TODO \ xmlGenericError(xmlGenericErrorContext, \ @@ -465,151 +462,6 @@ nodeVPop(xmlValidCtxtPtr ctxt) return (ret); }
-#ifdef DEBUG_VALID_ALGO -static void -xmlValidPrintNode(xmlNodePtr cur) { - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, "null"); - return; - } - switch (cur->type) { - case XML_ELEMENT_NODE: - xmlGenericError(xmlGenericErrorContext, "%s ", cur->name); - break; - case XML_TEXT_NODE: - xmlGenericError(xmlGenericErrorContext, "text "); - break; - case XML_CDATA_SECTION_NODE: - xmlGenericError(xmlGenericErrorContext, "cdata "); - break; - case XML_ENTITY_REF_NODE: - xmlGenericError(xmlGenericErrorContext, "&%s; ", cur->name); - break; - case XML_PI_NODE: - xmlGenericError(xmlGenericErrorContext, "pi(%s) ", cur->name); - break; - case XML_COMMENT_NODE: - xmlGenericError(xmlGenericErrorContext, "comment "); - break; - case XML_ATTRIBUTE_NODE: - xmlGenericError(xmlGenericErrorContext, "?attr? "); - break; - case XML_ENTITY_NODE: - xmlGenericError(xmlGenericErrorContext, "?ent? "); - break; - case XML_DOCUMENT_NODE: - xmlGenericError(xmlGenericErrorContext, "?doc? "); - break; - case XML_DOCUMENT_TYPE_NODE: - xmlGenericError(xmlGenericErrorContext, "?doctype? "); - break; - case XML_DOCUMENT_FRAG_NODE: - xmlGenericError(xmlGenericErrorContext, "?frag? "); - break; - case XML_NOTATION_NODE: - xmlGenericError(xmlGenericErrorContext, "?nota? "); - break; - case XML_HTML_DOCUMENT_NODE: - xmlGenericError(xmlGenericErrorContext, "?html? "); - break; - case XML_DTD_NODE: - xmlGenericError(xmlGenericErrorContext, "?dtd? "); - break; - case XML_ELEMENT_DECL: - xmlGenericError(xmlGenericErrorContext, "?edecl? "); - break; - case XML_ATTRIBUTE_DECL: - xmlGenericError(xmlGenericErrorContext, "?adecl? "); - break; - case XML_ENTITY_DECL: - xmlGenericError(xmlGenericErrorContext, "?entdecl? "); - break; - case XML_NAMESPACE_DECL: - xmlGenericError(xmlGenericErrorContext, "?nsdecl? "); - break; - case XML_XINCLUDE_START: - xmlGenericError(xmlGenericErrorContext, "incstart "); - break; - case XML_XINCLUDE_END: - xmlGenericError(xmlGenericErrorContext, "incend "); - break; - } -} - -static void -xmlValidPrintNodeList(xmlNodePtr cur) { - if (cur == NULL) - xmlGenericError(xmlGenericErrorContext, "null "); - while (cur != NULL) { - xmlValidPrintNode(cur); - cur = cur->next; - } -} - -static void -xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) { - char expr[5000]; - - expr[0] = 0; - xmlGenericError(xmlGenericErrorContext, "valid: "); - xmlValidPrintNodeList(cur); - xmlGenericError(xmlGenericErrorContext, "against "); - xmlSnprintfElementContent(expr, 5000, cont, 1); - xmlGenericError(xmlGenericErrorContext, "%s\n", expr); -} - -static void -xmlValidDebugState(xmlValidStatePtr state) { - xmlGenericError(xmlGenericErrorContext, "("); - if (state->cont == NULL) - xmlGenericError(xmlGenericErrorContext, "null,"); - else - switch (state->cont->type) { - case XML_ELEMENT_CONTENT_PCDATA: - xmlGenericError(xmlGenericErrorContext, "pcdata,"); - break; - case XML_ELEMENT_CONTENT_ELEMENT: - xmlGenericError(xmlGenericErrorContext, "%s,", - state->cont->name); - break; - case XML_ELEMENT_CONTENT_SEQ: - xmlGenericError(xmlGenericErrorContext, "seq,"); - break; - case XML_ELEMENT_CONTENT_OR: - xmlGenericError(xmlGenericErrorContext, "or,"); - break; - } - xmlValidPrintNode(state->node); - xmlGenericError(xmlGenericErrorContext, ",%d,%X,%d)", - state->depth, state->occurs, state->state); -} - -static void -xmlValidStateDebug(xmlValidCtxtPtr ctxt) { - int i, j; - - xmlGenericError(xmlGenericErrorContext, "state: "); - xmlValidDebugState(ctxt->vstate); - xmlGenericError(xmlGenericErrorContext, " stack: %d ", - ctxt->vstateNr - 1); - for (i = 0, j = ctxt->vstateNr - 1;(i < 3) && (j > 0);i++,j--) - xmlValidDebugState(&ctxt->vstateTab[j]); - xmlGenericError(xmlGenericErrorContext, "\n"); -} - -/***** -#define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c); - *****/ - -#define DEBUG_VALID_STATE(n,c) xmlValidStateDebug(ctxt); -#define DEBUG_VALID_MSG(m) \ - xmlGenericError(xmlGenericErrorContext, "%s\n", m); - -#else -#define DEBUG_VALID_STATE(n,c) -#define DEBUG_VALID_MSG(m) -#endif - /* TODO: use hash table for accesses to elem and attribute definitions */
@@ -828,9 +680,6 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) { XML_DTD_CONTENT_NOT_DETERMINIST, "Content model of %s is not deterministic: %s\n", elem->name, BAD_CAST expr, NULL); -#ifdef DEBUG_REGEXP_ALGO - xmlRegexpPrint(stderr, elem->contModel); -#endif ctxt->valid = 0; ctxt->state = NULL; xmlFreeAutomata(ctxt->am); @@ -4892,13 +4741,10 @@ cont: * epsilon transition, go directly to the analysis phase */ if (STATE == ROLLBACK_PARENT) { - DEBUG_VALID_MSG("restored parent branch"); - DEBUG_VALID_STATE(NODE, CONT) ret = 1; goto analyze; }
- DEBUG_VALID_STATE(NODE, CONT) /* * we may have to save a backup state here. This is the equivalent * of handling epsilon transition in NFAs. @@ -4910,7 +4756,6 @@ cont: ((CONT->ocur == XML_ELEMENT_CONTENT_MULT) || (CONT->ocur == XML_ELEMENT_CONTENT_OPT) || ((CONT->ocur == XML_ELEMENT_CONTENT_PLUS) && (OCCURRENCE)))) { - DEBUG_VALID_MSG("saving parent branch"); if (vstateVPush(ctxt, CONT, NODE, DEPTH, OCCURS, ROLLBACK_PARENT) < 0) return(0); } @@ -4922,12 +4767,10 @@ cont: switch (CONT->type) { case XML_ELEMENT_CONTENT_PCDATA: if (NODE == NULL) { - DEBUG_VALID_MSG("pcdata failed no node"); ret = 0; break; } if (NODE->type == XML_TEXT_NODE) { - DEBUG_VALID_MSG("pcdata found, skip to next"); /* * go to next element in the content model * skipping ignorable elems @@ -4945,14 +4788,12 @@ cont: ret = 1; break; } else { - DEBUG_VALID_MSG("pcdata failed"); ret = 0; break; } break; case XML_ELEMENT_CONTENT_ELEMENT: if (NODE == NULL) { - DEBUG_VALID_MSG("element failed no node"); ret = 0; break; } @@ -4968,7 +4809,6 @@ cont: } } if (ret == 1) { - DEBUG_VALID_MSG("element found, skip to next"); /* * go to next element in the content model * skipping ignorable elems @@ -4984,7 +4824,6 @@ cont: (NODE->type != XML_TEXT_NODE) && (NODE->type != XML_CDATA_SECTION_NODE))); } else { - DEBUG_VALID_MSG("element failed"); ret = 0; break; } @@ -5017,7 +4856,6 @@ cont: /* * save the second branch 'or' branch */ - DEBUG_VALID_MSG("saving 'or' branch"); if (vstateVPush(ctxt, CONT->c2, NODE, DEPTH + 1, OCCURS, ROLLBACK_OR) < 0) return(-1); @@ -5059,7 +4897,6 @@ cont: * At this point handle going up in the tree */ if (ret == -1) { - DEBUG_VALID_MSG("error found returning"); return(ret); } analyze: @@ -5074,9 +4911,7 @@ analyze:
case XML_ELEMENT_CONTENT_ONCE: cur = ctxt->vstate->node; - DEBUG_VALID_MSG("Once branch failed, rollback"); if (vstateVPop(ctxt) < 0 ) { - DEBUG_VALID_MSG("exhaustion, failed"); return(0); } if (cur != ctxt->vstate->node) @@ -5085,69 +4920,50 @@ analyze: case XML_ELEMENT_CONTENT_PLUS: if (OCCURRENCE == 0) { cur = ctxt->vstate->node; - DEBUG_VALID_MSG("Plus branch failed, rollback"); if (vstateVPop(ctxt) < 0 ) { - DEBUG_VALID_MSG("exhaustion, failed"); return(0); } if (cur != ctxt->vstate->node) determinist = -3; goto cont; } - DEBUG_VALID_MSG("Plus branch found"); ret = 1; break; case XML_ELEMENT_CONTENT_MULT: -#ifdef DEBUG_VALID_ALGO - if (OCCURRENCE == 0) { - DEBUG_VALID_MSG("Mult branch failed"); - } else { - DEBUG_VALID_MSG("Mult branch found"); - } -#endif ret = 1; break; case XML_ELEMENT_CONTENT_OPT: - DEBUG_VALID_MSG("Option branch failed"); ret = 1; break; } } else { switch (CONT->ocur) { case XML_ELEMENT_CONTENT_OPT: - DEBUG_VALID_MSG("Option branch succeeded"); ret = 1; break; case XML_ELEMENT_CONTENT_ONCE: - DEBUG_VALID_MSG("Once branch succeeded"); ret = 1; break; case XML_ELEMENT_CONTENT_PLUS: if (STATE == ROLLBACK_PARENT) { - DEBUG_VALID_MSG("Plus branch rollback"); ret = 1; break; } if (NODE == NULL) { - DEBUG_VALID_MSG("Plus branch exhausted"); ret = 1; break; } - DEBUG_VALID_MSG("Plus branch succeeded, continuing"); SET_OCCURRENCE; goto cont; case XML_ELEMENT_CONTENT_MULT: if (STATE == ROLLBACK_PARENT) { - DEBUG_VALID_MSG("Mult branch rollback"); ret = 1; break; } if (NODE == NULL) { - DEBUG_VALID_MSG("Mult branch exhausted"); ret = 1; break; } - DEBUG_VALID_MSG("Mult branch succeeded, continuing"); /* SET_OCCURRENCE; */ goto cont; } @@ -5164,33 +4980,26 @@ analyze:
switch (CONT->parent->type) { case XML_ELEMENT_CONTENT_PCDATA: - DEBUG_VALID_MSG("Error: parent pcdata"); return(-1); case XML_ELEMENT_CONTENT_ELEMENT: - DEBUG_VALID_MSG("Error: parent element"); return(-1); case XML_ELEMENT_CONTENT_OR: if (ret == 1) { - DEBUG_VALID_MSG("Or succeeded"); CONT = CONT->parent; DEPTH--; } else { - DEBUG_VALID_MSG("Or failed"); CONT = CONT->parent; DEPTH--; } break; case XML_ELEMENT_CONTENT_SEQ: if (ret == 0) { - DEBUG_VALID_MSG("Sequence failed"); CONT = CONT->parent; DEPTH--; } else if (CONT == CONT->parent->c1) { - DEBUG_VALID_MSG("Sequence testing 2nd branch"); CONT = CONT->parent->c2; goto cont; } else { - DEBUG_VALID_MSG("Sequence succeeded"); CONT = CONT->parent; DEPTH--; } @@ -5200,9 +5009,7 @@ analyze: xmlNodePtr cur;
cur = ctxt->vstate->node; - DEBUG_VALID_MSG("Failed, remaining input, rollback"); if (vstateVPop(ctxt) < 0 ) { - DEBUG_VALID_MSG("exhaustion, failed"); return(0); } if (cur != ctxt->vstate->node) @@ -5213,9 +5020,7 @@ analyze: xmlNodePtr cur;
cur = ctxt->vstate->node; - DEBUG_VALID_MSG("Failure, rollback"); if (vstateVPop(ctxt) < 0 ) { - DEBUG_VALID_MSG("exhaustion, failed"); return(0); } if (cur != ctxt->vstate->node) @@ -5454,7 +5259,6 @@ fail: * Build a minimal representation of this node content * sufficient to run the validation process on it */ - DEBUG_VALID_MSG("Found an entity reference, linearizing"); cur = child; while (cur != NULL) { switch (cur->type) { @@ -6460,7 +6264,7 @@ name_ok: * xmlValidateElement: * @ctxt: the validation context * @doc: a document instance - * @elem: an element instance + * @root: an element instance * * Try to validate the subtree under an element * diff --git a/libs/xml2/xinclude.c b/libs/xml2/xinclude.c index 9e7a2bed815..b6581558d93 100644 --- a/libs/xml2/xinclude.c +++ b/libs/xml2/xinclude.c @@ -22,7 +22,6 @@ #include <libxml/parserInternals.h> #include <libxml/xmlerror.h> #include <libxml/encoding.h> -#include <libxml/globals.h>
#ifdef LIBXML_XINCLUDE_ENABLED #include <libxml/xinclude.h> @@ -34,13 +33,6 @@
#define XINCLUDE_MAX_DEPTH 40
-/* #define DEBUG_XINCLUDE */ -#ifdef DEBUG_XINCLUDE -#ifdef LIBXML_DEBUG_ENABLED -#include <libxml/debugXML.h> -#endif -#endif - /************************************************************************ * * * XInclude context handling * @@ -222,9 +214,6 @@ static void xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) { if (ref == NULL) return; -#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "Freeing ref\n"); -#endif if (ref->URI != NULL) xmlFree(ref->URI); if (ref->fragment != NULL) @@ -247,9 +236,6 @@ xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI, xmlNodePtr elem) { xmlXIncludeRefPtr ret;
-#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "New ref %s\n", URI); -#endif ret = (xmlXIncludeRefPtr) xmlMalloc(sizeof(xmlXIncludeRef)); if (ret == NULL) { xmlXIncludeErrMemory(ctxt, elem, "growing XInclude context"); @@ -264,19 +250,13 @@ xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI, ret->elem = elem; ret->xml = 0; ret->inc = NULL; - if (ctxt->incMax == 0) { - ctxt->incMax = 4; - ctxt->incTab = (xmlXIncludeRefPtr *) xmlMalloc(ctxt->incMax * - sizeof(ctxt->incTab[0])); - if (ctxt->incTab == NULL) { - xmlXIncludeErrMemory(ctxt, elem, "growing XInclude context"); - xmlXIncludeFreeRef(ret); - return(NULL); - } - } if (ctxt->incNr >= ctxt->incMax) { xmlXIncludeRefPtr *tmp; - size_t newSize = ctxt->incMax * 2; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 1; +#else + size_t newSize = ctxt->incMax ? ctxt->incMax * 2 : 4; +#endif
tmp = (xmlXIncludeRefPtr *) xmlRealloc(ctxt->incTab, newSize * sizeof(ctxt->incTab[0])); @@ -286,7 +266,7 @@ xmlXIncludeNewRef(xmlXIncludeCtxtPtr ctxt, const xmlChar *URI, return(NULL); } ctxt->incTab = tmp; - ctxt->incMax *= 2; + ctxt->incMax = newSize; } ctxt->incTab[ctxt->incNr++] = ret; return(ret); @@ -304,9 +284,6 @@ xmlXIncludeCtxtPtr xmlXIncludeNewContext(xmlDocPtr doc) { xmlXIncludeCtxtPtr ret;
-#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "New context\n"); -#endif if (doc == NULL) return(NULL); ret = (xmlXIncludeCtxtPtr) xmlMalloc(sizeof(xmlXIncludeCtxt)); @@ -334,9 +311,6 @@ void xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) { int i;
-#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "Freeing context\n"); -#endif if (ctxt == NULL) return; if (ctxt->urlTab != NULL) { @@ -463,9 +437,6 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) { if (cur == NULL) return(NULL);
-#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "Add node\n"); -#endif /* * read the attributes */ @@ -1271,9 +1242,6 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int saveFlags; #endif
-#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "Loading doc %s\n", url); -#endif /* * Check the URL and remove any fragment identifier */ @@ -1314,9 +1282,6 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, */ for (i = 0; i < ctxt->urlNr; i++) { if (xmlStrEqual(URL, ctxt->urlTab[i].url)) { -#ifdef DEBUG_XINCLUDE - printf("Already loaded %s\n", URL); -#endif if (ctxt->urlTab[i].expanding) { xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_RECURSION, "inclusion loop detected\n", NULL); @@ -1332,9 +1297,6 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, /* * Load it. */ -#ifdef DEBUG_XINCLUDE - printf("loading %s\n", URL); -#endif #ifdef LIBXML_XPTR_ENABLED /* * If this is an XPointer evaluation, we want to assure that @@ -1355,7 +1317,11 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, /* Also cache NULL docs */ if (ctxt->urlNr >= ctxt->urlMax) { xmlXIncludeDoc *tmp; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + size_t newSize = ctxt->urlMax ? ctxt->urlMax * 2 : 1; +#else size_t newSize = ctxt->urlMax ? ctxt->urlMax * 2 : 8; +#endif
tmp = xmlRealloc(ctxt->urlTab, sizeof(xmlXIncludeDoc) * newSize); if (tmp == NULL) { @@ -1749,8 +1715,9 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int cur; int l;
- cur = xmlStringCurrentChar(NULL, &content[i], &l); - if (!IS_CHAR(cur)) { + l = len - i; + cur = xmlGetUTF8Char(&content[i], &l); + if ((cur < 0) || (!IS_CHAR(cur))) { xmlXIncludeErr(ctxt, ref->elem, XML_XINCLUDE_INVALID_CHAR, "%s contains invalid char\n", URL); goto error; @@ -1763,7 +1730,11 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url,
if (ctxt->txtNr >= ctxt->txtMax) { xmlXIncludeTxt *tmp; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + size_t newSize = ctxt->txtMax ? ctxt->txtMax * 2 : 1; +#else size_t newSize = ctxt->txtMax ? ctxt->txtMax * 2 : 8; +#endif
tmp = xmlRealloc(ctxt->txtTab, sizeof(xmlXIncludeTxt) * newSize); if (tmp == NULL) { @@ -1870,6 +1841,20 @@ xmlXIncludeExpandNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) { * The XInclude engine offers no protection against exponential * expansion attacks similar to "billion laughs". Avoid timeouts by * limiting the total number of replacements when fuzzing. + * + * Unfortuately, a single XInclude can already result in quadratic + * behavior: + * + * <doc xmlns:xi="http://www.w3.org/2001/XInclude"> + * <xi:include xpointer="xpointer(//e)"/> + * <e> + * <e> + * <e> + * <!-- more nested elements --> + * </e> + * </e> + * </e> + * </doc> */ if (ctxt->incTotal >= 20) return(NULL); @@ -1985,11 +1970,6 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { xmlFree(base); return(-1); } -#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "parse: %s\n", - xml ? "xml": "text"); - xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI); -#endif
/* * Save the base for this include (saving the current one) @@ -2015,9 +1995,6 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, xmlXIncludeRefPtr ref) { /* * Time to try a fallback if available */ -#ifdef DEBUG_XINCLUDE - xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n"); -#endif children = cur->children; while (children != NULL) { if ((children->type == XML_ELEMENT_NODE) && diff --git a/libs/xml2/xmlIO.c b/libs/xml2/xmlIO.c index 5cab16f4695..b601be6a209 100644 --- a/libs/xml2/xmlIO.c +++ b/libs/xml2/xmlIO.c @@ -50,10 +50,10 @@ # endif #endif
+#include <libxml/xmlIO.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> #include <libxml/parserInternals.h> -#include <libxml/xmlIO.h> #include <libxml/uri.h> #include <libxml/nanohttp.h> #include <libxml/nanoftp.h> @@ -61,7 +61,6 @@ #ifdef LIBXML_CATALOG_ENABLED #include <libxml/catalog.h> #endif -#include <libxml/globals.h>
#include "private/buf.h" #include "private/enc.h" @@ -70,14 +69,8 @@ #include "private/parser.h"
/* #define VERBOSE_FAILURE */ -/* #define DEBUG_EXTERNAL_ENTITIES */ -/* #define DEBUG_INPUT */
-#ifdef DEBUG_INPUT -#define MINLEN 40 -#else #define MINLEN 4000 -#endif
/* * Input I/O callback sets @@ -211,6 +204,7 @@ __xmlIOWin32UTF8ToWChar(const char *u8String) } #endif
+#if defined(LIBXML_HTTP_ENABLED) && defined(LIBXML_OUTPUT_ENABLED) /** * xmlIOErrMemory: * @extra: extra information @@ -222,6 +216,7 @@ xmlIOErrMemory(const char *extra) { __xmlSimpleError(XML_FROM_IO, XML_ERR_NO_MEMORY, NULL, NULL, extra); } +#endif
/** * __xmlIOErr: @@ -1447,23 +1442,11 @@ append_reverse_ulong( xmlZMemBuff * buff, unsigned long data ) { static void xmlFreeZMemBuff( xmlZMemBuffPtr buff ) {
-#ifdef DEBUG_HTTP - int z_err; -#endif - if ( buff == NULL ) return;
xmlFree( buff->zbuff ); -#ifdef DEBUG_HTTP - z_err = deflateEnd( &buff->zctrl ); - if ( z_err != Z_OK ) - xmlGenericError( xmlGenericErrorContext, - "xmlFreeZMemBuff: Error releasing zlib context: %d\n", - z_err ); -#else deflateEnd( &buff->zctrl ); -#endif
xmlFree( buff ); return; @@ -1561,15 +1544,6 @@ xmlZMemBuffExtend( xmlZMemBuffPtr buff, size_t ext_amt ) { cur_used = buff->zctrl.next_out - buff->zbuff; new_size = buff->size + ext_amt;
-#ifdef DEBUG_HTTP - if ( cur_used > new_size ) - xmlGenericError( xmlGenericErrorContext, - "xmlZMemBuffExtend: %s\n%s %d bytes.\n", - "Buffer overwrite detected during compressed memory", - "buffer extension. Overflowed by", - (cur_used - new_size ) ); -#endif - tmp_ptr = xmlRealloc( buff->zbuff, new_size ); if ( tmp_ptr != NULL ) { rc = 0; @@ -1990,57 +1964,6 @@ xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) { content_lgth );
if ( http_ctxt != NULL ) { -#ifdef DEBUG_HTTP - /* If testing/debugging - dump reply with request content */ - - FILE * tst_file = NULL; - char buffer[ 4096 ]; - char * dump_name = NULL; - int avail; - - xmlGenericError( xmlGenericErrorContext, - "xmlNanoHTTPCloseWrite: HTTP %s to\n%s returned %d.\n", - http_mthd, ctxt->uri, - xmlNanoHTTPReturnCode( http_ctxt ) ); - - /* - ** Since either content or reply may be gzipped, - ** dump them to separate files instead of the - ** standard error context. - */ - - dump_name = tempnam( NULL, "lxml" ); - if ( dump_name != NULL ) { - (void)snprintf( buffer, sizeof(buffer), "%s.content", dump_name ); - - tst_file = fopen( buffer, "wb" ); - if ( tst_file != NULL ) { - xmlGenericError( xmlGenericErrorContext, - "Transmitted content saved in file: %s\n", buffer ); - - fwrite( http_content, 1, content_lgth, tst_file ); - fclose( tst_file ); - } - - (void)snprintf( buffer, sizeof(buffer), "%s.reply", dump_name ); - tst_file = fopen( buffer, "wb" ); - if ( tst_file != NULL ) { - xmlGenericError( xmlGenericErrorContext, - "Reply content saved in file: %s\n", buffer ); - - - while ( (avail = xmlNanoHTTPRead( http_ctxt, - buffer, sizeof( buffer ) )) > 0 ) { - - fwrite( buffer, 1, avail, tst_file ); - } - - fclose( tst_file ); - } - - free( dump_name ); - } -#endif /* DEBUG_HTTP */
http_rtn = xmlNanoHTTPReturnCode( http_ctxt ); if ( ( http_rtn >= 200 ) && ( http_rtn < 300 ) ) @@ -2325,7 +2248,6 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
ret = (xmlParserInputBufferPtr) xmlMalloc(sizeof(xmlParserInputBuffer)); if (ret == NULL) { - xmlIOErrMemory("creating input buffer"); return(NULL); } memset(ret, 0, sizeof(xmlParserInputBuffer)); @@ -2364,7 +2286,6 @@ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); if (ret == NULL) { - xmlIOErrMemory("creating output buffer"); return(NULL); } memset(ret, 0, sizeof(xmlOutputBuffer)); @@ -2412,7 +2333,6 @@ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); if (ret == NULL) { - xmlIOErrMemory("creating output buffer"); return(NULL); } memset(ret, 0, sizeof(xmlOutputBuffer)); @@ -2910,38 +2830,78 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) { return(ret); }
+typedef struct { + char *mem; + const char *cur; + size_t size; +} xmlMemIOCtxt; + +static int +xmlMemRead(void *vctxt, char *buf, int size) { + xmlMemIOCtxt *ctxt = vctxt; + + if ((size_t) size > ctxt->size) + size = ctxt->size; + + memcpy(buf, ctxt->cur, size); + ctxt->cur += size; + ctxt->size -= size; + + return size; +} + +static int +xmlMemClose(void *vctxt) { + xmlMemIOCtxt *ctxt = vctxt; + + if (ctxt->mem != 0) + xmlFree(ctxt->mem); + xmlFree(ctxt); + return(0); +} + /** * xmlParserInputBufferCreateMem: * @mem: the memory input * @size: the length of the memory block * @enc: the charset encoding if known * - * Create a buffered parser input for the progressive parsing for the input - * from a memory area. + * Create a parser input buffer for parsing from a memory area. * - * Returns the new parser input or NULL + * This function makes a copy of the whole input buffer. If you are sure + * that the contents of the buffer will remain valid until the document + * was parsed, you can avoid the copy by using + * xmlParserInputBufferCreateStatic. + * + * 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 in case of error. */ xmlParserInputBufferPtr xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { - xmlParserInputBufferPtr ret; - int errcode; + xmlParserInputBufferPtr buf; + xmlMemIOCtxt *ctxt; + char *copy;
- if (size < 0) return(NULL); - if (mem == NULL) return(NULL); + if ((size < 0) || (mem == NULL)) + return(NULL);
- ret = xmlAllocParserInputBuffer(enc); - if (ret != NULL) { - ret->context = (void *) mem; - ret->readcallback = NULL; - ret->closecallback = NULL; - errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size); - if (errcode != 0) { - xmlFreeParserInputBuffer(ret); - return(NULL); - } + copy = (char *) xmlStrndup((const xmlChar *) mem, size); + if (copy == NULL) + return(NULL); + + buf = xmlParserInputBufferCreateStatic(copy, size, enc); + if (buf == NULL) { + xmlFree(copy); + return(NULL); }
- return(ret); + ctxt = buf->context; + ctxt->mem = copy; + + return(buf); }
/** @@ -2950,14 +2910,104 @@ xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { * @size: the length of the memory block * @enc: the charset encoding if known * - * DEPRECATED: Use xmlParserInputBufferCreateMem. + * Create a parser input buffer for parsing from a memory area. * - * Returns the new parser input or NULL + * This functions assumes that the contents of the input buffer remain + * valid until the document was parsed. Use xmlParserInputBufferCreateMem + * otherwise. + * + * 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 in case of error. */ xmlParserInputBufferPtr xmlParserInputBufferCreateStatic(const char *mem, int size, xmlCharEncoding enc) { - return(xmlParserInputBufferCreateMem(mem, size, enc)); + xmlParserInputBufferPtr ret; + xmlMemIOCtxt *ctxt; + + if ((size < 0) || (mem == NULL)) + return(NULL); + + ret = xmlAllocParserInputBuffer(enc); + if (ret == NULL) + return(NULL); + + ctxt = xmlMalloc(sizeof(*ctxt)); + if (ctxt == NULL) { + xmlFreeParserInputBuffer(ret); + return(NULL); + } + ctxt->mem = NULL; + ctxt->cur = mem; + ctxt->size = size; + + ret->context = ctxt; + ret->readcallback = xmlMemRead; + ret->closecallback = xmlMemClose; + + return(ret); +} + +typedef struct { + const xmlChar *str; +} xmlStringIOCtxt; + +static int +xmlStringRead(void *vctxt, char *buf, int size) { + xmlStringIOCtxt *ctxt = vctxt; + const xmlChar *zero; + size_t len; + + zero = memchr(ctxt->str, 0, size); + len = zero ? zero - ctxt->str : size; + + memcpy(buf, ctxt->str, len); + ctxt->str += len; + + return(len); +} + +static int +xmlStringClose(void *vctxt) { + xmlFree(vctxt); + return(0); +} + +/** + * xmlParserInputBufferCreateString: + * @str: a null-terminated string + * + * Create a buffered parser input for the progressive parsing for the input + * from a null-terminated C string. + * + * Returns the new parser input or NULL + */ +xmlParserInputBufferPtr +xmlParserInputBufferCreateString(const xmlChar *str) { + xmlParserInputBufferPtr ret; + xmlStringIOCtxt *ctxt; + + if (str == NULL) return(NULL); + + ret = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); + if (ret == NULL) + return(NULL); + + ctxt = xmlMalloc(sizeof(*ctxt)); + if (ctxt == NULL) { + xmlFreeParserInputBuffer(ret); + return(NULL); + } + ctxt->str = str; + + ret->context = ctxt; + ret->readcallback = xmlStringRead; + ret->closecallback = xmlStringClose; + + return(ret); }
#ifdef LIBXML_OUTPUT_ENABLED @@ -3112,45 +3162,36 @@ xmlParserInputBufferPush(xmlParserInputBufferPtr in, if (len < 0) return(0); if ((in == NULL) || (in->error)) return(-1); if (in->encoder != NULL) { - size_t use, consumed; - /* * Store the data in the incoming raw buffer */ if (in->raw == NULL) { in->raw = xmlBufCreate(); + if (in->raw == NULL) { + in->error = XML_ERR_NO_MEMORY; + return(-1); + } } ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len); - if (ret != 0) + if (ret != 0) { + in->error = XML_ERR_NO_MEMORY; return(-1); + }
/* * convert as much as possible to the parser reading buffer. */ - use = xmlBufUse(in->raw); - nbchars = xmlCharEncInput(in, 1); - if (nbchars < 0) { - xmlIOErr(XML_IO_ENCODER, NULL); - in->error = XML_IO_ENCODER; + nbchars = xmlCharEncInput(in); + if (nbchars < 0) return(-1); - } - consumed = use - xmlBufUse(in->raw); - if ((consumed > ULONG_MAX) || - (in->rawconsumed > ULONG_MAX - (unsigned long)consumed)) - in->rawconsumed = ULONG_MAX; - else - in->rawconsumed += consumed; } else { nbchars = len; ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars); - if (ret != 0) + if (ret != 0) { + in->error = XML_ERR_NO_MEMORY; return(-1); + } } -#ifdef DEBUG_INPUT - xmlGenericError(xmlGenericErrorContext, - "I/O: pushed %d chars, buffer %d/%d\n", - nbchars, xmlBufUse(in->buffer), xmlBufLength(in->buffer)); -#endif return(nbchars); }
@@ -3207,7 +3248,6 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) { */ if (in->readcallback != NULL) { if (xmlBufGrow(buf, len + 1) < 0) { - xmlIOErrMemory("growing input buffer"); in->error = XML_ERR_NO_MEMORY; return(-1); } @@ -3215,11 +3255,15 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) { res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len); if (res <= 0) in->readcallback = endOfInput; - if (res < 0) + if (res < 0) { + in->error = XML_IO_UNKNOWN; return(-1); + }
- if (xmlBufAddLen(buf, res) < 0) + if (xmlBufAddLen(buf, res) < 0) { + in->error = XML_ERR_NO_MEMORY; return(-1); + } }
/* @@ -3233,30 +3277,10 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) { }
if (in->encoder != NULL) { - size_t use, consumed; - - /* - * convert as much as possible to the parser reading buffer. - */ - use = xmlBufUse(buf); - res = xmlCharEncInput(in, 1); - if (res < 0) { - xmlIOErr(XML_IO_ENCODER, NULL); - in->error = XML_IO_ENCODER; + res = xmlCharEncInput(in); + if (res < 0) return(-1); - } - consumed = use - xmlBufUse(buf); - if ((consumed > ULONG_MAX) || - (in->rawconsumed > ULONG_MAX - (unsigned long)consumed)) - in->rawconsumed = ULONG_MAX; - else - in->rawconsumed += consumed; - } -#ifdef DEBUG_INPUT - xmlGenericError(xmlGenericErrorContext, - "I/O: read %d chars, buffer %d\n", - nbchars, xmlBufUse(in->buffer)); -#endif + } return(res); }
@@ -3382,10 +3406,6 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) { } while (len > 0);
done: -#ifdef DEBUG_INPUT - xmlGenericError(xmlGenericErrorContext, - "I/O: wrote %d chars\n", written); -#endif return(written); }
@@ -3582,10 +3602,6 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str, } while ((len > 0) && (oldwritten != written));
done: -#ifdef DEBUG_INPUT - xmlGenericError(xmlGenericErrorContext, - "I/O: wrote %d chars\n", written); -#endif return(written); }
@@ -3673,10 +3689,6 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) { else out->written += ret;
-#ifdef DEBUG_INPUT - xmlGenericError(xmlGenericErrorContext, - "I/O: flushed %d chars\n", ret); -#endif return(ret); } #endif /* LIBXML_OUTPUT_ENABLED */ @@ -3786,8 +3798,6 @@ xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { "Unknown encoding %s", BAD_CAST encoding, NULL); } - if (ret->encoding == NULL) - ret->encoding = xmlStrdup(BAD_CAST encoding); } #if 0 } else if (xmlStrstr(BAD_CAST mime, BAD_CAST "html")) { @@ -3929,10 +3939,6 @@ xmlDefaultExternalEntityLoader(const char *URL, const char *ID, xmlParserInputPtr ret = NULL; xmlChar *resource = NULL;
-#ifdef DEBUG_EXTERNAL_ENTITIES - xmlGenericError(xmlGenericErrorContext, - "xmlDefaultExternalEntityLoader(%s, xxx)\n", URL); -#endif if ((ctxt != NULL) && (ctxt->options & XML_PARSE_NONET)) { int options = ctxt->options;
@@ -4006,7 +4012,7 @@ xmlLoadExternalEntity(const char *URL, const char *ID,
canonicFilename = (char *) xmlCanonicPath((const xmlChar *) URL); if (canonicFilename == NULL) { - xmlIOErrMemory("building canonical path\n"); + xmlErrMemory(ctxt, "building canonical path\n"); return(NULL); }
@@ -4061,4 +4067,3 @@ xmlNoNetExternalEntityLoader(const char *URL, const char *ID, xmlFree(resource); return(input); } - diff --git a/libs/xml2/xmlmemory.c b/libs/xml2/xmlmemory.c index 9ec4770b157..d8cb18aaa6a 100644 --- a/libs/xml2/xmlmemory.c +++ b/libs/xml2/xmlmemory.c @@ -12,8 +12,6 @@ #include <ctype.h> #include <time.h>
-/* #define DEBUG_MEMORY */ - /** * MEM_LIST: * @@ -26,9 +24,9 @@ #endif #endif
-#include <libxml/globals.h> /* must come before xmlmemory.h */ #include <libxml/xmlmemory.h> #include <libxml/xmlerror.h> +#include <libxml/parser.h> #include <libxml/threads.h>
#include "private/memory.h" @@ -150,17 +148,12 @@ xmlMallocLoc(size_t size, const char * file, int line) void *ret;
xmlInitParser(); -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d)\n",size); -#endif
TEST_POINT
if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Unsigned overflow\n"); - xmlMemoryDump(); return(NULL); }
@@ -169,7 +162,6 @@ xmlMallocLoc(size_t size, const char * file, int line) if (!p) { xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Out of free space\n"); - xmlMemoryDump(); return(NULL); } p->mh_tag = MEMTAG; @@ -187,11 +179,6 @@ xmlMallocLoc(size_t size, const char * file, int line) #endif xmlMutexUnlock(&xmlMemMutex);
-#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d) Ok\n",size); -#endif - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
ret = HDR_2_CLIENT(p); @@ -226,17 +213,12 @@ xmlMallocAtomicLoc(size_t size, const char * file, int line) void *ret;
xmlInitParser(); -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d)\n",size); -#endif
TEST_POINT
if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlMallocAtomicLoc : Unsigned overflow\n"); - xmlMemoryDump(); return(NULL); }
@@ -245,7 +227,6 @@ xmlMallocAtomicLoc(size_t size, const char * file, int line) if (!p) { xmlGenericError(xmlGenericErrorContext, "xmlMallocAtomicLoc : Out of free space\n"); - xmlMemoryDump(); return(NULL); } p->mh_tag = MEMTAG; @@ -263,11 +244,6 @@ xmlMallocAtomicLoc(size_t size, const char * file, int line) #endif xmlMutexUnlock(&xmlMemMutex);
-#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d) Ok\n",size); -#endif - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
ret = HDR_2_CLIENT(p); @@ -315,9 +291,6 @@ xmlReallocLoc(void *ptr,size_t size, const char * file, int line) { MEMHDR *p, *tmp; unsigned long number; -#ifdef DEBUG_MEMORY - size_t oldsize; -#endif
if (ptr == NULL) return(xmlMallocLoc(size, file, line)); @@ -336,9 +309,6 @@ xmlReallocLoc(void *ptr,size_t size, const char * file, int line) xmlMutexLock(&xmlMemMutex); debugMemSize -= p->mh_size; debugMemBlocks--; -#ifdef DEBUG_MEMORY - oldsize = p->mh_size; -#endif #ifdef MEM_LIST debugmem_list_delete(p); #endif @@ -347,7 +317,6 @@ xmlReallocLoc(void *ptr,size_t size, const char * file, int line) if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlReallocLoc : Unsigned overflow\n"); - xmlMemoryDump(); return(NULL); }
@@ -381,10 +350,6 @@ xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
TEST_POINT
-#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Realloced(%d to %d) Ok\n", oldsize, size); -#endif return(HDR_2_CLIENT(p));
error: @@ -417,9 +382,6 @@ xmlMemFree(void *ptr) { MEMHDR *p; char *target; -#ifdef DEBUG_MEMORY - size_t size; -#endif
if (ptr == NULL) return; @@ -451,9 +413,6 @@ xmlMemFree(void *ptr) xmlMutexLock(&xmlMemMutex); debugMemSize -= p->mh_size; debugMemBlocks--; -#ifdef DEBUG_MEMORY - size = p->mh_size; -#endif #ifdef MEM_LIST debugmem_list_delete(p); #endif @@ -463,11 +422,6 @@ xmlMemFree(void *ptr)
TEST_POINT
-#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Freed(%d) Ok\n", size); -#endif - return;
error: @@ -501,7 +455,6 @@ xmlMemStrdupLoc(const char *str, const char *file, int line) if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlMemStrdupLoc : Unsigned overflow\n"); - xmlMemoryDump(); return(NULL); }
@@ -759,10 +712,6 @@ static void debugmem_list_add(MEMHDR *p) p->mh_prev = NULL; if (memlist) memlist->mh_prev = p; memlist = p; -#ifdef MEM_LIST_DEBUG - if (stderr) - Mem_Display(stderr); -#endif }
static void debugmem_list_delete(MEMHDR *p) @@ -772,10 +721,6 @@ static void debugmem_list_delete(MEMHDR *p) if (p->mh_prev) p->mh_prev->mh_next = p->mh_next; else memlist = p->mh_next; -#ifdef MEM_LIST_DEBUG - if (stderr) - Mem_Display(stderr); -#endif }
#endif @@ -900,10 +845,6 @@ xmlInitMemory(void) { void xmlInitMemoryInternal(void) { char *breakpoint; -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlInitMemory()\n"); -#endif xmlInitMutex(&xmlMemMutex);
breakpoint = getenv("XML_MEM_BREAKPOINT"); @@ -915,10 +856,6 @@ xmlInitMemoryInternal(void) { sscanf(breakpoint, "%p", &xmlMemTraceBlockAt); }
-#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlInitMemory() Ok\n"); -#endif }
/** @@ -941,15 +878,15 @@ xmlCleanupMemory(void) { */ void xmlCleanupMemoryInternal(void) { -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlCleanupMemory()\n"); -#endif - + /* + * Don't clean up mutex on Windows. Global state destructors can call + * malloc functions after xmlCleanupParser was called. If memory + * debugging is enabled, xmlMemMutex can be used after cleanup. + * + * See python/tests/thread2.py + */ +#if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32) xmlCleanupMutex(&xmlMemMutex); -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlCleanupMemory() Ok\n"); #endif }
@@ -971,10 +908,6 @@ xmlCleanupMemoryInternal(void) { int xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) { -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlMemSetup()\n"); -#endif if (freeFunc == NULL) return(-1); if (mallocFunc == NULL) @@ -988,10 +921,6 @@ xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, xmlMallocAtomic = mallocFunc; xmlRealloc = reallocFunc; xmlMemStrdup = strdupFunc; -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlMemSetup() Ok\n"); -#endif return(0); }
@@ -1038,10 +967,6 @@ int xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) { -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlGcMemSetup()\n"); -#endif if (freeFunc == NULL) return(-1); if (mallocFunc == NULL) @@ -1057,10 +982,6 @@ xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, xmlMallocAtomic = mallocAtomicFunc; xmlRealloc = reallocFunc; xmlMemStrdup = strdupFunc; -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlGcMemSetup() Ok\n"); -#endif return(0); }
@@ -1089,4 +1010,3 @@ xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup; return(0); } - diff --git a/libs/xml2/xmlreader.c b/libs/xml2/xmlreader.c index 172d1d7ce0b..1d954f21310 100644 --- a/libs/xml2/xmlreader.c +++ b/libs/xml2/xmlreader.c @@ -40,6 +40,7 @@ #endif
#include "private/buf.h" +#include "private/parser.h" #include "private/tree.h" #ifdef LIBXML_XINCLUDE_ENABLED #include "private/xinclude.h" @@ -77,9 +78,6 @@ #endif #endif
-/* #define DEBUG_CALLBACKS */ -/* #define DEBUG_READER */ - /** * TODO: * @@ -90,12 +88,6 @@ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);
-#ifdef DEBUG_READER -#define DUMP_READER xmlTextReaderDebug(reader); -#else -#define DUMP_READER -#endif - #define CHUNK_SIZE 512 /************************************************************************ * * @@ -505,33 +497,6 @@ xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) { * The reader core parser * * * ************************************************************************/ -#ifdef DEBUG_READER -static void -xmlTextReaderDebug(xmlTextReaderPtr reader) { - if ((reader == NULL) || (reader->ctxt == NULL)) { - fprintf(stderr, "xmlTextReader NULL\n"); - return; - } - fprintf(stderr, "xmlTextReader: state %d depth %d ", - reader->state, reader->depth); - if (reader->node == NULL) { - fprintf(stderr, "node = NULL\n"); - } else { - fprintf(stderr, "node %s\n", reader->node->name); - } - fprintf(stderr, " input: base %d, cur %d, depth %d: ", - reader->base, reader->cur, reader->ctxt->nodeNr); - if (reader->input->buffer == NULL) { - fprintf(stderr, "buffer is NULL\n"); - } else { -#ifdef LIBXML_DEBUG_ENABLED - xmlDebugDumpString(stderr, - &reader->input->buffer->content[reader->cur]); -#endif - fprintf(stderr, "\n"); - } -} -#endif
/** * xmlTextReaderEntPush: @@ -602,9 +567,6 @@ xmlTextReaderStartElement(void *ctx, const xmlChar *fullname, xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
-#ifdef DEBUG_CALLBACKS - printf("xmlTextReaderStartElement(%s)\n", fullname); -#endif if ((reader != NULL) && (reader->startElement != NULL)) { reader->startElement(ctx, fullname, atts); if ((ctxt->node != NULL) && (ctxt->input != NULL) && @@ -628,9 +590,6 @@ xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
-#ifdef DEBUG_CALLBACKS - printf("xmlTextReaderEndElement(%s)\n", fullname); -#endif if ((reader != NULL) && (reader->endElement != NULL)) { reader->endElement(ctx, fullname); } @@ -665,9 +624,6 @@ xmlTextReaderStartElementNs(void *ctx, xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
-#ifdef DEBUG_CALLBACKS - printf("xmlTextReaderStartElementNs(%s)\n", localname); -#endif if ((reader != NULL) && (reader->startElementNs != NULL)) { reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces, namespaces, nb_attributes, nb_defaulted, @@ -699,9 +655,6 @@ xmlTextReaderEndElementNs(void *ctx, xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
-#ifdef DEBUG_CALLBACKS - printf("xmlTextReaderEndElementNs(%s)\n", localname); -#endif if ((reader != NULL) && (reader->endElementNs != NULL)) { reader->endElementNs(ctx, localname, prefix, URI); } @@ -722,9 +675,6 @@ xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len) xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
-#ifdef DEBUG_CALLBACKS - printf("xmlTextReaderCharacters()\n"); -#endif if ((reader != NULL) && (reader->characters != NULL)) { reader->characters(ctx, ch, len); } @@ -744,9 +694,6 @@ xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len) xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlTextReaderPtr reader = ctxt->_private;
-#ifdef DEBUG_CALLBACKS - printf("xmlTextReaderCDataBlock()\n"); -#endif if ((reader != NULL) && (reader->cdataBlock != NULL)) { reader->cdataBlock(ctx, ch, len); } @@ -781,22 +728,17 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { */ if (reader->mode != XML_TEXTREADER_MODE_EOF) { val = xmlParserInputBufferRead(reader->input, 4096); - if ((val == 0) && - (reader->input->readcallback == NULL)) { + if (val == 0) { if (xmlBufUse(inbuf) == reader->cur) { reader->mode = XML_TEXTREADER_MODE_EOF; - reader->state = oldstate; + break; } } else if (val < 0) { + xmlGenericError(xmlGenericErrorContext, + "xmlParserInputBufferRead failed\n"); reader->mode = XML_TEXTREADER_MODE_EOF; reader->state = oldstate; - if ((oldstate != XML_TEXTREADER_START) || - (reader->ctxt->myDoc != NULL)) - return(val); - } else if (val == 0) { - /* mark the end of the stream and process the remains */ - reader->mode = XML_TEXTREADER_MODE_EOF; - break; + return(val); }
} else @@ -826,6 +768,7 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { break; } } + reader->state = oldstate;
/* * Discard the consumed input when needed and possible @@ -862,7 +805,6 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { } } } - reader->state = oldstate; if (reader->ctxt->wellFormed == 0) { reader->mode = XML_TEXTREADER_MODE_EOF; return(-1); @@ -1230,10 +1172,6 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { if (reader->ctxt == NULL) return(-1);
-#ifdef DEBUG_READER - fprintf(stderr, "\nREAD "); - DUMP_READER -#endif if (reader->mode == XML_TEXTREADER_MODE_INITIAL) { reader->mode = XML_TEXTREADER_MODE_INTERACTIVE; /* @@ -1425,8 +1363,6 @@ get_next_node: reader->state = XML_TEXTREADER_BACKTRACK;
node_found: - DUMP_READER - /* * If we are in the middle of a piece of CDATA make sure it's finished */ @@ -2860,20 +2796,17 @@ xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) { */ const xmlChar * xmlTextReaderConstEncoding(xmlTextReaderPtr reader) { - xmlDocPtr doc = NULL; + const xmlChar *encoding = NULL; + if (reader == NULL) - return(NULL); - if (reader->doc != NULL) - doc = reader->doc; - else if (reader->ctxt != NULL) - doc = reader->ctxt->myDoc; - if (doc == NULL) - return(NULL); + return(NULL);
- if (doc->encoding == NULL) - return(NULL); - else - return(CONSTSTR(doc->encoding)); + if (reader->ctxt != NULL) + encoding = xmlGetActualEncoding(reader->ctxt); + else if (reader->doc != NULL) + encoding = reader->doc->encoding; + + return(CONSTSTR(encoding)); }
@@ -4039,10 +3972,10 @@ xmlTextReaderValidityWarningRelay(void *ctx, const char *msg, ...) }
static void - xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error); +xmlTextReaderStructuredError(void *ctxt, const xmlError *error);
static void -xmlTextReaderValidityStructuredRelay(void *userData, xmlErrorPtr error) +xmlTextReaderValidityStructuredRelay(void *userData, const xmlError *error) { xmlTextReaderPtr reader = (xmlTextReaderPtr) userData;
@@ -4773,7 +4706,7 @@ xmlTextReaderGenericError(void *ctxt, xmlParserSeverities severity, }
static void -xmlTextReaderStructuredError(void *ctxt, xmlErrorPtr error) +xmlTextReaderStructuredError(void *ctxt, const xmlError *error) { xmlParserCtxtPtr ctx = (xmlParserCtxtPtr) ctxt;
@@ -5236,6 +5169,19 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, return (0); }
+/** + * xmlTextReaderSetMaxAmplification: + * @reader: an XML reader + * @maxAmpl: maximum amplification factor + * + * Set the maximum amplification factor. See xmlCtxtSetMaxAmplification. + */ +void +xmlTextReaderSetMaxAmplification(xmlTextReaderPtr reader, unsigned maxAmpl) +{ + xmlCtxtSetMaxAmplification(reader->ctxt, maxAmpl); +} + /** * xmlTextReaderByteConsumed: * @reader: an XML reader diff --git a/libs/xml2/xmlregexp.c b/libs/xml2/xmlregexp.c index 5638ddc62e8..f434a0cf986 100644 --- a/libs/xml2/xmlregexp.c +++ b/libs/xml2/xmlregexp.c @@ -19,8 +19,6 @@
#ifdef LIBXML_REGEXP_ENABLED
-/* #define DEBUG_ERR */ - #include <stdio.h> #include <string.h> #include <limits.h> @@ -38,13 +36,18 @@ #define SIZE_MAX ((size_t) -1) #endif
-/* #define DEBUG_REGEXP_GRAPH */ -/* #define DEBUG_REGEXP_EXEC */ -/* #define DEBUG_PUSH */ -/* #define DEBUG_COMPACTION */ - #define MAX_PUSH 10000000
+/* + * -2 and -3 are used by xmlValidateElementType for other things. + */ +#define XML_REGEXP_OK 0 +#define XML_REGEXP_NOT_FOUND (-1) +#define XML_REGEXP_INTERNAL_ERROR (-4) +#define XML_REGEXP_OUT_OF_MEMORY (-5) +#define XML_REGEXP_INTERNAL_LIMIT (-6) +#define XML_REGEXP_INVALID_UTF8 (-7) + #ifdef ERROR #undef ERROR #endif @@ -55,7 +58,6 @@ #define CUR (*(ctxt->cur)) #define NXT(index) (ctxt->cur[index])
-#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l) #define NEXTL(l) ctxt->cur += l; #define XML_REG_STRING_SEPARATOR '|' /* @@ -474,7 +476,11 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { ret->determinist = ctxt->determinist; ret->flags = ctxt->flags; if (ret->determinist == -1) { - xmlRegexpIsDeterminist(ret); + if (xmlRegexpIsDeterminist(ret) < 0) { + xmlRegexpErrMemory(ctxt, "checking determinism"); + xmlFree(ret); + return(NULL); + } }
if ((ret->determinist != 0) && @@ -513,9 +519,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { stateRemap[i] = -1; } } -#ifdef DEBUG_COMPACTION - printf("Final: %d states\n", nbstates); -#endif stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *)); if (stringMap == NULL) { xmlRegexpErrMemory(ctxt, "compiling regexp"); @@ -565,9 +568,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { return(NULL); } } -#ifdef DEBUG_COMPACTION - printf("Final: %d atoms\n", nbatoms); -#endif transitions = (int *) xmlRegCalloc2(nbstates + 1, nbatoms + 1, sizeof(int)); if (transitions == NULL) { @@ -600,7 +600,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
for (j = 0;j < state->nbTrans;j++) { trans = &(state->trans[j]); - if ((trans->to == -1) || (trans->atom == NULL)) + if ((trans->to < 0) || (trans->atom == NULL)) continue; atomno = stringRemap[trans->atom->no]; if ((trans->atom->data != NULL) && (transdata == NULL)) { @@ -621,11 +621,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { if (prev != 0) { if (prev != targetno + 1) { ret->determinist = 0; -#ifdef DEBUG_COMPACTION - printf("Indet: state %d trans %d, atom %d to %d : %d to %d\n", - i, j, trans->atom->no, trans->to, atomno, targetno); - printf(" previous to is %d\n", prev); -#endif if (transdata != NULL) xmlFree(transdata); xmlFree(transitions); @@ -650,18 +645,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) { } } ret->determinist = 1; -#ifdef DEBUG_COMPACTION - /* - * Debug - */ - for (i = 0;i < nbstates;i++) { - for (j = 0;j < nbatoms + 1;j++) { - printf("%02d ", transitions[i * (nbatoms + 1) + j]); - } - printf("\n"); - } - printf("\n"); -#endif /* * Cleanup of the old data */ @@ -1191,48 +1174,6 @@ xmlRegPrintState(FILE *output, xmlRegStatePtr state) { } }
-#ifdef DEBUG_REGEXP_GRAPH -static void -xmlRegPrintCtxt(FILE *output, xmlRegParserCtxtPtr ctxt) { - int i; - - fprintf(output, " ctxt: "); - if (ctxt == NULL) { - fprintf(output, "NULL\n"); - return; - } - fprintf(output, "'%s' ", ctxt->string); - if (ctxt->error) - fprintf(output, "error "); - if (ctxt->neg) - fprintf(output, "neg "); - fprintf(output, "\n"); - fprintf(output, "%d atoms:\n", ctxt->nbAtoms); - for (i = 0;i < ctxt->nbAtoms; i++) { - fprintf(output, " %02d ", i); - xmlRegPrintAtom(output, ctxt->atoms[i]); - } - if (ctxt->atom != NULL) { - fprintf(output, "current atom:\n"); - xmlRegPrintAtom(output, ctxt->atom); - } - fprintf(output, "%d states:", ctxt->nbStates); - if (ctxt->start != NULL) - fprintf(output, " start: %d", ctxt->start->no); - if (ctxt->end != NULL) - fprintf(output, " end: %d", ctxt->end->no); - fprintf(output, "\n"); - for (i = 0;i < ctxt->nbStates; i++) { - xmlRegPrintState(output, ctxt->states[i]); - } - fprintf(output, "%d counters:\n", ctxt->nbCounters); - for (i = 0;i < ctxt->nbCounters; i++) { - fprintf(output, " %d: min %d max %d\n", i, ctxt->counters[i].min, - ctxt->counters[i].max); - } -} -#endif - /************************************************************************ * * * Finite Automata structures manipulations * @@ -1389,10 +1330,6 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, (trans->to == target->no) && (trans->counter == counter) && (trans->count == count)) { -#ifdef DEBUG_REGEXP_GRAPH - printf("Ignoring duplicate transition from %d to %d\n", - state->no, target->no); -#endif return; } } @@ -1418,19 +1355,6 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, } state->trans = tmp; } -#ifdef DEBUG_REGEXP_GRAPH - printf("Add trans from %d to %d ", state->no, target->no); - if (count == REGEXP_ALL_COUNTER) - printf("all transition\n"); - else if (count >= 0) - printf("count based %d\n", count); - else if (counter >= 0) - printf("counted %d\n", counter); - else if (atom == NULL) - printf("epsilon transition\n"); - else if (atom != NULL) - xmlRegPrintAtom(stdout, atom); -#endif
state->trans[state->nbTrans].atom = atom; state->trans[state->nbTrans].to = target->no; @@ -1800,9 +1724,6 @@ xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr, xmlRegStatePtr from; xmlRegStatePtr to;
-#ifdef DEBUG_REGEXP_GRAPH - printf("xmlFAReduceEpsilonTransitions(%d, %d)\n", fromnr, tonr); -#endif from = ctxt->states[fromnr]; if (from == NULL) return; @@ -1815,56 +1736,67 @@ xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr,
to->mark = XML_REGEXP_MARK_VISITED; if (to->type == XML_REGEXP_FINAL_STATE) { -#ifdef DEBUG_REGEXP_GRAPH - printf("State %d is final, so %d becomes final\n", tonr, fromnr); -#endif from->type = XML_REGEXP_FINAL_STATE; } for (transnr = 0;transnr < to->nbTrans;transnr++) { - if (to->trans[transnr].to < 0) + xmlRegTransPtr t1 = &to->trans[transnr]; + int tcounter; + + if (t1->to < 0) continue; - if (to->trans[transnr].atom == NULL) { + if (t1->counter >= 0) { + /* assert(counter < 0); */ + tcounter = t1->counter; + } else { + tcounter = counter; + } + if (t1->atom == NULL) { /* * Don't remove counted transitions * Don't loop either */ - if (to->trans[transnr].to != fromnr) { - if (to->trans[transnr].count >= 0) { - int newto = to->trans[transnr].to; - - xmlRegStateAddTrans(ctxt, from, NULL, - ctxt->states[newto], - -1, to->trans[transnr].count); + if (t1->to != fromnr) { + if (t1->count >= 0) { + xmlRegStateAddTrans(ctxt, from, NULL, ctxt->states[t1->to], + -1, t1->count); } else { -#ifdef DEBUG_REGEXP_GRAPH - printf("Found epsilon trans %d from %d to %d\n", - transnr, tonr, to->trans[transnr].to); -#endif - if (to->trans[transnr].counter >= 0) { - xmlFAReduceEpsilonTransitions(ctxt, fromnr, - to->trans[transnr].to, - to->trans[transnr].counter); - } else { - xmlFAReduceEpsilonTransitions(ctxt, fromnr, - to->trans[transnr].to, - counter); - } + xmlFAReduceEpsilonTransitions(ctxt, fromnr, t1->to, + tcounter); } } } else { - int newto = to->trans[transnr].to; - - if (to->trans[transnr].counter >= 0) { - xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, - ctxt->states[newto], - to->trans[transnr].counter, -1); - } else { - xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, - ctxt->states[newto], counter, -1); - } + xmlRegStateAddTrans(ctxt, from, t1->atom, + ctxt->states[t1->to], tcounter, -1); } } +} + +/** + * xmlFAFinishReduceEpsilonTransitions: + * @ctxt: a regexp parser context + * @fromnr: the from state + * @tonr: the to state + * @counter: should that transition be associated to a counted + * + */ +static void +xmlFAFinishReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int tonr) { + int transnr; + xmlRegStatePtr to; + + to = ctxt->states[tonr]; + if (to == NULL) + return; + if ((to->mark == XML_REGEXP_MARK_START) || + (to->mark == XML_REGEXP_MARK_NORMAL)) + return; + to->mark = XML_REGEXP_MARK_NORMAL; + for (transnr = 0;transnr < to->nbTrans;transnr++) { + xmlRegTransPtr t1 = &to->trans[transnr]; + if ((t1->to >= 0) && (t1->atom == NULL)) + xmlFAFinishReduceEpsilonTransitions(ctxt, t1->to); + } }
/** @@ -1911,23 +1843,11 @@ xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) { newto = state->trans[0].to;
if (state->type == XML_REGEXP_START_STATE) { -#ifdef DEBUG_REGEXP_GRAPH - printf("Found simple epsilon trans from start %d to %d\n", - statenr, newto); -#endif } else { -#ifdef DEBUG_REGEXP_GRAPH - printf("Found simple epsilon trans from %d to %d\n", - statenr, newto); -#endif for (i = 0;i < state->nbTransTo;i++) { tmp = ctxt->states[state->transTo[i]]; for (j = 0;j < tmp->nbTrans;j++) { if (tmp->trans[j].to == statenr) { -#ifdef DEBUG_REGEXP_GRAPH - printf("Changed transition %d on %d to go to %d\n", - j, tmp->no, newto); -#endif tmp->trans[j].to = -1; xmlRegStateAddTrans(ctxt, tmp, tmp->trans[j].atom, ctxt->states[newto], @@ -1969,9 +1889,6 @@ xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) { for (statenr = 0;statenr < ctxt->nbStates;statenr++) { state = ctxt->states[statenr]; if ((state != NULL) && (state->type == XML_REGEXP_UNREACH_STATE)) { -#ifdef DEBUG_REGEXP_GRAPH - printf("Removed unreachable state %d\n", statenr); -#endif xmlRegFreeState(state); ctxt->states[statenr] = NULL; } @@ -2000,28 +1917,16 @@ xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) { (state->trans[transnr].to >= 0)) { if (state->trans[transnr].to == statenr) { state->trans[transnr].to = -1; -#ifdef DEBUG_REGEXP_GRAPH - printf("Removed loopback epsilon trans %d on %d\n", - transnr, statenr); -#endif } else if (state->trans[transnr].count < 0) { int newto = state->trans[transnr].to;
-#ifdef DEBUG_REGEXP_GRAPH - printf("Found epsilon trans %d from %d to %d\n", - transnr, statenr, newto); -#endif has_epsilon = 1; state->trans[transnr].to = -2; state->mark = XML_REGEXP_MARK_START; xmlFAReduceEpsilonTransitions(ctxt, statenr, newto, state->trans[transnr].counter); + xmlFAFinishReduceEpsilonTransitions(ctxt, newto); state->mark = XML_REGEXP_MARK_NORMAL; -#ifdef DEBUG_REGEXP_GRAPH - } else { - printf("Found counted transition %d on %d\n", - transnr, statenr); -#endif } } } @@ -2095,9 +2000,6 @@ xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) { for (statenr = 0;statenr < ctxt->nbStates;statenr++) { state = ctxt->states[statenr]; if ((state != NULL) && (state->reached == XML_REGEXP_MARK_NORMAL)) { -#ifdef DEBUG_REGEXP_GRAPH - printf("Removed unreachable state %d\n", statenr); -#endif xmlRegFreeState(state); ctxt->states[statenr] = NULL; } @@ -2623,7 +2525,7 @@ not_determinist: */ static int xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, - int to, xmlRegAtomPtr atom) { + int fromnr, int tonr, xmlRegAtomPtr atom) { int ret = 1; int res; int transnr, nbTrans; @@ -2648,22 +2550,23 @@ xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, /* * check transitions conflicting with the one looked at */ + if ((t1->to < 0) || (t1->to == fromnr)) + continue; if (t1->atom == NULL) { - if (t1->to < 0) - continue; state->markd = XML_REGEXP_MARK_VISITED; res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], - to, atom); + fromnr, tonr, atom); if (res == 0) { ret = 0; /* t1->nd = 1; */ } continue; } - if (t1->to != to) - continue; if (xmlFACompareAtoms(t1->atom, atom, deep)) { - ret = 0; + /* Treat equal transitions as deterministic. */ + if ((t1->to != tonr) || + (!xmlFAEqualAtoms(t1->atom, atom, deep))) + ret = 0; /* mark the transition as non-deterministic */ t1->nd = 1; } @@ -2712,10 +2615,6 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { int ret = 1; int deep = 1;
-#ifdef DEBUG_REGEXP_GRAPH - printf("xmlFAComputesDeterminism\n"); - xmlRegPrintCtxt(stdout, ctxt); -#endif if (ctxt->determinist != -1) return(ctxt->determinist);
@@ -2741,11 +2640,11 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { /* t1->nd = 1; */ continue; } - if (t1->to == -1) /* eliminated */ + if (t1->to < 0) /* eliminated */ continue; for (i = 0;i < transnr;i++) { t2 = &(state->trans[i]); - if (t2->to == -1) /* eliminated */ + if (t2->to < 0) /* eliminated */ continue; if (t2->atom != NULL) { if (t1->to == t2->to) { @@ -2783,11 +2682,11 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { if (t1->atom == NULL) { continue; } - if (t1->to == -1) /* eliminated */ + if (t1->to < 0) /* eliminated */ continue; for (i = 0;i < transnr;i++) { t2 = &(state->trans[i]); - if (t2->to == -1) /* eliminated */ + if (t2->to < 0) /* eliminated */ continue; if (t2->atom != NULL) { /* @@ -2795,29 +2694,39 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { * find transitions which indicate a conflict */ if (xmlFACompareAtoms(t1->atom, t2->atom, 1)) { - ret = 0; + /* + * Treat equal counter transitions that couldn't be + * eliminated as deterministic. + */ + if ((t1->to != t2->to) || + (t1->counter == t2->counter) || + (!xmlFAEqualAtoms(t1->atom, t2->atom, deep))) + ret = 0; /* mark the transitions as non-deterministic ones */ t1->nd = 1; t2->nd = 1; last = t1; } - } else if (t1->to != -1) { + } else { + int res; + /* * do the closure in case of remaining specific * epsilon transitions like choices or all */ - ret = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], - t2->to, t2->atom); - xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t1->to]); + res = xmlFARecurseDeterminism(ctxt, ctxt->states[t2->to], + statenr, t1->to, t1->atom); + xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t2->to]); /* don't shortcut the computation so all non deterministic transition get marked down if (ret == 0) return(0); */ - if (ret == 0) { + if (res == 0) { t1->nd = 1; /* t2->nd = 1; */ last = t1; + ret = 0; } } } @@ -3136,33 +3045,11 @@ xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint) { * * ************************************************************************/
-#ifdef DEBUG_REGEXP_EXEC -static void -xmlFARegDebugExec(xmlRegExecCtxtPtr exec) { - printf("state: %d:%d:idx %d", exec->state->no, exec->transno, exec->index); - if (exec->inputStack != NULL) { - int i; - printf(": "); - for (i = 0;(i < 3) && (i < exec->inputStackNr);i++) - printf("%s ", (const char *) - exec->inputStack[exec->inputStackNr - (i + 1)].value); - } else { - printf(": %s", &(exec->inputString[exec->index])); - } - printf("\n"); -} -#endif - static void xmlFARegExecSave(xmlRegExecCtxtPtr exec) { -#ifdef DEBUG_REGEXP_EXEC - printf("saving "); - exec->transno++; - xmlFARegDebugExec(exec); - exec->transno--; -#endif #ifdef MAX_PUSH if (exec->nbPush > MAX_PUSH) { + exec->status = XML_REGEXP_INTERNAL_LIMIT; return; } exec->nbPush++; @@ -3175,6 +3062,7 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) { if (exec->rollbacks == NULL) { xmlRegexpErrMemory(NULL, "saving regexp"); exec->maxRollbacks = 0; + exec->status = XML_REGEXP_OUT_OF_MEMORY; return; } memset(exec->rollbacks, 0, @@ -3189,6 +3077,7 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) { if (tmp == NULL) { xmlRegexpErrMemory(NULL, "saving regexp"); exec->maxRollbacks /= 2; + exec->status = XML_REGEXP_OUT_OF_MEMORY; return; } exec->rollbacks = tmp; @@ -3204,7 +3093,7 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) { xmlMalloc(exec->comp->nbCounters * sizeof(int)); if (exec->rollbacks[exec->nbRollbacks].counts == NULL) { xmlRegexpErrMemory(NULL, "saving regexp"); - exec->status = -5; + exec->status = XML_REGEXP_OUT_OF_MEMORY; return; } } @@ -3216,11 +3105,10 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
static void xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) { + if (exec->status != XML_REGEXP_OK) + return; if (exec->nbRollbacks <= 0) { - exec->status = -1; -#ifdef DEBUG_REGEXP_EXEC - printf("rollback failed on empty stack\n"); -#endif + exec->status = XML_REGEXP_NOT_FOUND; return; } exec->nbRollbacks--; @@ -3230,7 +3118,7 @@ xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) { if (exec->comp->nbCounters > 0) { if (exec->rollbacks[exec->nbRollbacks].counts == NULL) { fprintf(stderr, "exec save: allocation failed"); - exec->status = -6; + exec->status = XML_REGEXP_INTERNAL_ERROR; return; } if (exec->counts) { @@ -3238,11 +3126,6 @@ xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) { exec->comp->nbCounters * sizeof(int)); } } - -#ifdef DEBUG_REGEXP_EXEC - printf("restored "); - xmlFARegDebugExec(exec); -#endif }
/************************************************************************ @@ -3264,7 +3147,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { exec->maxRollbacks = 0; exec->nbRollbacks = 0; exec->rollbacks = NULL; - exec->status = 0; + exec->status = XML_REGEXP_OK; exec->comp = comp; exec->state = comp->states[0]; exec->transno = 0; @@ -3275,12 +3158,12 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)); if (exec->counts == NULL) { xmlRegexpErrMemory(NULL, "running regexp"); - return(-1); + return(XML_REGEXP_OUT_OF_MEMORY); } memset(exec->counts, 0, comp->nbCounters * sizeof(int)); } else exec->counts = NULL; - while ((exec->status == 0) && (exec->state != NULL) && + while ((exec->status == XML_REGEXP_OK) && (exec->state != NULL) && ((exec->inputString[exec->index] != 0) || ((exec->state != NULL) && (exec->state->type != XML_REGEXP_FINAL_STATE)))) { @@ -3324,7 +3207,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { xmlRegCounterPtr counter;
if (exec->counts == NULL) { - exec->status = -1; + exec->status = XML_REGEXP_INTERNAL_ERROR; goto error; } /* @@ -3333,19 +3216,21 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
count = exec->counts[trans->count]; counter = &exec->comp->counters[trans->count]; -#ifdef DEBUG_REGEXP_EXEC - printf("testing count %d: val %d, min %d, max %d\n", - trans->count, count, counter->min, counter->max); -#endif ret = ((count >= counter->min) && (count <= counter->max)); if ((ret) && (counter->min != counter->max)) deter = 0; } else if (atom == NULL) { fprintf(stderr, "epsilon transition left at runtime\n"); - exec->status = -2; + exec->status = XML_REGEXP_INTERNAL_ERROR; break; } else if (exec->inputString[exec->index] != 0) { - codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len); + len = 4; + codepoint = xmlGetUTF8Char(&exec->inputString[exec->index], + &len); + if (codepoint < 0) { + exec->status = XML_REGEXP_INVALID_UTF8; + goto error; + } ret = xmlRegCheckCharacter(atom, codepoint); if ((ret == 1) && (atom->min >= 0) && (atom->max > 0)) { xmlRegStatePtr to = comp->states[trans->to]; @@ -3362,7 +3247,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { if ((exec->counts == NULL) || (exec->comp == NULL) || (exec->comp->counters == NULL)) { - exec->status = -1; + exec->status = XML_REGEXP_INTERNAL_ERROR; goto error; } counter = &exec->comp->counters[trans->counter]; @@ -3372,11 +3257,10 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { /* Save before incrementing */ if (exec->state->nbTrans > exec->transno + 1) { xmlFARegExecSave(exec); + if (exec->status != XML_REGEXP_OK) + goto error; } if (trans->counter >= 0) { -#ifdef DEBUG_REGEXP_EXEC - printf("Increasing count %d\n", trans->counter); -#endif exec->counts[trans->counter]++; } exec->transcount = 1; @@ -3405,11 +3289,18 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { exec->transno = -1; /* trick */ exec->state = to; xmlFARegExecSave(exec); + if (exec->status != XML_REGEXP_OK) + goto error; exec->transno = transno; exec->state = state; } - codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), - len); + len = 4; + codepoint = xmlGetUTF8Char( + &exec->inputString[exec->index], &len); + if (codepoint < 0) { + exec->status = XML_REGEXP_INVALID_UTF8; + goto error; + } ret = xmlRegCheckCharacter(atom, codepoint); exec->transcount++; } while (ret == 1); @@ -3427,12 +3318,9 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { } if (trans->counter >= 0) { if (exec->counts == NULL) { - exec->status = -1; + exec->status = XML_REGEXP_INTERNAL_ERROR; goto error; } -#ifdef DEBUG_REGEXP_EXEC - printf("Decreasing count %d\n", trans->counter); -#endif exec->counts[trans->counter]--; } } else if ((ret == 0) && (atom->min == 0) && (atom->max > 0)) { @@ -3455,15 +3343,9 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { if ((trans->nd == 1) || ((trans->count >= 0) && (deter == 0) && (exec->state->nbTrans > exec->transno + 1))) { -#ifdef DEBUG_REGEXP_EXEC - if (trans->nd == 1) - printf("Saving on nd transition atom %d for %c at %d\n", - trans->atom->no, codepoint, exec->index); - else - printf("Saving on counted transition count %d for %c at %d\n", - trans->count, codepoint, exec->index); -#endif xmlFARegExecSave(exec); + if (exec->status != XML_REGEXP_OK) + goto error; } if (trans->counter >= 0) { xmlRegCounterPtr counter; @@ -3472,32 +3354,22 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { if ((exec->counts == NULL) || (exec->comp == NULL) || (exec->comp->counters == NULL)) { - exec->status = -1; + exec->status = XML_REGEXP_INTERNAL_ERROR; goto error; } counter = &exec->comp->counters[trans->counter]; if (exec->counts[trans->counter] >= counter->max) continue; /* for loop on transitions */ -#ifdef DEBUG_REGEXP_EXEC - printf("Increasing count %d\n", trans->counter); -#endif exec->counts[trans->counter]++; } if ((trans->count >= 0) && (trans->count < REGEXP_ALL_COUNTER)) { if (exec->counts == NULL) { - exec->status = -1; + exec->status = XML_REGEXP_INTERNAL_ERROR; goto error; } -#ifdef DEBUG_REGEXP_EXEC - printf("resetting count %d on transition\n", - trans->count); -#endif exec->counts[trans->count] = 0; } -#ifdef DEBUG_REGEXP_EXEC - printf("entering state %d\n", trans->to); -#endif exec->state = comp->states[trans->to]; exec->transno = 0; if (trans->atom != NULL) { @@ -3505,7 +3377,7 @@ xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) { } goto progress; } else if (ret < 0) { - exec->status = -4; + exec->status = XML_REGEXP_INTERNAL_ERROR; break; } } @@ -3515,10 +3387,6 @@ rollback: * Failed to find a way out */ exec->determinist = 0; -#ifdef DEBUG_REGEXP_EXEC - printf("rollback from state %d on %d:%c\n", exec->state->no, - codepoint,codepoint); -#endif xmlFARegExecRollBack(exec); } progress: @@ -3536,16 +3404,13 @@ error: xmlFree(exec->rollbacks); } if (exec->state == NULL) - return(-1); + return(XML_REGEXP_INTERNAL_ERROR); if (exec->counts != NULL) xmlFree(exec->counts); - if (exec->status == 0) + if (exec->status == XML_REGEXP_OK) return(1); - if (exec->status == -1) { - if (exec->nbPush > MAX_PUSH) - return(-1); + if (exec->status == XML_REGEXP_NOT_FOUND) return(0); - } return(exec->status); }
@@ -3554,9 +3419,6 @@ error: * Progressive interface to the verifier one atom at a time * * * ************************************************************************/ -#ifdef DEBUG_ERR -static void testerr(xmlRegExecCtxtPtr exec); -#endif
/** * xmlRegNewExecCtxt: @@ -3589,7 +3451,7 @@ xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) { exec->maxRollbacks = 0; exec->nbRollbacks = 0; exec->rollbacks = NULL; - exec->status = 0; + exec->status = XML_REGEXP_OK; exec->comp = comp; if (comp->compact == NULL) exec->state = comp->states[0]; @@ -3664,9 +3526,6 @@ xmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec) { static void xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value, void *data) { -#ifdef DEBUG_PUSH - printf("saving value: %d:%s\n", exec->inputStackNr, value); -#endif if (exec->inputStackMax == 0) { exec->inputStackMax = 4; exec->inputStack = (xmlRegInputTokenPtr) @@ -3779,10 +3638,6 @@ xmlRegCompactPushString(xmlRegExecCtxtPtr exec, return(0); }
-#ifdef DEBUG_PUSH - printf("value pushed: %s\n", value); -#endif - /* * Examine all outside transitions from current state */ @@ -3796,9 +3651,6 @@ xmlRegCompactPushString(xmlRegExecCtxtPtr exec, exec->callback(exec->data, value, comp->transdata[state * comp->nbstrings + i], data); } -#ifdef DEBUG_PUSH - printf("entering state %d\n", target); -#endif if (comp->compact[target * (comp->nbstrings + 1)] == XML_REGEXP_SINK_STATE) goto error; @@ -3814,19 +3666,13 @@ xmlRegCompactPushString(xmlRegExecCtxtPtr exec, * Failed to find an exit transition out from current state for the * current token */ -#ifdef DEBUG_PUSH - printf("failed to find a transition for %s on state %d\n", value, state); -#endif error: if (exec->errString != NULL) xmlFree(exec->errString); exec->errString = xmlStrdup(value); exec->errStateNo = state; - exec->status = -1; -#ifdef DEBUG_ERR - testerr(exec); -#endif - return(-1); + exec->status = XML_REGEXP_NOT_FOUND; + return(XML_REGEXP_NOT_FOUND); }
/** @@ -3854,7 +3700,7 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, return(-1); if (exec->comp == NULL) return(-1); - if (exec->status != 0) + if (exec->status != XML_REGEXP_OK) return(exec->status);
if (exec->comp->compact != NULL) @@ -3866,9 +3712,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, final = 1; }
-#ifdef DEBUG_PUSH - printf("value pushed: %s\n", value); -#endif /* * If we have an active rollback stack push the new value there * and get back to where we were left @@ -3877,12 +3720,9 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, xmlFARegExecSaveInputString(exec, value, data); value = exec->inputStack[exec->index].value; data = exec->inputStack[exec->index].data; -#ifdef DEBUG_PUSH - printf("value loaded: %s\n", value); -#endif }
- while ((exec->status == 0) && + while ((exec->status == XML_REGEXP_OK) && ((value != NULL) || ((final == 1) && (exec->state->type != XML_REGEXP_FINAL_STATE)))) { @@ -3910,9 +3750,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
ret = 0;
-#ifdef DEBUG_PUSH - printf("testing all lax %d\n", trans->count); -#endif /* * Check all counted transitions from the current state */ @@ -3948,9 +3785,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
ret = 1;
-#ifdef DEBUG_PUSH - printf("testing all %d\n", trans->count); -#endif /* * Check all counted transitions from the current state */ @@ -3975,14 +3809,10 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
count = exec->counts[trans->count]; counter = &exec->comp->counters[trans->count]; -#ifdef DEBUG_PUSH - printf("testing count %d: val %d, min %d, max %d\n", - trans->count, count, counter->min, counter->max); -#endif ret = ((count >= counter->min) && (count <= counter->max)); } else if (atom == NULL) { fprintf(stderr, "epsilon transition left at runtime\n"); - exec->status = -2; + exec->status = XML_REGEXP_INTERNAL_ERROR; break; } else if (value != NULL) { ret = xmlRegStrEqualWildcard(atom->valuep, value); @@ -4024,9 +3854,6 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, exec->index++; value = exec->inputStack[exec->index].value; data = exec->inputStack[exec->index].data; -#ifdef DEBUG_PUSH - printf("value loaded: %s\n", value); -#endif
/* * End of input: stop here @@ -4081,22 +3908,12 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, xmlFARegExecSave(exec); } if (trans->counter >= 0) { -#ifdef DEBUG_PUSH - printf("Increasing count %d\n", trans->counter); -#endif exec->counts[trans->counter]++; } if ((trans->count >= 0) && (trans->count < REGEXP_ALL_COUNTER)) { -#ifdef DEBUG_REGEXP_EXEC - printf("resetting count %d on transition\n", - trans->count); -#endif exec->counts[trans->count] = 0; } -#ifdef DEBUG_PUSH - printf("entering state %d\n", trans->to); -#endif if ((exec->comp->states[trans->to] != NULL) && (exec->comp->states[trans->to]->type == XML_REGEXP_SINK_STATE)) { @@ -4119,27 +3936,18 @@ xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value, if (exec->index < exec->inputStackNr) { value = exec->inputStack[exec->index].value; data = exec->inputStack[exec->index].data; -#ifdef DEBUG_PUSH - printf("value loaded: %s\n", value); -#endif } else { value = NULL; data = NULL; -#ifdef DEBUG_PUSH - printf("end of input\n"); -#endif } } else { value = NULL; data = NULL; -#ifdef DEBUG_PUSH - printf("end of input\n"); -#endif } } goto progress; } else if (ret < 0) { - exec->status = -4; + exec->status = XML_REGEXP_INTERNAL_ERROR; break; } } @@ -4166,12 +3974,10 @@ rollback: */ exec->determinist = 0; xmlFARegExecRollBack(exec); - if ((exec->inputStack != NULL ) && (exec->status == 0)) { + if ((exec->inputStack != NULL ) && + (exec->status == XML_REGEXP_OK)) { value = exec->inputStack[exec->index].value; data = exec->inputStack[exec->index].data; -#ifdef DEBUG_PUSH - printf("value loaded: %s\n", value); -#endif } } continue; @@ -4179,14 +3985,9 @@ progress: progress = 1; continue; } - if (exec->status == 0) { + if (exec->status == XML_REGEXP_OK) { return(exec->state->type == XML_REGEXP_FINAL_STATE); } -#ifdef DEBUG_ERR - if (exec->status < 0) { - testerr(exec); - } -#endif return(exec->status); }
@@ -4230,7 +4031,7 @@ xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value, return(-1); if (exec->comp == NULL) return(-1); - if (exec->status != 0) + if (exec->status != XML_REGEXP_OK) return(exec->status);
if (value2 == NULL) @@ -4242,7 +4043,7 @@ xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value, if (150 < lenn + lenp + 2) { str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); if (str == NULL) { - exec->status = -1; + exec->status = XML_REGEXP_OUT_OF_MEMORY; return(-1); } } else { @@ -4471,7 +4272,7 @@ xmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string, if (exec == NULL) return(-1); if (string != NULL) { - if (exec->status != 0) + if (exec->status != XML_REGEXP_OK) *string = exec->errString; else *string = NULL; @@ -4479,17 +4280,6 @@ xmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string, return(xmlRegExecGetValues(exec, 1, nbval, nbneg, values, terminal)); }
-#ifdef DEBUG_ERR -static void testerr(xmlRegExecCtxtPtr exec) { - const xmlChar *string; - xmlChar *values[5]; - int nb = 5; - int nbneg; - int terminal; - xmlRegExecErrInfo(exec, &string, &nb, &nbneg, &values[0], &terminal); -} -#endif - #if 0 static int xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) { @@ -4500,10 +4290,10 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
if (exec == NULL) return(-1); - if (exec->status != 0) + if (exec->status != XML_REGEXP_OK) return(exec->status);
- while ((exec->status == 0) && + while ((exec->status == XML_REGEXP_OK) && ((exec->inputString[exec->index] != 0) || (exec->state->type != XML_REGEXP_FINAL_STATE))) {
@@ -4532,14 +4322,10 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
count = exec->counts[trans->count]; counter = &exec->comp->counters[trans->count]; -#ifdef DEBUG_REGEXP_EXEC - printf("testing count %d: val %d, min %d, max %d\n", - trans->count, count, counter->min, counter->max); -#endif ret = ((count >= counter->min) && (count <= counter->max)); } else if (atom == NULL) { fprintf(stderr, "epsilon transition left at runtime\n"); - exec->status = -2; + exec->status = XML_REGEXP_INTERNAL_ERROR; break; } else if (exec->inputString[exec->index] != 0) { codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len); @@ -4609,20 +4395,11 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) { * restart count for expressions like this ((abc){2})* */ if (trans->count >= 0) { -#ifdef DEBUG_REGEXP_EXEC - printf("Reset count %d\n", trans->count); -#endif exec->counts[trans->count] = 0; } if (trans->counter >= 0) { -#ifdef DEBUG_REGEXP_EXEC - printf("Increasing count %d\n", trans->counter); -#endif exec->counts[trans->counter]++; } -#ifdef DEBUG_REGEXP_EXEC - printf("entering state %d\n", trans->to); -#endif exec->state = exec->comp->states[trans->to]; exec->transno = 0; if (trans->atom != NULL) { @@ -4630,7 +4407,7 @@ xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) { } goto progress; } else if (ret < 0) { - exec->status = -4; + exec->status = XML_REGEXP_INTERNAL_ERROR; break; } } @@ -4665,7 +4442,12 @@ xmlFAIsChar(xmlRegParserCtxtPtr ctxt) { int cur; int len;
- cur = CUR_SCHAR(ctxt->cur, len); + len = 4; + cur = xmlGetUTF8Char(ctxt->cur, &len); + if (cur < 0) { + ERROR("Invalid UTF-8"); + return(0); + } if ((cur == '.') || (cur == '\') || (cur == '?') || (cur == '*') || (cur == '+') || (cur == '(') || (cur == ')') || (cur == '|') || (cur == 0x5B) || @@ -5153,7 +4935,12 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) { end = start; len = 1; } else if ((cur != 0x5B) && (cur != 0x5D)) { - end = start = CUR_SCHAR(ctxt->cur, len); + len = 4; + end = start = xmlGetUTF8Char(ctxt->cur, &len); + if (start < 0) { + ERROR("Invalid UTF-8"); + return; + } } else { ERROR("Expecting a char range"); return; @@ -5192,7 +4979,12 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) { } len = 1; } else if ((cur != '\0') && (cur != 0x5B) && (cur != 0x5D)) { - end = CUR_SCHAR(ctxt->cur, len); + len = 4; + end = xmlGetUTF8Char(ctxt->cur, &len); + if (end < 0) { + ERROR("Invalid UTF-8"); + return; + } } else { ERROR("Expecting the end of a char range"); return; @@ -5407,7 +5199,12 @@ xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) { ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL); if (ctxt->atom == NULL) return(-1); - codepoint = CUR_SCHAR(ctxt->cur, len); + len = 4; + codepoint = xmlGetUTF8Char(ctxt->cur, &len); + if (codepoint < 0) { + ERROR("Invalid UTF-8"); + return(-1); + } ctxt->atom->codepoint = codepoint; NEXTL(len); return(1); @@ -5544,9 +5341,6 @@ xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) { ctxt->end = NULL; xmlFAParseBranch(ctxt, NULL); if (top) { -#ifdef DEBUG_REGEXP_GRAPH - printf("State %d is final\n", ctxt->state->no); -#endif ctxt->state->type = XML_REGEXP_FINAL_STATE; } if (CUR != '|') { @@ -5624,6 +5418,9 @@ xmlRegexpCompile(const xmlChar *regexp) { xmlRegexpPtr ret = NULL; xmlRegParserCtxtPtr ctxt;
+ if (regexp == NULL) + return(NULL); + ctxt = xmlRegNewParserCtxt(regexp); if (ctxt == NULL) return(NULL); @@ -6608,8 +6405,6 @@ xmlExpFreeCtxt(xmlExpCtxtPtr ctxt) { ************************************************************************/ #define MAX_NODES 10000
-/* #define DEBUG_DERIV */ - /* * TODO: * - Wildcards @@ -7284,14 +7079,8 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str) return(forbiddenExp); case XML_EXP_ATOM: if (exp->exp_str == str) { -#ifdef DEBUG_DERIV - printf("deriv atom: equal => Empty\n"); -#endif ret = emptyExp; } else { -#ifdef DEBUG_DERIV - printf("deriv atom: mismatch => forbid\n"); -#endif /* TODO wildcards here */ ret = forbiddenExp; } @@ -7299,9 +7088,6 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str) case XML_EXP_OR: { xmlExpNodePtr tmp;
-#ifdef DEBUG_DERIV - printf("deriv or: => or(derivs)\n"); -#endif tmp = xmlExpStringDeriveInt(ctxt, exp->exp_left, str); if (tmp == NULL) { return(NULL); @@ -7316,23 +7102,14 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str) return(ret); } case XML_EXP_SEQ: -#ifdef DEBUG_DERIV - printf("deriv seq: starting with left\n"); -#endif ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str); if (ret == NULL) { return(NULL); } else if (ret == forbiddenExp) { if (IS_NILLABLE(exp->exp_left)) { -#ifdef DEBUG_DERIV - printf("deriv seq: left failed but nillable\n"); -#endif ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str); } } else { -#ifdef DEBUG_DERIV - printf("deriv seq: left match => sequence\n"); -#endif exp->exp_right->ref++; ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, exp->exp_right, NULL, 0, 0); @@ -7348,9 +7125,6 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str) if (ret == NULL) return(NULL); if (ret == forbiddenExp) { -#ifdef DEBUG_DERIV - printf("deriv count: pattern mismatch => forbid\n"); -#endif return(ret); } if (exp->exp_max == 1) @@ -7367,14 +7141,8 @@ xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str) tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL, NULL, min, max); if (ret == emptyExp) { -#ifdef DEBUG_DERIV - printf("deriv count: match to empty => new count\n"); -#endif return(tmp); } -#ifdef DEBUG_DERIV - printf("deriv count: match => sequence with new count\n"); -#endif return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, tmp, NULL, 0, 0)); } @@ -7483,17 +7251,11 @@ xmlExpDivide(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub, *mult = tmp; else xmlExpFree(ctxt, tmp); -#ifdef DEBUG_DERIV - printf("Divide succeeded %d\n", i); -#endif return(i); } xmlExpFree(ctxt, tmp); xmlExpFree(ctxt, tmp2); } -#ifdef DEBUG_DERIV - printf("Divide failed\n"); -#endif return(0); }
@@ -7519,25 +7281,16 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { * amount, then the derivation is empty */ if ((exp == sub) && (exp->c_max >= 0)) { -#ifdef DEBUG_DERIV - printf("Equal(exp, sub) and finite -> Empty\n"); -#endif return(emptyExp); } /* * decompose sub sequence first */ if (sub->type == XML_EXP_EMPTY) { -#ifdef DEBUG_DERIV - printf("Empty(sub) -> Empty\n"); -#endif exp->ref++; return(exp); } if (sub->type == XML_EXP_SEQ) { -#ifdef DEBUG_DERIV - printf("Seq(sub) -> decompose\n"); -#endif tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left); if (tmp == NULL) return(NULL); @@ -7548,9 +7301,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { return(ret); } if (sub->type == XML_EXP_OR) { -#ifdef DEBUG_DERIV - printf("Or(sub) -> decompose\n"); -#endif tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left); if (tmp == forbiddenExp) return(tmp); @@ -7564,36 +7314,21 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret, NULL, 0, 0)); } if (!xmlExpCheckCard(exp, sub)) { -#ifdef DEBUG_DERIV - printf("CheckCard(exp, sub) failed -> Forbid\n"); -#endif return(forbiddenExp); } switch (exp->type) { case XML_EXP_EMPTY: if (sub == emptyExp) return(emptyExp); -#ifdef DEBUG_DERIV - printf("Empty(exp) -> Forbid\n"); -#endif return(forbiddenExp); case XML_EXP_FORBID: -#ifdef DEBUG_DERIV - printf("Forbid(exp) -> Forbid\n"); -#endif return(forbiddenExp); case XML_EXP_ATOM: if (sub->type == XML_EXP_ATOM) { /* TODO: handle wildcards */ if (exp->exp_str == sub->exp_str) { -#ifdef DEBUG_DERIV - printf("Atom match -> Empty\n"); -#endif return(emptyExp); } -#ifdef DEBUG_DERIV - printf("Atom mismatch -> Forbid\n"); -#endif return(forbiddenExp); } if ((sub->type == XML_EXP_COUNT) && @@ -7601,32 +7336,17 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { (sub->exp_left->type == XML_EXP_ATOM)) { /* TODO: handle wildcards */ if (exp->exp_str == sub->exp_left->exp_str) { -#ifdef DEBUG_DERIV - printf("Atom match -> Empty\n"); -#endif return(emptyExp); } -#ifdef DEBUG_DERIV - printf("Atom mismatch -> Forbid\n"); -#endif return(forbiddenExp); } -#ifdef DEBUG_DERIV - printf("Complex exp vs Atom -> Forbid\n"); -#endif return(forbiddenExp); case XML_EXP_SEQ: /* try to get the sequence consumed only if possible */ if (xmlExpCheckCard(exp->exp_left, sub)) { /* See if the sequence can be consumed directly */ -#ifdef DEBUG_DERIV - printf("Seq trying left only\n"); -#endif ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub); if ((ret != forbiddenExp) && (ret != NULL)) { -#ifdef DEBUG_DERIV - printf("Seq trying left only worked\n"); -#endif /* * TODO: assumption here that we are determinist * i.e. we won't get to a nillable exp left @@ -7638,25 +7358,15 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, exp->exp_right, NULL, 0, 0)); } -#ifdef DEBUG_DERIV - } else { - printf("Seq: left too short\n"); -#endif } /* Try instead to decompose */ if (sub->type == XML_EXP_COUNT) { int min, max;
-#ifdef DEBUG_DERIV - printf("Seq: sub is a count\n"); -#endif ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left); if (ret == NULL) return(NULL); if (ret != forbiddenExp) { -#ifdef DEBUG_DERIV - printf("Seq , Count match on left\n"); -#endif if (sub->exp_max < 0) max = -1; else @@ -7687,9 +7397,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { /* we made no progress on structured operations */ break; case XML_EXP_OR: -#ifdef DEBUG_DERIV - printf("Or , trying both side\n"); -#endif ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub); if (ret == NULL) return(NULL); @@ -7712,15 +7419,9 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { if (tmp == forbiddenExp) { int mult;
-#ifdef DEBUG_DERIV - printf("Count, Count inner don't subsume\n"); -#endif mult = xmlExpDivide(ctxt, sub->exp_left, exp->exp_left, NULL, &tmp); if (mult <= 0) { -#ifdef DEBUG_DERIV - printf("Count, Count not multiple => forbidden\n"); -#endif return(forbiddenExp); } if (sub->exp_max == -1) { @@ -7731,17 +7432,11 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { else min = exp->exp_min - sub->exp_min * mult; } else { -#ifdef DEBUG_DERIV - printf("Count, Count finite can't subsume infinite\n"); -#endif xmlExpFree(ctxt, tmp); return(forbiddenExp); } } else { if (exp->exp_max == -1) { -#ifdef DEBUG_DERIV - printf("Infinite loop consume mult finite loop\n"); -#endif if (exp->exp_min > sub->exp_min * mult) { max = -1; min = exp->exp_min - sub->exp_min * mult; @@ -7751,9 +7446,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { } } else { if (exp->exp_max < sub->exp_max * mult) { -#ifdef DEBUG_DERIV - printf("loops max mult mismatch => forbidden\n"); -#endif xmlExpFree(ctxt, tmp); return(forbiddenExp); } @@ -7769,30 +7461,18 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { * TODO: loop here to try to grow if working on finite * blocks. */ -#ifdef DEBUG_DERIV - printf("Count, Count remain not nillable => forbidden\n"); -#endif xmlExpFree(ctxt, tmp); return(forbiddenExp); } else if (sub->exp_max == -1) { if (exp->exp_max == -1) { if (exp->exp_min <= sub->exp_min) { -#ifdef DEBUG_DERIV - printf("Infinite loops Okay => COUNT(0,Inf)\n"); -#endif max = -1; min = 0; } else { -#ifdef DEBUG_DERIV - printf("Infinite loops min => Count(X,Inf)\n"); -#endif max = -1; min = exp->exp_min - sub->exp_min; } } else if (exp->exp_min > sub->exp_min) { -#ifdef DEBUG_DERIV - printf("loops min mismatch 1 => forbidden ???\n"); -#endif xmlExpFree(ctxt, tmp); return(forbiddenExp); } else { @@ -7801,9 +7481,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { } } else { if (exp->exp_max == -1) { -#ifdef DEBUG_DERIV - printf("Infinite loop consume finite loop\n"); -#endif if (exp->exp_min > sub->exp_min) { max = -1; min = exp->exp_min - sub->exp_min; @@ -7813,9 +7490,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { } } else { if (exp->exp_max < sub->exp_max) { -#ifdef DEBUG_DERIV - printf("loops max mismatch => forbidden\n"); -#endif xmlExpFree(ctxt, tmp); return(forbiddenExp); } @@ -7826,9 +7500,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { max = exp->exp_max - sub->exp_max; } } -#ifdef DEBUG_DERIV - printf("loops match => SEQ(COUNT())\n"); -#endif exp->exp_left->ref++; tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL, NULL, min, max); @@ -7843,9 +7514,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { if (tmp == NULL) return(NULL); if (tmp == forbiddenExp) { -#ifdef DEBUG_DERIV - printf("loop mismatch => forbidden\n"); -#endif return(forbiddenExp); } if (exp->exp_min > 0) @@ -7857,9 +7525,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { else max = exp->exp_max - 1;
-#ifdef DEBUG_DERIV - printf("loop match => SEQ(COUNT())\n"); -#endif exp->exp_left->ref++; tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL, NULL, min, max); @@ -7871,9 +7536,6 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { } }
-#ifdef DEBUG_DERIV - printf("Fallback to derivative\n"); -#endif if (IS_NILLABLE(sub)) { if (!(IS_NILLABLE(exp))) return(forbiddenExp); @@ -7971,15 +7633,9 @@ xmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { * O(1) speedups */ if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) { -#ifdef DEBUG_DERIV - printf("Sub nillable and not exp : can't subsume\n"); -#endif return(forbiddenExp); } if (xmlExpCheckCard(exp, sub) == 0) { -#ifdef DEBUG_DERIV - printf("sub generate longer sequences than exp : can't subsume\n"); -#endif return(forbiddenExp); } return(xmlExpExpDeriveInt(ctxt, exp, sub)); @@ -8011,22 +7667,12 @@ xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { * O(1) speedups */ if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) { -#ifdef DEBUG_DERIV - printf("Sub nillable and not exp : can't subsume\n"); -#endif return(0); } if (xmlExpCheckCard(exp, sub) == 0) { -#ifdef DEBUG_DERIV - printf("sub generate longer sequences than exp : can't subsume\n"); -#endif return(0); } tmp = xmlExpExpDeriveInt(ctxt, exp, sub); -#ifdef DEBUG_DERIV - printf("Result derivation :\n"); - PRINT_EXP(tmp); -#endif if (tmp == NULL) return(-1); if (tmp == forbiddenExp) diff --git a/libs/xml2/xmlsave.c b/libs/xml2/xmlsave.c index 5b5c8f1f2fd..dc48c573033 100644 --- a/libs/xml2/xmlsave.c +++ b/libs/xml2/xmlsave.c @@ -1391,13 +1391,14 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) { static void xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { int format = ctxt->format, addmeta; - xmlNodePtr tmp, root, unformattedNode = NULL; + xmlNodePtr tmp, root, unformattedNode = NULL, parent; xmlChar *start, *end; xmlOutputBufferPtr buf = ctxt->buf;
if (cur == NULL) return;
root = cur; + parent = cur->parent; while (1) { switch (cur->type) { case XML_DOCUMENT_NODE: @@ -1414,7 +1415,9 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break;
case XML_DOCUMENT_FRAG_NODE: - if (cur->children) { + /* Always validate cur->parent when descending. */ + if ((cur->parent == parent) && (cur->children != NULL)) { + parent = cur; cur = cur->children; continue; } @@ -1441,6 +1444,16 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { ctxt->indent_nr : ctxt->level), ctxt->indent);
+ /* + * Some users like lxml are known to pass nodes with a corrupted + * tree structure. Fall back to a recursive call to handle this + * case. + */ + if ((cur->parent != parent) && (cur->children != NULL)) { + xhtmlNodeDumpOutput(ctxt, cur); + break; + } + xmlOutputBufferWrite(buf, 1, "<"); if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); @@ -1461,10 +1474,10 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { if (cur->properties != NULL) xhtmlAttrListDumpOutput(ctxt, cur->properties);
- if ((cur->parent != NULL) && - (cur->parent->parent == (xmlNodePtr) cur->doc) && + if ((parent != NULL) && + (parent->parent == (xmlNodePtr) cur->doc) && xmlStrEqual(cur->name, BAD_CAST"head") && - xmlStrEqual(cur->parent->name, BAD_CAST"html")) { + xmlStrEqual(parent->name, BAD_CAST"html")) {
tmp = cur->children; while (tmp != NULL) { @@ -1570,6 +1583,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n"); if (ctxt->level >= 0) ctxt->level++; + parent = cur; cur = cur->children; continue; } @@ -1664,13 +1678,9 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break; }
- /* - * The parent should never be NULL here but we want to handle - * corrupted documents gracefully. - */ - if (cur->parent == NULL) - return; - cur = cur->parent; + cur = parent; + /* cur->parent was validated when descending. */ + parent = cur->parent;
if (cur->type == XML_ELEMENT_NODE) { if (ctxt->level > 0) ctxt->level--; @@ -1847,7 +1857,7 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc) /** * xmlSaveTree: * @ctxt: a document saving context - * @node: the top node of the subtree to save + * @cur: the top node of the subtree to save * * Save a subtree starting at the node parameter to a saving context * TODO: The function is not fully implemented yet as it does not return the @@ -2166,17 +2176,9 @@ xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, xmlInitParser();
if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeDump : node == NULL\n"); -#endif return (-1); } if (buf == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeDump : buf == NULL\n"); -#endif return (-1); } outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); @@ -2218,18 +2220,8 @@ xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur) xmlInitParser();
if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlElemDump : cur == NULL\n"); -#endif return; } -#ifdef DEBUG_TREE - if (doc == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlElemDump : doc == NULL\n"); - } -#endif
outbuf = xmlOutputBufferCreateFile(f, NULL); if (outbuf == NULL) @@ -2274,6 +2266,8 @@ xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int is_xhtml = 0; #endif
+ (void) doc; + xmlInitParser();
if ((buf == NULL) || (cur == NULL)) return; @@ -2467,10 +2461,6 @@ xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) { int ret;
if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlDocDump : document == NULL\n"); -#endif return(-1); } encoding = (const char *) cur->encoding; @@ -2692,4 +2682,3 @@ xmlSaveFile(const char *filename, xmlDocPtr cur) { }
#endif /* LIBXML_OUTPUT_ENABLED */ - diff --git a/libs/xml2/xmlschemas.c b/libs/xml2/xmlschemas.c index 9e57636e9a4..40ff1ea32dd 100644 --- a/libs/xml2/xmlschemas.c +++ b/libs/xml2/xmlschemas.c @@ -79,28 +79,8 @@ #include "private/error.h" #include "private/string.h"
-/* #define DEBUG 1 */ - -/* #define DEBUG_CONTENT 1 */ - -/* #define DEBUG_TYPE 1 */ - -/* #define DEBUG_CONTENT_REGEXP 1 */ - -/* #define DEBUG_AUTOMATA 1 */ - -/* #define DEBUG_IDC */ - -/* #define DEBUG_IDC_NODE_TABLE */ - /* #define WXS_ELEM_DECL_CONS_ENABLED */
-#ifdef DEBUG_IDC - #ifndef DEBUG_IDC_NODE_TABLE - #define DEBUG_IDC_NODE_TABLE - #endif -#endif - /* #define ENABLE_PARTICLE_RESTRICTION 1 */
#define ENABLE_REDEFINE @@ -2143,8 +2123,14 @@ xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, (vctxt->parserCtxt != NULL) && (vctxt->parserCtxt->input != NULL)) { file = vctxt->parserCtxt->input->filename; - line = vctxt->parserCtxt->input->line; - col = vctxt->parserCtxt->input->col; + if (vctxt->inode != NULL) { + line = vctxt->inode->nodeLine; + col = 0; + } else { + /* This is inaccurate. */ + line = vctxt->parserCtxt->input->line; + col = vctxt->parserCtxt->input->col; + } } } else { /* @@ -3803,6 +3789,8 @@ xmlSchemaFreeNotation(xmlSchemaNotationPtr nota) { if (nota == NULL) return; + if (nota->annot != NULL) + xmlSchemaFreeAnnot(nota->annot); xmlFree(nota); }
@@ -4612,83 +4600,6 @@ xmlSchemaDump(FILE * output, xmlSchemaPtr schema) xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output); }
-#ifdef DEBUG_IDC_NODE_TABLE -/** - * xmlSchemaDebugDumpIDCTable: - * @vctxt: the WXS validation context - * - * Displays the current IDC table for debug purposes. - */ -static void -xmlSchemaDebugDumpIDCTable(FILE * output, - const xmlChar *namespaceName, - const xmlChar *localName, - xmlSchemaPSVIIDCBindingPtr bind) -{ - xmlChar *str = NULL; - const xmlChar *value; - xmlSchemaPSVIIDCNodePtr tab; - xmlSchemaPSVIIDCKeyPtr key; - int i, j, res; - - fprintf(output, "IDC: TABLES on '%s'\n", - xmlSchemaFormatQName(&str, namespaceName, localName)); - FREE_AND_NULL(str) - - if (bind == NULL) - return; - do { - fprintf(output, "IDC: BINDING '%s' (%d)\n", - xmlSchemaGetComponentQName(&str, - bind->definition), bind->nbNodes); - FREE_AND_NULL(str) - for (i = 0; i < bind->nbNodes; i++) { - tab = bind->nodeTable[i]; - fprintf(output, " ( "); - for (j = 0; j < bind->definition->nbFields; j++) { - key = tab->keys[j]; - if ((key != NULL) && (key->val != NULL)) { - res = xmlSchemaGetCanonValue(key->val, &value); - if (res >= 0) - fprintf(output, "'%s' ", value); - else - fprintf(output, "CANON-VALUE-FAILED "); - if (res == 0) - FREE_AND_NULL(value) - } else if (key != NULL) - fprintf(output, "(no val), "); - else - fprintf(output, "(key missing), "); - } - fprintf(output, ")\n"); - } - if (bind->dupls && bind->dupls->nbItems) { - fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems); - for (i = 0; i < bind->dupls->nbItems; i++) { - tab = bind->dupls->items[i]; - fprintf(output, " ( "); - for (j = 0; j < bind->definition->nbFields; j++) { - key = tab->keys[j]; - if ((key != NULL) && (key->val != NULL)) { - res = xmlSchemaGetCanonValue(key->val, &value); - if (res >= 0) - fprintf(output, "'%s' ", value); - else - fprintf(output, "CANON-VALUE-FAILED "); - if (res == 0) - FREE_AND_NULL(value) - } else if (key != NULL) - fprintf(output, "(no val), "); - else - fprintf(output, "(key missing), "); - } - fprintf(output, ")\n"); - } - } - bind = bind->next; - } while (bind != NULL); -} -#endif /* DEBUG_IDC */ #endif /* LIBXML_OUTPUT_ENABLED */
/************************************************************************ @@ -4844,15 +4755,6 @@ xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name, WXS_FIND_GLOBAL_ITEM(elemDecl) } exit: -#ifdef DEBUG - if (ret == NULL) { - if (nsName == NULL) - fprintf(stderr, "Unable to lookup element decl. %s", name); - else - fprintf(stderr, "Unable to lookup element decl. %s:%s", name, - nsName); - } -#endif return (ret); }
@@ -4891,15 +4793,6 @@ xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name, } exit:
-#ifdef DEBUG - if (ret == NULL) { - if (nsName == NULL) - fprintf(stderr, "Unable to lookup type %s", name); - else - fprintf(stderr, "Unable to lookup type %s:%s", name, - nsName); - } -#endif return (ret); }
@@ -4925,15 +4818,6 @@ xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name, WXS_FIND_GLOBAL_ITEM(attrDecl) } exit: -#ifdef DEBUG - if (ret == NULL) { - if (nsName == NULL) - fprintf(stderr, "Unable to lookup attribute %s", name); - else - fprintf(stderr, "Unable to lookup attribute %s:%s", name, - nsName); - } -#endif return (ret); }
@@ -4965,15 +4849,6 @@ exit: ret = ret->redef; } */ -#ifdef DEBUG - if (ret == NULL) { - if (nsName == NULL) - fprintf(stderr, "Unable to lookup attribute group %s", name); - else - fprintf(stderr, "Unable to lookup attribute group %s:%s", name, - nsName); - } -#endif return (ret); }
@@ -5000,15 +4875,6 @@ xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name, } exit:
-#ifdef DEBUG - if (ret == NULL) { - if (nsName == NULL) - fprintf(stderr, "Unable to lookup group %s", name); - else - fprintf(stderr, "Unable to lookup group %s:%s", name, - nsName); - } -#endif return (ret); }
@@ -5598,9 +5464,6 @@ xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, if (ctxt == NULL) return (NULL);
-#ifdef DEBUG - fprintf(stderr, "Adding particle component\n"); -#endif ret = (xmlSchemaParticlePtr) xmlMalloc(sizeof(xmlSchemaParticle)); if (ret == NULL) { @@ -10682,7 +10545,7 @@ doc_load: * TODO: (2.2) is not supported. */ if (doc == NULL) { - xmlErrorPtr lerr; + const xmlError *lerr; lerr = xmlGetLastError(); /* * Check if this a parser error, or if the document could @@ -13251,10 +13114,6 @@ xmlSchemaBuildContentModel(xmlSchemaTypePtr type, (type->contentType != XML_SCHEMA_CONTENT_MIXED))) return;
-#ifdef DEBUG_CONTENT - xmlGenericError(xmlGenericErrorContext, - "Building content model for %s\n", name); -#endif ctxt->am = NULL; ctxt->am = xmlNewAutomata(); if (ctxt->am == NULL) { @@ -13281,11 +13140,6 @@ xmlSchemaBuildContentModel(xmlSchemaTypePtr type, WXS_BASIC_CAST type, type->node, "The content model is not determinist", NULL); } else { -#ifdef DEBUG_CONTENT_REGEXP - xmlGenericError(xmlGenericErrorContext, - "Content model of %s:\n", type->name); - xmlRegexpPrint(stderr, type->contModel); -#endif } ctxt->state = NULL; xmlFreeAutomata(ctxt->am); @@ -18149,59 +18003,6 @@ xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt, return(0); }
-#ifdef DEBUG_TYPE -static void -xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt, - xmlSchemaTypePtr type) -{ - if (type->node != NULL) { - xmlGenericError(xmlGenericErrorContext, - "Type of %s : %s:%d :", name, - type->node->doc->URL, - xmlGetLineNo(type->node)); - } else { - xmlGenericError(xmlGenericErrorContext, "Type of %s :", name); - } - if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) { - switch (type->contentType) { - case XML_SCHEMA_CONTENT_SIMPLE: - xmlGenericError(xmlGenericErrorContext, "simple\n"); - break; - case XML_SCHEMA_CONTENT_ELEMENTS: - xmlGenericError(xmlGenericErrorContext, "elements\n"); - break; - case XML_SCHEMA_CONTENT_UNKNOWN: - xmlGenericError(xmlGenericErrorContext, "unknown !!!\n"); - break; - case XML_SCHEMA_CONTENT_EMPTY: - xmlGenericError(xmlGenericErrorContext, "empty\n"); - break; - case XML_SCHEMA_CONTENT_MIXED: - if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) - type->subtypes)) - xmlGenericError(xmlGenericErrorContext, - "mixed as emptiable particle\n"); - else - xmlGenericError(xmlGenericErrorContext, "mixed\n"); - break; - /* Removed, since not used. */ - /* - case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: - xmlGenericError(xmlGenericErrorContext, "mixed or elems\n"); - break; - */ - case XML_SCHEMA_CONTENT_BASIC: - xmlGenericError(xmlGenericErrorContext, "basic\n"); - break; - default: - xmlGenericError(xmlGenericErrorContext, - "not registered !!!\n"); - break; - } - } -} -#endif - /* * 3.14.6 Constraints on Simple Type Definition Schema Components */ @@ -18284,17 +18085,11 @@ xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt, xmlSchemaTypeFixupOptimFacets(type);
exit_error: -#ifdef DEBUG_TYPE - xmlSchemaDebugFixedType(pctxt, type); -#endif if (olderrs != pctxt->nberrors) return(pctxt->err); return(0);
exit_failure: -#ifdef DEBUG_TYPE - xmlSchemaDebugFixedType(pctxt, type); -#endif return(-1); }
@@ -18716,9 +18511,6 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt, res = xmlSchemaCheckCTComponent(pctxt, type); HFAILURE HERROR
-#ifdef DEBUG_TYPE - xmlSchemaDebugFixedType(pctxt, type); -#endif if (olderrs != pctxt->nberrors) return(pctxt->err); else @@ -18726,16 +18518,10 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
exit_error: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; -#ifdef DEBUG_TYPE - xmlSchemaDebugFixedType(pctxt, type); -#endif return(pctxt->err);
exit_failure: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; -#ifdef DEBUG_TYPE - xmlSchemaDebugFixedType(pctxt, type); -#endif return(-1); }
@@ -22614,10 +22400,6 @@ xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt, sto->sel = sel; sto->nbHistory = 0;
-#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n", - sto->sel->xpath); -#endif return (0); }
@@ -22643,30 +22425,12 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
if (nodeType == XML_ATTRIBUTE_NODE) depth++; -#ifdef DEBUG_IDC - { - xmlChar *str = NULL; - xmlGenericError(xmlGenericErrorContext, - "IDC: EVAL on %s, depth %d, type %d\n", - xmlSchemaFormatQName(&str, vctxt->inode->nsName, - vctxt->inode->localName), depth, nodeType); - FREE_AND_NULL(str) - } -#endif /* * Process all active XPath state objects. */ first = vctxt->xpathStates; sto = first; while (sto != head) { -#ifdef DEBUG_IDC - if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) - xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n", - sto->matcher->aidc->def->name, sto->sel->xpath); - else - xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n", - sto->matcher->aidc->def->name, sto->sel->xpath); -#endif if (nodeType == XML_ELEMENT_NODE) res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt, vctxt->inode->localName, vctxt->inode->nsName); @@ -22684,10 +22448,6 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, /* * Full match. */ -#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, "IDC: " - "MATCH\n"); -#endif /* * Register a match in the state object history. */ @@ -22711,21 +22471,12 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, } sto->history[sto->nbHistory++] = depth;
-#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n", - vctxt->depth); -#endif - if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { xmlSchemaIDCSelectPtr sel; /* * Activate state objects for the IDC fields of * the IDC selector. */ -#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, "IDC: " - "activating field states\n"); -#endif sel = sto->matcher->aidc->def->fields; while (sel != NULL) { if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher, @@ -22737,10 +22488,6 @@ xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, /* * An IDC key node was found by the IDC field. */ -#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, - "IDC: key found\n"); -#endif /* * Notify that the character value of this node is * needed. @@ -22873,16 +22620,6 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, return (0); sto = vctxt->xpathStates;
-#ifdef DEBUG_IDC - { - xmlChar *str = NULL; - xmlGenericError(xmlGenericErrorContext, - "IDC: BACK on %s, depth %d\n", - xmlSchemaFormatQName(&str, vctxt->inode->nsName, - vctxt->inode->localName), vctxt->depth); - FREE_AND_NULL(str) - } -#endif /* * Evaluate the state objects. */ @@ -22893,10 +22630,6 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, "calling xmlStreamPop()"); return (-1); } -#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n", - sto->sel->xpath); -#endif if (sto->nbHistory == 0) goto deregister_check;
@@ -23355,10 +23088,6 @@ deregister_check: * Deregister state objects if they reach the depth of creation. */ if ((sto->nbHistory == 0) && (sto->depth == depth)) { -#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n", - sto->sel->xpath); -#endif if (vctxt->xpathStates != sto) { VERROR_INT("xmlSchemaXPathProcessHistory", "The state object to be removed is not the first " @@ -23403,16 +23132,6 @@ xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt, if (idc == NULL) return (0);
-#ifdef DEBUG_IDC - { - xmlChar *str = NULL; - xmlGenericError(xmlGenericErrorContext, - "IDC: REGISTER on %s, depth %d\n", - (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName, - vctxt->inode->localName), vctxt->depth); - FREE_AND_NULL(str) - } -#endif if (vctxt->inode->idcMatchers != NULL) { VERROR_INT("xmlSchemaIDCRegisterMatchers", "The chain of IDC matchers is expected to be empty"); @@ -23497,9 +23216,6 @@ xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt, matcher->depth = vctxt->depth; matcher->aidc = aidc; matcher->idcType = aidc->def->type; -#ifdef DEBUG_IDC - xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n"); -#endif /* * Init the automaton state object. */ @@ -26210,25 +25926,6 @@ xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED, xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata; xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata; inode->decl = item; -#ifdef DEBUG_CONTENT - { - xmlChar *str = NULL; - - if (item->type == XML_SCHEMA_TYPE_ELEMENT) { - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON callback for '%s' [declaration]\n", - xmlSchemaFormatQName(&str, - inode->localName, inode->nsName)); - } else { - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON callback for '%s' [wildcard]\n", - xmlSchemaFormatQName(&str, - inode->localName, inode->nsName)); - - } - FREE_AND_NULL(str) - } -#endif }
static int @@ -26319,10 +26016,6 @@ xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt) "failed to create a regex context"); goto internal_error; } -#ifdef DEBUG_AUTOMATA - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON create on '%s'\n", inode->localName); -#endif }
/* @@ -26330,11 +26023,6 @@ xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt) */ if (INODE_NILLED(inode)) { ret = 0; -#ifdef DEBUG_AUTOMATA - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON succeeded on nilled '%s'\n", - inode->localName); -#endif goto skip_nilled; }
@@ -26356,21 +26044,11 @@ xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt) XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL, "Missing child element(s)", nbval, nbneg, values); -#ifdef DEBUG_AUTOMATA - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON missing ERROR on '%s'\n", - inode->localName); -#endif } else { /* * Content model is satisfied. */ ret = 0; -#ifdef DEBUG_AUTOMATA - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON succeeded on '%s'\n", - inode->localName); -#endif }
} @@ -26673,12 +26351,6 @@ end_elem: * Merge/free the IDC table. */ if (inode->idcTable != NULL) { -#ifdef DEBUG_IDC_NODE_TABLE - xmlSchemaDebugDumpIDCTable(stdout, - inode->nsName, - inode->localName, - inode->idcTable); -#endif if ((vctxt->depth > 0) && (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) { @@ -26870,10 +26542,6 @@ xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt) return (-1); } pielem->regexCtxt = regexCtxt; -#ifdef DEBUG_AUTOMATA - xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n", - pielem->localName); -#endif }
/* @@ -26888,16 +26556,6 @@ xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt) vctxt->inode->localName, vctxt->inode->nsName, vctxt->inode); -#ifdef DEBUG_AUTOMATA - if (ret < 0) - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON push ERROR for '%s' on '%s'\n", - vctxt->inode->localName, pielem->localName); - else - xmlGenericError(xmlGenericErrorContext, - "AUTOMATON push OK for '%s' on '%s'\n", - vctxt->inode->localName, pielem->localName); -#endif if (vctxt->err == XML_SCHEMAV_INTERNAL) { VERROR_INT("xmlSchemaValidateChildElem", "calling xmlRegExecPushString2()"); @@ -29067,6 +28725,55 @@ xmlSchemaValidateStreamLocator(void *ctx, const char **file, return(-1); }
+/** + * xmlSchemaValidateStreamInternal: + * @ctxt: a schema validation context + * @pctxt: a parser context + * + * Returns 0 if the document is schemas valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +static int +xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt, + xmlParserCtxtPtr pctxt) { + xmlSchemaSAXPlugPtr plug = NULL; + int ret; + + pctxt->linenumbers = 1; + xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt); + + ctxt->parserCtxt = pctxt; + ctxt->input = pctxt->input->buf; + + /* + * Plug the validation and launch the parsing + */ + plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData)); + if (plug == NULL) { + ret = -1; + goto done; + } + ctxt->input = pctxt->input->buf; + ctxt->sax = pctxt->sax; + ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; + ret = xmlSchemaVStart(ctxt); + + if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) { + ret = ctxt->parserCtxt->errNo; + if (ret == 0) + ret = 1; + } + +done: + ctxt->parserCtxt = NULL; + ctxt->sax = NULL; + ctxt->input = NULL; + if (plug != NULL) { + xmlSchemaSAXUnplug(plug); + } + return (ret); +} + /** * xmlSchemaValidateStream: * @ctxt: a schema validation context @@ -29087,7 +28794,6 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, xmlParserInputBufferPtr input, xmlCharEncoding enc, xmlSAXHandlerPtr sax, void *user_data) { - xmlSchemaSAXPlugPtr plug = NULL; xmlParserCtxtPtr pctxt = NULL; xmlParserInputPtr inputStream = NULL; int ret; @@ -29114,8 +28820,6 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, if (options) xmlCtxtUseOptions(pctxt, options); #endif - pctxt->linenumbers = 1; - xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
inputStream = xmlNewIOInputStream(pctxt, input, enc); if (inputStream == NULL) { @@ -29123,36 +28827,12 @@ xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, goto done; } inputPush(pctxt, inputStream); - ctxt->parserCtxt = pctxt; - ctxt->input = input;
- /* - * Plug the validation and launch the parsing - */ - plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData)); - if (plug == NULL) { - ret = -1; - goto done; - } - ctxt->input = input; ctxt->enc = enc; - ctxt->sax = pctxt->sax; - ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; - ret = xmlSchemaVStart(ctxt);
- if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) { - ret = ctxt->parserCtxt->errNo; - if (ret == 0) - ret = 1; - } + ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
done: - ctxt->parserCtxt = NULL; - ctxt->sax = NULL; - ctxt->input = NULL; - if (plug != NULL) { - xmlSchemaSAXUnplug(plug); - } /* cleanup */ if (pctxt != NULL) { xmlFreeParserCtxt(pctxt); @@ -29178,17 +28858,19 @@ xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt, int options ATTRIBUTE_UNUSED) { int ret; - xmlParserInputBufferPtr input; + xmlParserCtxtPtr pctxt = NULL;
if ((ctxt == NULL) || (filename == NULL)) return (-1);
- input = xmlParserInputBufferCreateFilename(filename, - XML_CHAR_ENCODING_NONE); - if (input == NULL) + pctxt = xmlCreateURLParserCtxt(filename, 0); + if (pctxt == NULL) return (-1); - ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE, - NULL, NULL); + /* We really want pctxt->sax to be NULL here. */ + xmlFree(pctxt->sax); + pctxt->sax = NULL; + ret = xmlSchemaValidateStreamInternal(ctxt, pctxt); + xmlFreeParserCtxt(pctxt); return (ret); }
diff --git a/libs/xml2/xmlschemastypes.c b/libs/xml2/xmlschemastypes.c index 60268e2d8eb..de95d940762 100644 --- a/libs/xml2/xmlschemastypes.c +++ b/libs/xml2/xmlschemastypes.c @@ -17,6 +17,7 @@
#ifdef LIBXML_SCHEMAS_ENABLED
+#include <stdlib.h> #include <string.h> #include <math.h> #include <float.h> @@ -25,7 +26,6 @@ #include <libxml/parser.h> #include <libxml/parserInternals.h> #include <libxml/hash.h> -#include <libxml/valid.h> #include <libxml/xpath.h> #include <libxml/uri.h>
@@ -35,8 +35,6 @@
#include "private/error.h"
-#define DEBUG - #ifndef LIBXML_XPATH_ENABLED extern double xmlXPathNAN; extern double xmlXPathPINF; @@ -1299,25 +1297,6 @@ static const long dayInLeapYearByMonth[12] = dayInLeapYearByMonth[month - 1] : \ dayInYearByMonth[month - 1]) + day)
-#ifdef DEBUG -#define DEBUG_DATE(dt) \ - xmlGenericError(xmlGenericErrorContext, \ - "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \ - dt->type,dt->value.date.year,dt->value.date.mon, \ - dt->value.date.day,dt->value.date.hour,dt->value.date.min, \ - dt->value.date.sec); \ - if (dt->value.date.tz_flag) \ - if (dt->value.date.tzo != 0) \ - xmlGenericError(xmlGenericErrorContext, \ - "%+05d\n",dt->value.date.tzo); \ - else \ - xmlGenericError(xmlGenericErrorContext, "Z\n"); \ - else \ - xmlGenericError(xmlGenericErrorContext,"\n") -#else -#define DEBUG_DATE(dt) -#endif - /** * _xmlSchemaParseGYear: * @dt: pointer to a date structure diff --git a/libs/xml2/xmlstring.c b/libs/xml2/xmlstring.c index 7f6153aff51..ce1c12dabbc 100644 --- a/libs/xml2/xmlstring.c +++ b/libs/xml2/xmlstring.c @@ -712,47 +712,47 @@ xmlGetUTF8Char(const unsigned char *utf, int *len) { goto error; if (len == NULL) goto error; - if (*len < 1) - goto error;
c = utf[0]; - if (c & 0x80) { - if (*len < 2) + if (c < 0x80) { + if (*len < 1) goto error; - if ((utf[1] & 0xc0) != 0x80) + /* 1-byte code */ + *len = 1; + } else { + if ((*len < 2) || ((utf[1] & 0xc0) != 0x80)) goto error; - if ((c & 0xe0) == 0xe0) { - if (*len < 3) + if (c < 0xe0) { + if (c < 0xc2) goto error; - if ((utf[2] & 0xc0) != 0x80) + /* 2-byte code */ + *len = 2; + c = (c & 0x1f) << 6; + c |= utf[1] & 0x3f; + } else { + if ((*len < 3) || ((utf[2] & 0xc0) != 0x80)) goto error; - if ((c & 0xf0) == 0xf0) { - if (*len < 4) + if (c < 0xf0) { + /* 3-byte code */ + *len = 3; + c = (c & 0xf) << 12; + c |= (utf[1] & 0x3f) << 6; + c |= utf[2] & 0x3f; + if ((c < 0x800) || ((c >= 0xd800) && (c < 0xe000))) goto error; - if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80) + } else { + if ((*len < 4) || ((utf[3] & 0xc0) != 0x80)) goto error; *len = 4; /* 4-byte code */ - c = (utf[0] & 0x7) << 18; + c = (c & 0x7) << 18; c |= (utf[1] & 0x3f) << 12; c |= (utf[2] & 0x3f) << 6; c |= utf[3] & 0x3f; - } else { - /* 3-byte code */ - *len = 3; - c = (utf[0] & 0xf) << 12; - c |= (utf[1] & 0x3f) << 6; - c |= utf[2] & 0x3f; + if ((c < 0x10000) || (c >= 0x110000)) + goto error; } - } else { - /* 2-byte code */ - *len = 2; - c = (utf[0] & 0x1f) << 6; - c |= utf[1] & 0x3f; } - } else { - /* 1-byte code */ - *len = 1; } return(c);
diff --git a/libs/xml2/xpath.c b/libs/xml2/xpath.c index 9c3a2acf6d5..83e06526226 100644 --- a/libs/xml2/xpath.c +++ b/libs/xml2/xpath.c @@ -31,7 +31,6 @@
#include <libxml/xmlmemory.h> #include <libxml/tree.h> -#include <libxml/valid.h> #include <libxml/xpath.h> #include <libxml/xpathInternals.h> #include <libxml/parserInternals.h> @@ -44,7 +43,6 @@ #endif #include <libxml/xmlerror.h> #include <libxml/threads.h> -#include <libxml/globals.h> #ifdef LIBXML_PATTERN_ENABLED #include <libxml/pattern.h> #endif @@ -89,13 +87,6 @@ */ #define XP_OPTIMIZED_FILTER_FIRST
-/* -* XP_DEBUG_OBJ_USAGE: -* Internal flag to enable tracking of how much XPath objects have been -* created. -*/ -/* #define XP_DEBUG_OBJ_USAGE */ - /* * XPATH_MAX_STEPS: * when compiling an XPath expression we arbitrary limit the maximum @@ -192,6 +183,8 @@ xmlInitXPathInternal(void) { * xmlXPathIsNaN: * @val: a double value * + * Checks whether a double is a NaN. + * * Returns 1 if the value is a NaN, 0 otherwise */ int @@ -207,6 +200,8 @@ xmlXPathIsNaN(double val) { * xmlXPathIsInf: * @val: a double value * + * Checks whether a double is an infinity. + * * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise */ int @@ -230,11 +225,6 @@ xmlXPathIsInf(double val) { * TODO: when compatibility allows remove all "fake node libxslt" strings * the test should just be name[0] = ' ' */ -#ifdef DEBUG_XPATH_EXPRESSION -#define DEBUG_STEP -#define DEBUG_EXPR -#define DEBUG_EVAL_COUNTS -#endif
static xmlNs xmlXPathXMLNamespaceStruct = { NULL, @@ -982,10 +972,6 @@ struct _xmlXPathCompExpr { int last; /* index of last step in expression */ xmlChar *expr; /* the expression being computed */ xmlDictPtr dict; /* the dictionary to use if any */ -#ifdef DEBUG_EVAL_COUNTS - int nb; - xmlChar *string; -#endif #ifdef XPATH_STREAMING xmlPatternPtr stream; #endif @@ -1044,9 +1030,6 @@ xmlXPathNewCompExpr(void) { } memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp)); cur->last = -1; -#ifdef DEBUG_EVAL_COUNTS - cur->nb = 0; -#endif return(cur); }
@@ -1089,11 +1072,6 @@ xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp) if (comp->steps != NULL) { xmlFree(comp->steps); } -#ifdef DEBUG_EVAL_COUNTS - if (comp->string != NULL) { - xmlFree(comp->string); - } -#endif #ifdef XPATH_STREAMING if (comp->stream != NULL) { xmlFreePatternList(comp->stream); @@ -1240,33 +1218,6 @@ struct _xmlXPathContextCache { int maxBoolean; int maxNumber; int maxMisc; -#ifdef XP_DEBUG_OBJ_USAGE - int dbgCachedAll; - int dbgCachedNodeset; - int dbgCachedString; - int dbgCachedBool; - int dbgCachedNumber; - int dbgCachedPoint; - int dbgCachedRange; - int dbgCachedLocset; - int dbgCachedUsers; - int dbgCachedXSLTTree; - int dbgCachedUndefined; - - - int dbgReusedAll; - int dbgReusedNodeset; - int dbgReusedString; - int dbgReusedBool; - int dbgReusedNumber; - int dbgReusedPoint; - int dbgReusedRange; - int dbgReusedLocset; - int dbgReusedUsers; - int dbgReusedXSLTTree; - int dbgReusedUndefined; - -#endif };
/************************************************************************ @@ -1723,478 +1674,6 @@ xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp, } }
-#ifdef XP_DEBUG_OBJ_USAGE - -/* -* XPath object usage related debugging variables. -*/ -static int xmlXPathDebugObjCounterUndefined = 0; -static int xmlXPathDebugObjCounterNodeset = 0; -static int xmlXPathDebugObjCounterBool = 0; -static int xmlXPathDebugObjCounterNumber = 0; -static int xmlXPathDebugObjCounterString = 0; -static int xmlXPathDebugObjCounterPoint = 0; -static int xmlXPathDebugObjCounterRange = 0; -static int xmlXPathDebugObjCounterLocset = 0; -static int xmlXPathDebugObjCounterUsers = 0; -static int xmlXPathDebugObjCounterXSLTTree = 0; -static int xmlXPathDebugObjCounterAll = 0; - -static int xmlXPathDebugObjTotalUndefined = 0; -static int xmlXPathDebugObjTotalNodeset = 0; -static int xmlXPathDebugObjTotalBool = 0; -static int xmlXPathDebugObjTotalNumber = 0; -static int xmlXPathDebugObjTotalString = 0; -static int xmlXPathDebugObjTotalPoint = 0; -static int xmlXPathDebugObjTotalRange = 0; -static int xmlXPathDebugObjTotalLocset = 0; -static int xmlXPathDebugObjTotalUsers = 0; -static int xmlXPathDebugObjTotalXSLTTree = 0; -static int xmlXPathDebugObjTotalAll = 0; - -static int xmlXPathDebugObjMaxUndefined = 0; -static int xmlXPathDebugObjMaxNodeset = 0; -static int xmlXPathDebugObjMaxBool = 0; -static int xmlXPathDebugObjMaxNumber = 0; -static int xmlXPathDebugObjMaxString = 0; -static int xmlXPathDebugObjMaxPoint = 0; -static int xmlXPathDebugObjMaxRange = 0; -static int xmlXPathDebugObjMaxLocset = 0; -static int xmlXPathDebugObjMaxUsers = 0; -static int xmlXPathDebugObjMaxXSLTTree = 0; -static int xmlXPathDebugObjMaxAll = 0; - -static void -xmlXPathDebugObjUsageReset(xmlXPathContextPtr ctxt) -{ - if (ctxt != NULL) { - if (ctxt->cache != NULL) { - xmlXPathContextCachePtr cache = - (xmlXPathContextCachePtr) ctxt->cache; - - cache->dbgCachedAll = 0; - cache->dbgCachedNodeset = 0; - cache->dbgCachedString = 0; - cache->dbgCachedBool = 0; - cache->dbgCachedNumber = 0; - cache->dbgCachedPoint = 0; - cache->dbgCachedRange = 0; - cache->dbgCachedLocset = 0; - cache->dbgCachedUsers = 0; - cache->dbgCachedXSLTTree = 0; - cache->dbgCachedUndefined = 0; - - cache->dbgReusedAll = 0; - cache->dbgReusedNodeset = 0; - cache->dbgReusedString = 0; - cache->dbgReusedBool = 0; - cache->dbgReusedNumber = 0; - cache->dbgReusedPoint = 0; - cache->dbgReusedRange = 0; - cache->dbgReusedLocset = 0; - cache->dbgReusedUsers = 0; - cache->dbgReusedXSLTTree = 0; - cache->dbgReusedUndefined = 0; - } - } - - xmlXPathDebugObjCounterUndefined = 0; - xmlXPathDebugObjCounterNodeset = 0; - xmlXPathDebugObjCounterBool = 0; - xmlXPathDebugObjCounterNumber = 0; - xmlXPathDebugObjCounterString = 0; - xmlXPathDebugObjCounterPoint = 0; - xmlXPathDebugObjCounterRange = 0; - xmlXPathDebugObjCounterLocset = 0; - xmlXPathDebugObjCounterUsers = 0; - xmlXPathDebugObjCounterXSLTTree = 0; - xmlXPathDebugObjCounterAll = 0; - - xmlXPathDebugObjTotalUndefined = 0; - xmlXPathDebugObjTotalNodeset = 0; - xmlXPathDebugObjTotalBool = 0; - xmlXPathDebugObjTotalNumber = 0; - xmlXPathDebugObjTotalString = 0; - xmlXPathDebugObjTotalPoint = 0; - xmlXPathDebugObjTotalRange = 0; - xmlXPathDebugObjTotalLocset = 0; - xmlXPathDebugObjTotalUsers = 0; - xmlXPathDebugObjTotalXSLTTree = 0; - xmlXPathDebugObjTotalAll = 0; - - xmlXPathDebugObjMaxUndefined = 0; - xmlXPathDebugObjMaxNodeset = 0; - xmlXPathDebugObjMaxBool = 0; - xmlXPathDebugObjMaxNumber = 0; - xmlXPathDebugObjMaxString = 0; - xmlXPathDebugObjMaxPoint = 0; - xmlXPathDebugObjMaxRange = 0; - xmlXPathDebugObjMaxLocset = 0; - xmlXPathDebugObjMaxUsers = 0; - xmlXPathDebugObjMaxXSLTTree = 0; - xmlXPathDebugObjMaxAll = 0; - -} - -static void -xmlXPathDebugObjUsageRequested(xmlXPathContextPtr ctxt, - xmlXPathObjectType objType) -{ - int isCached = 0; - - if (ctxt != NULL) { - if (ctxt->cache != NULL) { - xmlXPathContextCachePtr cache = - (xmlXPathContextCachePtr) ctxt->cache; - - isCached = 1; - - cache->dbgReusedAll++; - switch (objType) { - case XPATH_UNDEFINED: - cache->dbgReusedUndefined++; - break; - case XPATH_NODESET: - cache->dbgReusedNodeset++; - break; - case XPATH_BOOLEAN: - cache->dbgReusedBool++; - break; - case XPATH_NUMBER: - cache->dbgReusedNumber++; - break; - case XPATH_STRING: - cache->dbgReusedString++; - break; -#ifdef LIBXML_XPTR_LOCS_ENABLED - case XPATH_POINT: - cache->dbgReusedPoint++; - break; - case XPATH_RANGE: - cache->dbgReusedRange++; - break; - case XPATH_LOCATIONSET: - cache->dbgReusedLocset++; - break; -#endif /* LIBXML_XPTR_LOCS_ENABLED */ - case XPATH_USERS: - cache->dbgReusedUsers++; - break; - case XPATH_XSLT_TREE: - cache->dbgReusedXSLTTree++; - break; - default: - break; - } - } - } - - switch (objType) { - case XPATH_UNDEFINED: - if (! isCached) - xmlXPathDebugObjTotalUndefined++; - xmlXPathDebugObjCounterUndefined++; - if (xmlXPathDebugObjCounterUndefined > - xmlXPathDebugObjMaxUndefined) - xmlXPathDebugObjMaxUndefined = - xmlXPathDebugObjCounterUndefined; - break; - case XPATH_NODESET: - if (! isCached) - xmlXPathDebugObjTotalNodeset++; - xmlXPathDebugObjCounterNodeset++; - if (xmlXPathDebugObjCounterNodeset > - xmlXPathDebugObjMaxNodeset) - xmlXPathDebugObjMaxNodeset = - xmlXPathDebugObjCounterNodeset; - break; - case XPATH_BOOLEAN: - if (! isCached) - xmlXPathDebugObjTotalBool++; - xmlXPathDebugObjCounterBool++; - if (xmlXPathDebugObjCounterBool > - xmlXPathDebugObjMaxBool) - xmlXPathDebugObjMaxBool = - xmlXPathDebugObjCounterBool; - break; - case XPATH_NUMBER: - if (! isCached) - xmlXPathDebugObjTotalNumber++; - xmlXPathDebugObjCounterNumber++; - if (xmlXPathDebugObjCounterNumber > - xmlXPathDebugObjMaxNumber) - xmlXPathDebugObjMaxNumber = - xmlXPathDebugObjCounterNumber; - break; - case XPATH_STRING: - if (! isCached) - xmlXPathDebugObjTotalString++; - xmlXPathDebugObjCounterString++; - if (xmlXPathDebugObjCounterString > - xmlXPathDebugObjMaxString) - xmlXPathDebugObjMaxString = - xmlXPathDebugObjCounterString; - break; -#ifdef LIBXML_XPTR_LOCS_ENABLED - case XPATH_POINT: - if (! isCached) - xmlXPathDebugObjTotalPoint++; - xmlXPathDebugObjCounterPoint++; - if (xmlXPathDebugObjCounterPoint > - xmlXPathDebugObjMaxPoint) - xmlXPathDebugObjMaxPoint = - xmlXPathDebugObjCounterPoint; - break; - case XPATH_RANGE: - if (! isCached) - xmlXPathDebugObjTotalRange++; - xmlXPathDebugObjCounterRange++; - if (xmlXPathDebugObjCounterRange > - xmlXPathDebugObjMaxRange) - xmlXPathDebugObjMaxRange = - xmlXPathDebugObjCounterRange; - break; - case XPATH_LOCATIONSET: - if (! isCached) - xmlXPathDebugObjTotalLocset++; - xmlXPathDebugObjCounterLocset++; - if (xmlXPathDebugObjCounterLocset > - xmlXPathDebugObjMaxLocset) - xmlXPathDebugObjMaxLocset = - xmlXPathDebugObjCounterLocset; - break; -#endif /* LIBXML_XPTR_LOCS_ENABLED */ - case XPATH_USERS: - if (! isCached) - xmlXPathDebugObjTotalUsers++; - xmlXPathDebugObjCounterUsers++; - if (xmlXPathDebugObjCounterUsers > - xmlXPathDebugObjMaxUsers) - xmlXPathDebugObjMaxUsers = - xmlXPathDebugObjCounterUsers; - break; - case XPATH_XSLT_TREE: - if (! isCached) - xmlXPathDebugObjTotalXSLTTree++; - xmlXPathDebugObjCounterXSLTTree++; - if (xmlXPathDebugObjCounterXSLTTree > - xmlXPathDebugObjMaxXSLTTree) - xmlXPathDebugObjMaxXSLTTree = - xmlXPathDebugObjCounterXSLTTree; - break; - default: - break; - } - if (! isCached) - xmlXPathDebugObjTotalAll++; - xmlXPathDebugObjCounterAll++; - if (xmlXPathDebugObjCounterAll > - xmlXPathDebugObjMaxAll) - xmlXPathDebugObjMaxAll = - xmlXPathDebugObjCounterAll; -} - -static void -xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt, - xmlXPathObjectType objType) -{ - int isCached = 0; - - if (ctxt != NULL) { - if (ctxt->cache != NULL) { - xmlXPathContextCachePtr cache = - (xmlXPathContextCachePtr) ctxt->cache; - - isCached = 1; - - cache->dbgCachedAll++; - switch (objType) { - case XPATH_UNDEFINED: - cache->dbgCachedUndefined++; - break; - case XPATH_NODESET: - cache->dbgCachedNodeset++; - break; - case XPATH_BOOLEAN: - cache->dbgCachedBool++; - break; - case XPATH_NUMBER: - cache->dbgCachedNumber++; - break; - case XPATH_STRING: - cache->dbgCachedString++; - break; -#ifdef LIBXML_XPTR_LOCS_ENABLED - case XPATH_POINT: - cache->dbgCachedPoint++; - break; - case XPATH_RANGE: - cache->dbgCachedRange++; - break; - case XPATH_LOCATIONSET: - cache->dbgCachedLocset++; - break; -#endif /* LIBXML_XPTR_LOCS_ENABLED */ - case XPATH_USERS: - cache->dbgCachedUsers++; - break; - case XPATH_XSLT_TREE: - cache->dbgCachedXSLTTree++; - break; - default: - break; - } - - } - } - switch (objType) { - case XPATH_UNDEFINED: - xmlXPathDebugObjCounterUndefined--; - break; - case XPATH_NODESET: - xmlXPathDebugObjCounterNodeset--; - break; - case XPATH_BOOLEAN: - xmlXPathDebugObjCounterBool--; - break; - case XPATH_NUMBER: - xmlXPathDebugObjCounterNumber--; - break; - case XPATH_STRING: - xmlXPathDebugObjCounterString--; - break; -#ifdef LIBXML_XPTR_LOCS_ENABLED - case XPATH_POINT: - xmlXPathDebugObjCounterPoint--; - break; - case XPATH_RANGE: - xmlXPathDebugObjCounterRange--; - break; - case XPATH_LOCATIONSET: - xmlXPathDebugObjCounterLocset--; - break; -#endif /* LIBXML_XPTR_LOCS_ENABLED */ - case XPATH_USERS: - xmlXPathDebugObjCounterUsers--; - break; - case XPATH_XSLT_TREE: - xmlXPathDebugObjCounterXSLTTree--; - break; - default: - break; - } - xmlXPathDebugObjCounterAll--; -} - -static void -xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt) -{ - int reqAll, reqNodeset, reqString, reqBool, reqNumber, - reqXSLTTree, reqUndefined; - int caAll = 0, caNodeset = 0, caString = 0, caBool = 0, - caNumber = 0, caXSLTTree = 0, caUndefined = 0; - int reAll = 0, reNodeset = 0, reString = 0, reBool = 0, - reNumber = 0, reXSLTTree = 0, reUndefined = 0; - int leftObjs = xmlXPathDebugObjCounterAll; - - reqAll = xmlXPathDebugObjTotalAll; - reqNodeset = xmlXPathDebugObjTotalNodeset; - reqString = xmlXPathDebugObjTotalString; - reqBool = xmlXPathDebugObjTotalBool; - reqNumber = xmlXPathDebugObjTotalNumber; - reqXSLTTree = xmlXPathDebugObjTotalXSLTTree; - reqUndefined = xmlXPathDebugObjTotalUndefined; - - printf("# XPath object usage:\n"); - - if (ctxt != NULL) { - if (ctxt->cache != NULL) { - xmlXPathContextCachePtr cache = - (xmlXPathContextCachePtr) ctxt->cache; - - reAll = cache->dbgReusedAll; - reqAll += reAll; - reNodeset = cache->dbgReusedNodeset; - reqNodeset += reNodeset; - reString = cache->dbgReusedString; - reqString += reString; - reBool = cache->dbgReusedBool; - reqBool += reBool; - reNumber = cache->dbgReusedNumber; - reqNumber += reNumber; - reXSLTTree = cache->dbgReusedXSLTTree; - reqXSLTTree += reXSLTTree; - reUndefined = cache->dbgReusedUndefined; - reqUndefined += reUndefined; - - caAll = cache->dbgCachedAll; - caBool = cache->dbgCachedBool; - caNodeset = cache->dbgCachedNodeset; - caString = cache->dbgCachedString; - caNumber = cache->dbgCachedNumber; - caXSLTTree = cache->dbgCachedXSLTTree; - caUndefined = cache->dbgCachedUndefined; - - if (cache->nodesetObjs) - leftObjs -= cache->nodesetObjs->number; - if (cache->stringObjs) - leftObjs -= cache->stringObjs->number; - if (cache->booleanObjs) - leftObjs -= cache->booleanObjs->number; - if (cache->numberObjs) - leftObjs -= cache->numberObjs->number; - if (cache->miscObjs) - leftObjs -= cache->miscObjs->number; - } - } - - printf("# all\n"); - printf("# total : %d\n", reqAll); - printf("# left : %d\n", leftObjs); - printf("# created: %d\n", xmlXPathDebugObjTotalAll); - printf("# reused : %d\n", reAll); - printf("# max : %d\n", xmlXPathDebugObjMaxAll); - - printf("# node-sets\n"); - printf("# total : %d\n", reqNodeset); - printf("# created: %d\n", xmlXPathDebugObjTotalNodeset); - printf("# reused : %d\n", reNodeset); - printf("# max : %d\n", xmlXPathDebugObjMaxNodeset); - - printf("# strings\n"); - printf("# total : %d\n", reqString); - printf("# created: %d\n", xmlXPathDebugObjTotalString); - printf("# reused : %d\n", reString); - printf("# max : %d\n", xmlXPathDebugObjMaxString); - - printf("# booleans\n"); - printf("# total : %d\n", reqBool); - printf("# created: %d\n", xmlXPathDebugObjTotalBool); - printf("# reused : %d\n", reBool); - printf("# max : %d\n", xmlXPathDebugObjMaxBool); - - printf("# numbers\n"); - printf("# total : %d\n", reqNumber); - printf("# created: %d\n", xmlXPathDebugObjTotalNumber); - printf("# reused : %d\n", reNumber); - printf("# max : %d\n", xmlXPathDebugObjMaxNumber); - - printf("# XSLT result tree fragments\n"); - printf("# total : %d\n", reqXSLTTree); - printf("# created: %d\n", xmlXPathDebugObjTotalXSLTTree); - printf("# reused : %d\n", reXSLTTree); - printf("# max : %d\n", xmlXPathDebugObjMaxXSLTTree); - - printf("# undefined\n"); - printf("# total : %d\n", reqUndefined); - printf("# created: %d\n", xmlXPathDebugObjTotalUndefined); - printf("# reused : %d\n", reUndefined); - printf("# max : %d\n", xmlXPathDebugObjMaxUndefined); - -} - -#endif /* XP_DEBUG_OBJ_USAGE */ - #endif /* LIBXML_DEBUG_ENABLED */
/************************************************************************ @@ -2250,9 +1729,6 @@ xmlXPathCacheFreeObjectList(xmlPointerListPtr list) xmlFree(obj->nodesetval); } xmlFree(obj); -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjCounterAll--; -#endif } xmlPointerListFree(list); } @@ -2358,9 +1834,6 @@ xmlXPathCacheWrapNodeSet(xmlXPathContextPtr ctxt, xmlNodeSetPtr val) cache->miscObjs->items[--cache->miscObjs->number]; ret->type = XPATH_NODESET; ret->nodesetval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); -#endif return(ret); } } @@ -2395,9 +1868,6 @@ xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val) cache->stringObjs->items[--cache->stringObjs->number]; ret->type = XPATH_STRING; ret->stringval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); -#endif return(ret); } else if ((cache->miscObjs != NULL) && (cache->miscObjs->number != 0)) @@ -2411,9 +1881,6 @@ xmlXPathCacheWrapString(xmlXPathContextPtr ctxt, xmlChar *val)
ret->type = XPATH_STRING; ret->stringval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); -#endif return(ret); } } @@ -2459,9 +1926,6 @@ xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) ret->nodesetval->nodeNr = 1; } } -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); -#endif return(ret); } else if ((cache->miscObjs != NULL) && (cache->miscObjs->number != 0)) @@ -2485,9 +1949,6 @@ xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) ret->type = XPATH_NODESET; ret->boolval = 0; ret->nodesetval = set; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); -#endif return(ret); } } @@ -2528,9 +1989,6 @@ xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) cache->stringObjs->items[--cache->stringObjs->number]; ret->type = XPATH_STRING; ret->stringval = copy; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); -#endif return(ret); } else if ((cache->miscObjs != NULL) && (cache->miscObjs->number != 0)) @@ -2551,9 +2009,6 @@ xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val)
ret->type = XPATH_STRING; ret->stringval = copy; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); -#endif return(ret); } } @@ -2601,9 +2056,6 @@ xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val) cache->booleanObjs->items[--cache->booleanObjs->number]; ret->type = XPATH_BOOLEAN; ret->boolval = (val != 0); -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN); -#endif return(ret); } else if ((cache->miscObjs != NULL) && (cache->miscObjs->number != 0)) @@ -2615,9 +2067,6 @@ xmlXPathCacheNewBoolean(xmlXPathContextPtr ctxt, int val)
ret->type = XPATH_BOOLEAN; ret->boolval = (val != 0); -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_BOOLEAN); -#endif return(ret); } } @@ -2649,9 +2098,6 @@ xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val) cache->numberObjs->items[--cache->numberObjs->number]; ret->type = XPATH_NUMBER; ret->floatval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER); -#endif return(ret); } else if ((cache->miscObjs != NULL) && (cache->miscObjs->number != 0)) @@ -2663,9 +2109,6 @@ xmlXPathCacheNewFloat(xmlXPathContextPtr ctxt, double val)
ret->type = XPATH_NUMBER; ret->floatval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(ctxt, XPATH_NUMBER); -#endif return(ret); } } @@ -2693,9 +2136,6 @@ xmlXPathCacheConvertString(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
switch (val->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n"); -#endif break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -3204,7 +2644,7 @@ xmlXPathFormatNumber(double number, char buffer[], int buffersize) /* Finally copy result back to caller */ size = strlen(work) + 1; if (size > buffersize) { - /*work[buffersize - 1] = 0;*/ + work[buffersize - 1] = 0; size = buffersize; } memmove(buffer, work, size); @@ -4062,11 +3502,6 @@ xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) { if (cur->nodeTab[i] == val) break;
if (i >= cur->nodeNr) { /* not found */ -#ifdef DEBUG - xmlGenericError(xmlGenericErrorContext, - "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n", - val->name); -#endif return; } if ((cur->nodeTab[i] != NULL) && @@ -4216,47 +3651,6 @@ xmlXPathFreeValueTree(xmlNodeSetPtr obj) { xmlFree(obj); }
-#if defined(DEBUG) || defined(DEBUG_STEP) -/** - * xmlGenericErrorContextNodeSet: - * @output: a FILE * for the output - * @obj: the xmlNodeSetPtr to display - * - * Quick display of a NodeSet - */ -void -xmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) { - int i; - - if (output == NULL) output = xmlGenericErrorContext; - if (obj == NULL) { - fprintf(output, "NodeSet == NULL !\n"); - return; - } - if (obj->nodeNr == 0) { - fprintf(output, "NodeSet is empty\n"); - return; - } - if (obj->nodeTab == NULL) { - fprintf(output, " nodeTab == NULL !\n"); - return; - } - for (i = 0; i < obj->nodeNr; i++) { - if (obj->nodeTab[i] == NULL) { - fprintf(output, " NULL !\n"); - return; - } - if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) || - (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE)) - fprintf(output, " /"); - else if (obj->nodeTab[i]->name == NULL) - fprintf(output, " noname!"); - else fprintf(output, " %s", obj->nodeTab[i]->name); - } - fprintf(output, "\n"); -} -#endif - /** * xmlXPathNewNodeSet: * @val: the NodePtr value @@ -4281,9 +3675,6 @@ xmlXPathNewNodeSet(xmlNodePtr val) { /* TODO: Check memory error. */ ret->nodesetval = xmlXPathNodeSetCreate(val); /* @@ with_ns to check whether namespace nodes should be looked at @@ */ -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET); -#endif return(ret); }
@@ -4310,9 +3701,6 @@ xmlXPathNewValueTree(xmlNodePtr val) { ret->boolval = 1; ret->user = (void *) val; ret->nodesetval = xmlXPathNodeSetCreate(val); -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_XSLT_TREE); -#endif return(ret); }
@@ -4372,9 +3760,6 @@ xmlXPathWrapNodeSet(xmlNodeSetPtr val) { memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_NODESET; ret->nodesetval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_NODESET); -#endif return(ret); }
@@ -4388,9 +3773,6 @@ xmlXPathWrapNodeSet(xmlNodeSetPtr val) { void xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) { if (obj == NULL) return; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageReleased(NULL, obj->type); -#endif xmlFree(obj); }
@@ -5199,9 +4581,6 @@ xmlXPathNewFloat(double val) { memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_NUMBER; ret->floatval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_NUMBER); -#endif return(ret); }
@@ -5225,9 +4604,6 @@ xmlXPathNewBoolean(int val) { memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_BOOLEAN; ret->boolval = (val != 0); -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_BOOLEAN); -#endif return(ret); }
@@ -5257,9 +4633,6 @@ xmlXPathNewString(const xmlChar *val) { xmlFree(ret); return(NULL); } -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING); -#endif return(ret); }
@@ -5286,9 +4659,6 @@ xmlXPathWrapString (xmlChar *val) { memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_STRING; ret->stringval = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING); -#endif return(ret); }
@@ -5338,9 +4708,6 @@ xmlXPathWrapExternal (void *val) { memset(ret, 0 , sizeof(xmlXPathObject)); ret->type = XPATH_USERS; ret->user = val; -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, XPATH_USERS); -#endif return(ret); }
@@ -5365,9 +4732,6 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) { return(NULL); } memcpy(ret, val , sizeof(xmlXPathObject)); -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageRequested(NULL, val->type); -#endif switch (val->type) { case XPATH_BOOLEAN: case XPATH_NUMBER: @@ -5475,9 +4839,6 @@ xmlXPathFreeObject(xmlXPathObjectPtr obj) { if (obj->stringval != NULL) xmlFree(obj->stringval); } -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageReleased(NULL, obj->type); -#endif xmlFree(obj); }
@@ -5576,11 +4937,6 @@ xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj) goto free_obj;
obj_cached: - -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageReleased(ctxt, obj->type); -#endif - if (obj->nodesetval != NULL) { xmlNodeSetPtr tmpset = obj->nodesetval;
@@ -5621,9 +4977,6 @@ free_obj: */ if (obj->nodesetval != NULL) xmlXPathFreeNodeSet(obj->nodesetval); -#ifdef XP_DEBUG_OBJ_USAGE - xmlXPathDebugObjUsageReleased(NULL, obj->type); -#endif xmlFree(obj); } return; @@ -5740,9 +5093,6 @@ xmlXPathCastToString(xmlXPathObjectPtr val) { return(xmlStrdup((const xmlChar *) "")); switch (val->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, "String: undefined\n"); -#endif ret = xmlStrdup((const xmlChar *) ""); break; case XPATH_NODESET: @@ -5789,9 +5139,6 @@ xmlXPathConvertString(xmlXPathObjectPtr val) {
switch (val->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n"); -#endif break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -5909,9 +5256,6 @@ xmlXPathCastToNumber(xmlXPathObjectPtr val) { return(xmlXPathNAN); switch (val->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n"); -#endif ret = xmlXPathNAN; break; case XPATH_NODESET: @@ -6023,9 +5367,6 @@ xmlXPathCastToBoolean (xmlXPathObjectPtr val) { return(0); switch (val->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n"); -#endif ret = 0; break; case XPATH_NODESET: @@ -6382,11 +5723,12 @@ xmlXPathNodeValHash(xmlNodePtr node) { /* * Skip to next node */ - if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) { - if (tmp->children->type != XML_ENTITY_DECL) { - tmp = tmp->children; - continue; - } + if ((tmp->children != NULL) && + (tmp->type != XML_DTD_NODE) && + (tmp->type != XML_ENTITY_REF_NODE) && + (tmp->children->type != XML_ENTITY_DECL)) { + tmp = tmp->children; + continue; } if (tmp == node) break; @@ -6946,25 +6288,12 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, */ switch (arg1->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "Equal: undefined\n"); -#endif break; case XPATH_BOOLEAN: switch (arg2->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "Equal: undefined\n"); -#endif break; case XPATH_BOOLEAN: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "Equal: %d boolean %d \n", - arg1->boolval, arg2->boolval); -#endif ret = (arg1->boolval == arg2->boolval); break; case XPATH_NUMBER: @@ -6994,10 +6323,6 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, case XPATH_NUMBER: switch (arg2->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "Equal: undefined\n"); -#endif break; case XPATH_BOOLEAN: ret = (arg2->boolval== @@ -7055,10 +6380,6 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt, case XPATH_STRING: switch (arg2->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "Equal: undefined\n"); -#endif break; case XPATH_BOOLEAN: if ((arg1->stringval == NULL) || @@ -7159,10 +6480,6 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { }
if (arg1 == arg2) { -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "Equal: by pointer\n"); -#endif xmlXPathFreeObject(arg1); return(1); } @@ -7182,10 +6499,6 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { } switch (arg2->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "Equal: undefined\n"); -#endif break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -7246,10 +6559,6 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { }
if (arg1 == arg2) { -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "NotEqual: by pointer\n"); -#endif xmlXPathReleaseObject(ctxt->context, arg1); return(0); } @@ -7269,10 +6578,6 @@ xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) { } switch (arg2->type) { case XPATH_UNDEFINED: -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "NotEqual: undefined\n"); -#endif break; case XPATH_NODESET: case XPATH_XSLT_TREE: @@ -8464,10 +7769,6 @@ xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) { valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) ctxt->context->contextSize)); -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, - "last() : %d\n", ctxt->context->contextSize); -#endif } else { XP_ERROR(XPATH_INVALID_CTXT_SIZE); } @@ -8491,10 +7792,6 @@ xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) { valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) ctxt->context->proximityPosition)); -#ifdef DEBUG_EXPR - xmlGenericError(xmlGenericErrorContext, "position() : %d\n", - ctxt->context->proximityPosition); -#endif } else { XP_ERROR(XPATH_INVALID_CTXT_POSITION); } @@ -10339,14 +9636,6 @@ xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) { XP_ERROR(XPATH_EXPR_ERROR); } SKIP_BLANKS; -#ifdef DEBUG_EXPR - if (prefix == NULL) - xmlGenericError(xmlGenericErrorContext, "Calling function %s\n", - name); - else - xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n", - prefix, name); -#endif
if (CUR != '(') { xmlFree(name); @@ -10563,10 +9852,6 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { SKIP_BLANKS; name = xmlXPathScanName(ctxt); if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) { -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "PathExpr: Axis\n"); -#endif lc = 1; xmlFree(name); } else if (name != NULL) { @@ -10576,29 +9861,17 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { while (NXT(len) != 0) { if (NXT(len) == '/') { /* element name */ -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "PathExpr: AbbrRelLocation\n"); -#endif lc = 1; break; } else if (IS_BLANK_CH(NXT(len))) { /* ignore blanks */ ; } else if (NXT(len) == ':') { -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "PathExpr: AbbrRelLocation\n"); -#endif lc = 1; break; } else if ((NXT(len) == '(')) { /* Node Type or Function */ if (xmlXPathIsNodeType(name)) { -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "PathExpr: Type search\n"); -#endif lc = 1; #ifdef LIBXML_XPTR_LOCS_ENABLED } else if (ctxt->xptr && @@ -10606,19 +9879,11 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { lc = 1; #endif } else { -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "PathExpr: function call\n"); -#endif lc = 0; } break; } else if ((NXT(len) == '[')) { /* element name */ -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "PathExpr: AbbrRelLocation\n"); -#endif lc = 1; break; } else if ((NXT(len) == '<') || (NXT(len) == '>') || @@ -10632,10 +9897,6 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { len++; } if (NXT(len) == 0) { -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "PathExpr: AbbrRelLocation\n"); -#endif /* element name */ lc = 1; } @@ -11346,20 +10607,6 @@ xmlXPathCompStep(xmlXPathParserContextPtr ctxt) { xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR); } } -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "Basis : computing new set\n"); -#endif - -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, "Basis : "); - if (ctxt->value == NULL) - xmlGenericError(xmlGenericErrorContext, "no value\n"); - else if (ctxt->value->nodesetval == NULL) - xmlGenericError(xmlGenericErrorContext, "Empty\n"); - else - xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval); -#endif
#ifdef LIBXML_XPTR_LOCS_ENABLED eval_predicates: @@ -11383,16 +10630,6 @@ eval_predicates: xmlFree(name); } } -#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, "Step : "); - if (ctxt->value == NULL) - xmlGenericError(xmlGenericErrorContext, "no value\n"); - else if (ctxt->value->nodesetval == NULL) - xmlGenericError(xmlGenericErrorContext, "Empty\n"); - else - xmlGenericErrorContextNodeSet(xmlGenericErrorContext, - ctxt->value->nodesetval); -#endif }
/** @@ -11494,93 +10731,6 @@ xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) { static int xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
-#ifdef DEBUG_STEP -static void -xmlXPathDebugDumpStepAxis(xmlXPathStepOpPtr op, - int nbNodes) -{ - xmlGenericError(xmlGenericErrorContext, "new step : "); - switch (op->value) { - case AXIS_ANCESTOR: - xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' "); - break; - case AXIS_ANCESTOR_OR_SELF: - xmlGenericError(xmlGenericErrorContext, - "axis 'ancestors-or-self' "); - break; - case AXIS_ATTRIBUTE: - xmlGenericError(xmlGenericErrorContext, "axis 'attributes' "); - break; - case AXIS_CHILD: - xmlGenericError(xmlGenericErrorContext, "axis 'child' "); - break; - case AXIS_DESCENDANT: - xmlGenericError(xmlGenericErrorContext, "axis 'descendant' "); - break; - case AXIS_DESCENDANT_OR_SELF: - xmlGenericError(xmlGenericErrorContext, - "axis 'descendant-or-self' "); - break; - case AXIS_FOLLOWING: - xmlGenericError(xmlGenericErrorContext, "axis 'following' "); - break; - case AXIS_FOLLOWING_SIBLING: - xmlGenericError(xmlGenericErrorContext, - "axis 'following-siblings' "); - break; - case AXIS_NAMESPACE: - xmlGenericError(xmlGenericErrorContext, "axis 'namespace' "); - break; - case AXIS_PARENT: - xmlGenericError(xmlGenericErrorContext, "axis 'parent' "); - break; - case AXIS_PRECEDING: - xmlGenericError(xmlGenericErrorContext, "axis 'preceding' "); - break; - case AXIS_PRECEDING_SIBLING: - xmlGenericError(xmlGenericErrorContext, - "axis 'preceding-sibling' "); - break; - case AXIS_SELF: - xmlGenericError(xmlGenericErrorContext, "axis 'self' "); - break; - } - xmlGenericError(xmlGenericErrorContext, - " context contains %d nodes\n", nbNodes); - switch (op->value2) { - case NODE_TEST_NONE: - xmlGenericError(xmlGenericErrorContext, - " searching for none !!!\n"); - break; - case NODE_TEST_TYPE: - xmlGenericError(xmlGenericErrorContext, - " searching for type %d\n", op->value3); - break; - case NODE_TEST_PI: - xmlGenericError(xmlGenericErrorContext, - " searching for PI !!!\n"); - break; - case NODE_TEST_ALL: - xmlGenericError(xmlGenericErrorContext, - " searching for *\n"); - break; - case NODE_TEST_NS: - xmlGenericError(xmlGenericErrorContext, - " searching for namespace %s\n", - op->value5); - break; - case NODE_TEST_NAME: - xmlGenericError(xmlGenericErrorContext, - " searching for name %s\n", op->value5); - if (op->value4) - xmlGenericError(xmlGenericErrorContext, - " with namespace %s\n", op->value4); - break; - } - xmlGenericError(xmlGenericErrorContext, "Testing : "); -} -#endif /* DEBUG_STEP */ - /** * xmlXPathNodeSetFilter: * @ctxt: the XPath Parser context @@ -11971,9 +11121,6 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, const xmlChar *name = op->value5; const xmlChar *URI = NULL;
-#ifdef DEBUG_STEP - int nbMatches = 0, prevMatches = 0; -#endif int total = 0, hasNsNodes = 0; /* The popped object holding the context nodes */ xmlXPathObjectPtr obj; @@ -12098,11 +11245,6 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, break; }
-#ifdef DEBUG_STEP - xmlXPathDebugDumpStepAxis(op, - (obj->nodesetval != NULL) ? obj->nodesetval->nodeNr : 0); -#endif - if (next == NULL) { xmlXPathReleaseObject(xpctxt, obj); return(0); @@ -12236,10 +11378,6 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
total++;
-#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, " %s", cur->name); -#endif - switch (test) { case NODE_TEST_NONE: total = 0; @@ -12426,11 +11564,6 @@ first_hit: /* ---------------------------------------------------------- */ outSeq = mergeAndClear(outSeq, seq); break;
-#ifdef DEBUG_STEP - if (seq != NULL) - nbMatches += seq->nodeNr; -#endif - apply_predicates: /* --------------------------------------------------- */ if (ctxt->error != XPATH_EXPRESSION_OK) goto error; @@ -12542,12 +11675,6 @@ error: xpctxt->tmpNsList = NULL; }
-#ifdef DEBUG_STEP - xmlGenericError(xmlGenericErrorContext, - "\nExamined %d nodes, found %d nodes at that step\n", - total, nbMatches); -#endif - return(total); }
@@ -14245,10 +13372,6 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
if (comp != NULL) { comp->expr = xmlStrdup(str); -#ifdef DEBUG_EVAL_COUNTS - comp->string = xmlStrdup(str); - comp->nb = 0; -#endif } return(comp); } @@ -14305,13 +13428,6 @@ xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp, xmlXPathDisableOptimizer = 1; #endif
-#ifdef DEBUG_EVAL_COUNTS - comp->nb++; - if ((comp->string != NULL) && (comp->nb > 100)) { - fprintf(stderr, "100 x %s\n", comp->string); - comp->nb = 0; - } -#endif pctxt = xmlXPathCompParserContext(comp, ctxt); if (pctxt == NULL) return(-1); diff --git a/libs/xml2/xpointer.c b/libs/xml2/xpointer.c index d8c18d7afb0..8f38dd103fa 100644 --- a/libs/xml2/xpointer.c +++ b/libs/xml2/xpointer.c @@ -38,20 +38,12 @@ #include <libxml/xpath.h> #include <libxml/xpathInternals.h> #include <libxml/xmlerror.h> -#include <libxml/globals.h>
#ifdef LIBXML_XPTR_ENABLED
/* Add support of the xmlns() xpointer scheme to initialize the namespaces */ #define XPTR_XMLNS_SCHEME
-/* #define DEBUG_RANGES */ -#ifdef DEBUG_RANGES -#ifdef LIBXML_DEBUG_ENABLED -#include <libxml/debugXML.h> -#endif -#endif - #include "private/error.h"
#define TODO \ @@ -705,10 +697,6 @@ xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val) { if (cur->locTab[i] == val) break;
if (i >= cur->locNr) { -#ifdef DEBUG - xmlGenericError(xmlGenericErrorContext, - "xmlXPtrLocationSetDel: Range wasn't found in RangeList\n"); -#endif return; } cur->locNr--; @@ -1248,7 +1236,6 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) { ctxt->valueNr = 0; ctxt->valueMax = 10; ctxt->value = NULL; - ctxt->valueFrame = 0; } SKIP_BLANKS; if (CUR == '/') { @@ -2425,13 +2412,6 @@ xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex, if (len >= pos + stringlen) { match = (!xmlStrncmp(&cur->content[pos], string, stringlen)); if (match) { -#ifdef DEBUG_RANGES - xmlGenericError(xmlGenericErrorContext, - "found range %d bytes at index %d of ->", - stringlen, pos + 1); - xmlDebugDumpString(stdout, cur->content); - xmlGenericError(xmlGenericErrorContext, "\n"); -#endif *end = cur; *endindex = pos + stringlen; return(1); @@ -2442,13 +2422,6 @@ xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex, int sub = len - pos; match = (!xmlStrncmp(&cur->content[pos], string, sub)); if (match) { -#ifdef DEBUG_RANGES - xmlGenericError(xmlGenericErrorContext, - "found subrange %d bytes at index %d of ->", - sub, pos + 1); - xmlDebugDumpString(stdout, cur->content); - xmlGenericError(xmlGenericErrorContext, "\n"); -#endif string = &string[sub]; stringlen -= sub; } else { @@ -2508,13 +2481,6 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex, str = xmlStrchr(&cur->content[pos], first); if (str != NULL) { pos = (str - (xmlChar *)(cur->content)); -#ifdef DEBUG_RANGES - xmlGenericError(xmlGenericErrorContext, - "found '%c' at index %d of ->", - first, pos + 1); - xmlDebugDumpString(stdout, cur->content); - xmlGenericError(xmlGenericErrorContext, "\n"); -#endif if (xmlXPtrMatchString(string, cur, pos + 1, end, endindex)) { *start = cur; @@ -2531,13 +2497,6 @@ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex, * character of the string-value and after the final * character. */ -#ifdef DEBUG_RANGES - xmlGenericError(xmlGenericErrorContext, - "found '' at index %d of ->", - pos + 1); - xmlDebugDumpString(stdout, cur->content); - xmlGenericError(xmlGenericErrorContext, "\n"); -#endif *start = cur; *startindex = pos + 1; *end = cur; @@ -2787,25 +2746,12 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { * the list of location set corresponding to that search */ for (i = 0;i < oldset->locNr;i++) { -#ifdef DEBUG_RANGES - xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0); -#endif
xmlXPtrGetStartPoint(oldset->locTab[i], &start, &startindex); xmlXPtrGetEndPoint(oldset->locTab[i], &end, &endindex); xmlXPtrAdvanceChar(&start, &startindex, 0); xmlXPtrGetLastChar(&end, &endindex);
-#ifdef DEBUG_RANGES - xmlGenericError(xmlGenericErrorContext, - "from index %d of ->", startindex); - xmlDebugDumpString(stdout, start->content); - xmlGenericError(xmlGenericErrorContext, "\n"); - xmlGenericError(xmlGenericErrorContext, - "to index %d of ->", endindex); - xmlDebugDumpString(stdout, end->content); - xmlGenericError(xmlGenericErrorContext, "\n"); -#endif do { fend = end; fendindex = endindex; @@ -2971,4 +2917,3 @@ xmlXPtrEvalRangePredicate(xmlXPathParserContextPtr ctxt) { #endif /* LIBXML_XPTR_LOCS_ENABLED */
#endif -
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149020
Your paranoid android.
=== debian11 (32 bit report) ===
msxml3: schema.c:1300: Test failed: Unexpected hr 0x80004005. schema.c:1318: Test failed: Unexpected hr 0x1. schema.c:1321: Test failed: Unexpected hr 0. schema.c:1324: Test failed: Unexpected value c00ce224 : (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testBase64']/Value/base64Data": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testHex']/Value/hexData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testBool']/Value/boolData": got variant type 8 schema.c:1385: Test failed: got ffff9b4c schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testDate']/Value/dateData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testDateTime']/Value/dateTimeData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testDateTimeTz']/Value/dateTimeTzData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testFixed']/Value/fixedData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testFloat']/Value/floatData": got variant type 8 schema.c:1410: Test failed: got 0.000000 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testI1']/Value/i1Data": got variant type 8 schema.c:1388: Test failed: got -116 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testI2']/Value/i2Data": got variant type 8 schema.c:1391: Test failed: got -25684 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testI4']/Value/i4Data": got variant type 8 schema.c:1400: Test failed: got 2420980 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testInt']/Value/intData": got variant type 8 schema.c:1395: Test failed: got 2399180 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testR4']/Value/r4Data": got variant type 8 schema.c:1406: Test failed: got 0.000000 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testR8']/Value/r8Data": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testTime']/Value/timeData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testTimeTz']/Value/timeTzData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testU1']/Value/u1Data": got variant type 8 schema.c:1416: Test failed: got 0c schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testU2']/Value/u2Data": got variant type 8 schema.c:1419: Test failed: got 9c2c schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testU4']/Value/u4Data": got variant type 8 schema.c:1422: Test failed: got 0x2488bc schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null)
=== debian11b (64 bit WoW report) ===
msxml3: schema.c:1300: Test failed: Unexpected hr 0x80004005. schema.c:1318: Test failed: Unexpected hr 0x1. schema.c:1321: Test failed: Unexpected hr 0. schema.c:1324: Test failed: Unexpected value c00ce224 : (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testBase64']/Value/base64Data": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testHex']/Value/hexData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testBool']/Value/boolData": got variant type 8 schema.c:1385: Test failed: got ffffe008 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testDate']/Value/dateData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testDateTime']/Value/dateTimeData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testDateTimeTz']/Value/dateTimeTzData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testFixed']/Value/fixedData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testFloat']/Value/floatData": got variant type 8 schema.c:1410: Test failed: got 0.000000 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testI1']/Value/i1Data": got variant type 8 schema.c:1388: Test failed: got -104 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testI2']/Value/i2Data": got variant type 8 schema.c:1391: Test failed: got -7992 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testI4']/Value/i4Data": got variant type 8 schema.c:1400: Test failed: got 2416888 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testInt']/Value/intData": got variant type 8 schema.c:1395: Test failed: got 2416984 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testR4']/Value/r4Data": got variant type 8 schema.c:1406: Test failed: got 0.000000 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testR8']/Value/r8Data": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testTime']/Value/timeData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testTimeTz']/Value/timeTzData": got variant type 8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testU1']/Value/u1Data": got variant type 8 schema.c:1416: Test failed: got 98 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testU2']/Value/u2Data": got variant type 8 schema.c:1419: Test failed: got 74c8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1380: Test failed: L"//Property[Name!text()='testU4']/Value/u4Data": got variant type 8 schema.c:1422: Test failed: got 0x13874f8 schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null) schema.c:1364: Test failed: Unexpected hr 0x1. schema.c:1365: Test failed: got type 1 schema.c:1366: Test failed: got (null)
This breaks msxml3/tests/schema.c tests for me.
Yes, the schema fails to load. Any thoughts on fixing that?
So far I can tell that it's caused by changes to xmlregexp.c. Reverting its diff works, but we don't want that obviously.
Apparently there was a bug in the validator that has been fixed in 2.11.4, cf. https://gitlab.gnome.org/GNOME/libxml2/-/issues/573
So I guess it means that the schema should have failed also in previous versions?
I think validation is a separate thing. Currently failing test loads a schema that references what we have as datatype.xsd, and that datatype.xsd fails to load.
I see some reports of broken schemas after upgrading to 2.12.0, we currently have 2.11.7 so it matches in that sense. The supposed change is https://gitlab.gnome.org/GNOME/libxml2/-/commit/a06eaa6119ca5b296b8105dc8c9a.... There are only two patterns in our xsd, but I don't know exactly what's going on there.
Good news is that this diff helps, bad news is I don't know why it helps. I only found about this attribute from docs, when I was trying things at random.
[schema.diff](/uploads/7b86113848034541c9b999c35b377e20/schema.diff)
That's good enough for me ;-)