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 -