aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsetser <setser@yandex-team.ru>2022-05-09 00:13:37 +0300
committersetser <setser@yandex-team.ru>2022-05-09 00:13:37 +0300
commite87e3fc8d0e04eb7ba3eee221bb91613b527ad85 (patch)
tree5279c128bdbdf902b9a08d9fae8e55b91910a553
parentf4f3e4024a1f32bd0bc3fa20239025a1b179e42d (diff)
downloadydb-e87e3fc8d0e04eb7ba3eee221bb91613b527ad85.tar.gz
Update libxml to 2.9.13
ref:f572491d236694e847142c36f0f5546c649e05d7
-rw-r--r--contrib/libs/libxml/.yandex_meta/devtools.licenses.report20
-rw-r--r--contrib/libs/libxml/.yandex_meta/licenses.list.txt14
-rw-r--r--contrib/libs/libxml/AUTHORS5
-rw-r--r--contrib/libs/libxml/HTMLparser.c1208
-rw-r--r--contrib/libs/libxml/HTMLtree.c511
-rw-r--r--contrib/libs/libxml/README.md121
-rw-r--r--contrib/libs/libxml/SAX2.c205
-rw-r--r--contrib/libs/libxml/TODO10
-rw-r--r--contrib/libs/libxml/buf.c16
-rw-r--r--contrib/libs/libxml/c14n.c20
-rw-r--r--contrib/libs/libxml/catalog.c20
-rw-r--r--contrib/libs/libxml/config-linux.h40
-rw-r--r--contrib/libs/libxml/debugXML.c10
-rw-r--r--contrib/libs/libxml/dict.c4
-rw-r--r--contrib/libs/libxml/elfgcchack.h12
-rw-r--r--contrib/libs/libxml/encoding.c132
-rw-r--r--contrib/libs/libxml/entities.c58
-rw-r--r--contrib/libs/libxml/error.c26
-rw-r--r--contrib/libs/libxml/globals.c2
-rw-r--r--contrib/libs/libxml/hash.c24
-rw-r--r--contrib/libs/libxml/include/libxml/c14n.h10
-rw-r--r--contrib/libs/libxml/include/libxml/parser.h16
-rw-r--r--contrib/libs/libxml/include/libxml/tree.h6
-rw-r--r--contrib/libs/libxml/include/libxml/xmlIO.h2
-rw-r--r--contrib/libs/libxml/include/libxml/xmlexports.h154
-rw-r--r--contrib/libs/libxml/include/libxml/xmlschemas.h2
-rw-r--r--contrib/libs/libxml/include/libxml/xmlversion.h14
-rw-r--r--contrib/libs/libxml/include/libxml/xpath.h4
-rw-r--r--contrib/libs/libxml/libxml2.syms7
-rw-r--r--contrib/libs/libxml/list.c2
-rw-r--r--contrib/libs/libxml/nanoftp.c29
-rw-r--r--contrib/libs/libxml/nanohttp.c14
-rw-r--r--contrib/libs/libxml/parser.c657
-rw-r--r--contrib/libs/libxml/parserInternals.c21
-rw-r--r--contrib/libs/libxml/relaxng.c14
-rw-r--r--contrib/libs/libxml/schematron.c4
-rw-r--r--contrib/libs/libxml/threads.c5
-rw-r--r--contrib/libs/libxml/tree.c110
-rw-r--r--contrib/libs/libxml/uri.c46
-rw-r--r--contrib/libs/libxml/valid.c155
-rw-r--r--contrib/libs/libxml/xinclude.c235
-rw-r--r--contrib/libs/libxml/xmlIO.c41
-rw-r--r--contrib/libs/libxml/xmlmemory.c4
-rw-r--r--contrib/libs/libxml/xmlreader.c112
-rw-r--r--contrib/libs/libxml/xmlregexp.c146
-rw-r--r--contrib/libs/libxml/xmlsave.c1154
-rw-r--r--contrib/libs/libxml/xmlschemas.c536
-rw-r--r--contrib/libs/libxml/xmlschemastypes.c229
-rw-r--r--contrib/libs/libxml/xmlstring.c94
-rw-r--r--contrib/libs/libxml/xpath.c184
-rw-r--r--contrib/libs/libxml/xpointer.c129
51 files changed, 3669 insertions, 2925 deletions
diff --git a/contrib/libs/libxml/.yandex_meta/devtools.licenses.report b/contrib/libs/libxml/.yandex_meta/devtools.licenses.report
index 50819d5509..e79eee80a1 100644
--- a/contrib/libs/libxml/.yandex_meta/devtools.licenses.report
+++ b/contrib/libs/libxml/.yandex_meta/devtools.licenses.report
@@ -54,13 +54,25 @@ FILE_INCLUDE Copyright found in files: xpath.c at line 11
Files with this license:
xpath.c [11:11]
-KEEP Mit-Veillard-Variant 1d17653acef0ece203567b31819d603d
+KEEP MIT 4138c95edb8e207b0c56cfaf284bd9fd
+BELONGS ya.make
+FILE_INCLUDE Copyright found in files: README.md at line 18
+ License text:
+ This code is released under the MIT License, see the Copyright file.
+ Scancode info:
+ Original SPDX id: MIT
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT
+ Files with this license:
+ README.md [18:18]
+
+KEEP Mit-Veillard-Variant 43589b25dd99faeb77ea58a7ea046a1f
BELONGS ya.make
-FILE_INCLUDE AUTHORS found in files: dict.c at line 13, hash.c at line 14, list.c at line 12
Note: matched license text is too long. Read it in the source files.
Scancode info:
Original SPDX id: LicenseRef-scancode-mit-veillard-variant
- Score : 100.00
+ Score : 98.57
Match type : TEXT
Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/mit-veillard-variant.LICENSE, https://raw.githubusercontent.com/GNOME/libxml2/4c2e7c651f6c2f0d1a74f350cbda95f7df3e7017/hash.c
Files with this license:
@@ -70,7 +82,6 @@ FILE_INCLUDE AUTHORS found in files: dict.c at line 13, hash.c at line 14, list.
KEEP MIT 4372cff0d21afdacf852b4c78b18140d
BELONGS ya.make
-FILE_INCLUDE AUTHORS found in files: timsort.h at line 28
Note: matched license text is too long. Read it in the source files.
Scancode info:
Original SPDX id: MIT
@@ -155,7 +166,6 @@ FILE_INCLUDE Copyright found in files: tree.c at line 7
KEEP MIT 78d4c8870de0cf03b21661637338ced8
BELONGS ya.make
-FILE_INCLUDE AUTHORS found in files: COPYING at line 20, Copyright at line 20
Note: matched license text is too long. Read it in the source files.
Scancode info:
Original SPDX id: MIT
diff --git a/contrib/libs/libxml/.yandex_meta/licenses.list.txt b/contrib/libs/libxml/.yandex_meta/licenses.list.txt
index f1e1371f4e..9c201607b0 100644
--- a/contrib/libs/libxml/.yandex_meta/licenses.list.txt
+++ b/contrib/libs/libxml/.yandex_meta/licenses.list.txt
@@ -20,14 +20,6 @@
Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
-====================File: AUTHORS====================
-Daniel Veillard <daniel@veillard.com>
-Bjorn Reese <breese@users.sourceforge.net>
-William Brack <wbrack@mmm.com.hk>
-Igor Zlatkovic <igor@zlatkovic.com> for the Windows port
-Aleksey Sanin <aleksey@aleksey.com>
-
-
====================File: Copyright====================
Except where otherwise noted in the source code (e.g. the files hash.c,
list.c and the trio files, which are covered by a similar licence but
@@ -113,6 +105,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+====================MIT====================
+This code is released under the MIT License, see the Copyright file.
+
+
====================Mit-Veillard-Variant====================
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -120,5 +116,5 @@ THE SOFTWARE.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
diff --git a/contrib/libs/libxml/AUTHORS b/contrib/libs/libxml/AUTHORS
deleted file mode 100644
index cf2e9a6fad..0000000000
--- a/contrib/libs/libxml/AUTHORS
+++ /dev/null
@@ -1,5 +0,0 @@
-Daniel Veillard <daniel@veillard.com>
-Bjorn Reese <breese@users.sourceforge.net>
-William Brack <wbrack@mmm.com.hk>
-Igor Zlatkovic <igor@zlatkovic.com> for the Windows port
-Aleksey Sanin <aleksey@aleksey.com>
diff --git a/contrib/libs/libxml/HTMLparser.c b/contrib/libs/libxml/HTMLparser.c
index 7b6d68961c..3e8a165740 100644
--- a/contrib/libs/libxml/HTMLparser.c
+++ b/contrib/libs/libxml/HTMLparser.c
@@ -69,7 +69,7 @@ static void htmlParseComment(htmlParserCtxtPtr ctxt);
/**
* htmlErrMemory:
* @ctxt: an HTML parser context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -296,7 +296,7 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt)
#define UPPER (toupper(*ctxt->input->cur))
-#define SKIP(val) ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val)
+#define SKIP(val) ctxt->input->cur += (val),ctxt->input->col+=(val)
#define NXT(val) ctxt->input->cur[(val)]
@@ -330,7 +330,7 @@ htmlNodeInfoPop(htmlParserCtxtPtr ctxt)
if (*(ctxt->input->cur) == '\n') { \
ctxt->input->line++; ctxt->input->col = 1; \
} else ctxt->input->col++; \
- ctxt->token = 0; ctxt->input->cur += l; ctxt->nbChars++; \
+ ctxt->token = 0; ctxt->input->cur += l; \
} while (0)
/************
@@ -414,6 +414,10 @@ htmlFindEncoding(xmlParserCtxtPtr ctxt) {
static int
htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
+ const unsigned char *cur;
+ unsigned char c;
+ unsigned int val;
+
if (ctxt->instate == XML_PARSER_EOF)
return(0);
@@ -421,99 +425,29 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
*len = 0;
return(ctxt->token);
}
- 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;
-
- c = *cur;
- if (c & 0x80) {
- if (cur[1] == 0) {
- xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
- cur = ctxt->input->cur;
- }
- if ((cur[1] & 0xc0) != 0x80)
- goto encoding_error;
- if ((c & 0xe0) == 0xe0) {
+ if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
+ xmlChar * guess;
+ xmlCharEncodingHandlerPtr handler;
- if (cur[2] == 0) {
- xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
- cur = ctxt->input->cur;
- }
- if ((cur[2] & 0xc0) != 0x80)
- goto encoding_error;
- if ((c & 0xf0) == 0xf0) {
- if (cur[3] == 0) {
- xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
- cur = ctxt->input->cur;
- }
- 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)) {
- htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
- "Char 0x%X out of allowed range\n", val);
- }
- return(val);
- } else {
+ /*
+ * Assume it's a fixed length encoding (1) with
+ * a compatible encoding for the ASCII set, since
+ * HTML constructs only use < 128 chars
+ */
+ if ((int) *ctxt->input->cur < 0x80) {
+ *len = 1;
if ((*ctxt->input->cur == 0) &&
(ctxt->input->cur < ctxt->input->end)) {
- htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
- "Char 0x%X out of allowed range\n", 0);
- *len = 1;
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Char 0x%X out of allowed range\n", 0);
return(' ');
}
- /* 1-byte code */
- *len = 1;
- return((int) *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 ((int) *ctxt->input->cur < 0x80)
- return((int) *ctxt->input->cur);
-
- /*
- * Humm this is bad, do an automatic flow conversion
- */
- {
- xmlChar * guess;
- xmlCharEncodingHandlerPtr handler;
+ return((int) *ctxt->input->cur);
+ }
+ /*
+ * Humm this is bad, do an automatic flow conversion
+ */
guess = htmlFindEncoding(ctxt);
if (guess == NULL) {
xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
@@ -523,7 +457,12 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
ctxt->input->encoding = guess;
handler = xmlFindCharEncodingHandler((const char *) guess);
if (handler != NULL) {
- xmlSwitchToEncoding(ctxt, handler);
+ /*
+ * Don't use UTF-8 encoder which isn't required and
+ * can produce invalid UTF-8.
+ */
+ if (!xmlStrEqual(BAD_CAST handler->name, BAD_CAST "UTF-8"))
+ xmlSwitchToEncoding(ctxt, handler);
} else {
htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
"Unsupported encoding %s", guess, NULL);
@@ -532,7 +471,86 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
ctxt->charset = XML_CHAR_ENCODING_UTF8;
}
- return(xmlCurrentChar(ctxt, len));
+ /*
+ * 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) {
+ if ((c & 0x40) == 0)
+ goto encoding_error;
+ if (cur[1] == 0) {
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ cur = ctxt->input->cur;
+ }
+ if ((cur[1] & 0xc0) != 0x80)
+ goto encoding_error;
+ if ((c & 0xe0) == 0xe0) {
+
+ if (cur[2] == 0) {
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ cur = ctxt->input->cur;
+ }
+ if ((cur[2] & 0xc0) != 0x80)
+ goto encoding_error;
+ if ((c & 0xf0) == 0xf0) {
+ if (cur[3] == 0) {
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ cur = ctxt->input->cur;
+ }
+ 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)) {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Char 0x%X out of allowed range\n", val);
+ }
+ return(val);
+ } else {
+ if ((*ctxt->input->cur == 0) &&
+ (ctxt->input->cur < ctxt->input->end)) {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Char 0x%X out of allowed range\n", 0);
+ *len = 1;
+ return(' ');
+ }
+ /* 1-byte code */
+ *len = 1;
+ return((int) *ctxt->input->cur);
+ }
encoding_error:
/*
@@ -557,7 +575,16 @@ encoding_error:
BAD_CAST buffer, NULL);
}
- ctxt->charset = XML_CHAR_ENCODING_8859_1;
+ /*
+ * 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))
+ xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1);
*len = 1;
return((int) *ctxt->input->cur);
}
@@ -584,7 +611,6 @@ htmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
ctxt->input->line++; ctxt->input->col = 1;
} else ctxt->input->col++;
ctxt->input->cur++;
- ctxt->nbChars++;
if (*ctxt->input->cur == 0)
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
}
@@ -1046,102 +1072,266 @@ html40ElementTable[] = {
}
};
+typedef struct {
+ const char *oldTag;
+ const char *newTag;
+} htmlStartCloseEntry;
+
/*
* start tags that imply the end of current element
*/
-static const char * const htmlStartClose[] = {
-"form", "form", "p", "hr", "h1", "h2", "h3", "h4", "h5", "h6",
- "dl", "ul", "ol", "menu", "dir", "address", "pre",
- "listing", "xmp", "head", NULL,
-"head", "p", NULL,
-"title", "p", NULL,
-"body", "head", "style", "link", "title", "p", NULL,
-"frameset", "head", "style", "link", "title", "p", NULL,
-"li", "p", "h1", "h2", "h3", "h4", "h5", "h6", "dl", "address",
- "pre", "listing", "xmp", "head", "li", NULL,
-"hr", "p", "head", NULL,
-"h1", "p", "head", NULL,
-"h2", "p", "head", NULL,
-"h3", "p", "head", NULL,
-"h4", "p", "head", NULL,
-"h5", "p", "head", NULL,
-"h6", "p", "head", NULL,
-"dir", "p", "head", NULL,
-"address", "p", "head", "ul", NULL,
-"pre", "p", "head", "ul", NULL,
-"listing", "p", "head", NULL,
-"xmp", "p", "head", NULL,
-"blockquote", "p", "head", NULL,
-"dl", "p", "dt", "menu", "dir", "address", "pre", "listing",
- "xmp", "head", NULL,
-"dt", "p", "menu", "dir", "address", "pre", "listing", "xmp",
- "head", "dd", NULL,
-"dd", "p", "menu", "dir", "address", "pre", "listing", "xmp",
- "head", "dt", NULL,
-"ul", "p", "head", "ol", "menu", "dir", "address", "pre",
- "listing", "xmp", NULL,
-"ol", "p", "head", "ul", NULL,
-"menu", "p", "head", "ul", NULL,
-"p", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", FONTSTYLE, NULL,
-"div", "p", "head", NULL,
-"noscript", "script", NULL,
-"center", "font", "b", "i", "p", "head", NULL,
-"a", "a", "head", NULL,
-"caption", "p", NULL,
-"colgroup", "caption", "colgroup", "col", "p", NULL,
-"col", "caption", "col", "p", NULL,
-"table", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", "pre",
- "listing", "xmp", "a", NULL,
-"th", "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL,
-"td", "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL,
-"tr", "th", "td", "tr", "caption", "col", "colgroup", "p", NULL,
-"thead", "caption", "col", "colgroup", NULL,
-"tfoot", "th", "td", "tr", "caption", "col", "colgroup", "thead",
- "tbody", "p", NULL,
-"tbody", "th", "td", "tr", "caption", "col", "colgroup", "thead",
- "tfoot", "tbody", "p", NULL,
-"optgroup", "option", NULL,
-"option", "option", NULL,
-"fieldset", "legend", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6",
- "pre", "listing", "xmp", "a", NULL,
-/* most tags in in FONTSTYLE, PHRASE and SPECIAL should close <head> */
-"tt", "head", NULL,
-"i", "head", NULL,
-"b", "head", NULL,
-"u", "head", NULL,
-"s", "head", NULL,
-"strike", "head", NULL,
-"big", "head", NULL,
-"small", "head", NULL,
-
-"em", "head", NULL,
-"strong", "head", NULL,
-"dfn", "head", NULL,
-"code", "head", NULL,
-"samp", "head", NULL,
-"kbd", "head", NULL,
-"var", "head", NULL,
-"cite", "head", NULL,
-"abbr", "head", NULL,
-"acronym", "head", NULL,
-
-/* "a" */
-"img", "head", NULL,
-/* "applet" */
-/* "embed" */
-/* "object" */
-"font", "head", NULL,
-/* "basefont" */
-"br", "head", NULL,
-/* "script" */
-"map", "head", NULL,
-"q", "head", NULL,
-"sub", "head", NULL,
-"sup", "head", NULL,
-"span", "head", NULL,
-"bdo", "head", NULL,
-"iframe", "head", NULL,
-NULL
+static const htmlStartCloseEntry htmlStartClose[] = {
+ { "a", "a" },
+ { "a", "fieldset" },
+ { "a", "table" },
+ { "a", "td" },
+ { "a", "th" },
+ { "address", "dd" },
+ { "address", "dl" },
+ { "address", "dt" },
+ { "address", "form" },
+ { "address", "li" },
+ { "address", "ul" },
+ { "b", "center" },
+ { "b", "p" },
+ { "b", "td" },
+ { "b", "th" },
+ { "big", "p" },
+ { "caption", "col" },
+ { "caption", "colgroup" },
+ { "caption", "tbody" },
+ { "caption", "tfoot" },
+ { "caption", "thead" },
+ { "caption", "tr" },
+ { "col", "col" },
+ { "col", "colgroup" },
+ { "col", "tbody" },
+ { "col", "tfoot" },
+ { "col", "thead" },
+ { "col", "tr" },
+ { "colgroup", "colgroup" },
+ { "colgroup", "tbody" },
+ { "colgroup", "tfoot" },
+ { "colgroup", "thead" },
+ { "colgroup", "tr" },
+ { "dd", "dt" },
+ { "dir", "dd" },
+ { "dir", "dl" },
+ { "dir", "dt" },
+ { "dir", "form" },
+ { "dir", "ul" },
+ { "dl", "form" },
+ { "dl", "li" },
+ { "dt", "dd" },
+ { "dt", "dl" },
+ { "font", "center" },
+ { "font", "td" },
+ { "font", "th" },
+ { "form", "form" },
+ { "h1", "fieldset" },
+ { "h1", "form" },
+ { "h1", "li" },
+ { "h1", "p" },
+ { "h1", "table" },
+ { "h2", "fieldset" },
+ { "h2", "form" },
+ { "h2", "li" },
+ { "h2", "p" },
+ { "h2", "table" },
+ { "h3", "fieldset" },
+ { "h3", "form" },
+ { "h3", "li" },
+ { "h3", "p" },
+ { "h3", "table" },
+ { "h4", "fieldset" },
+ { "h4", "form" },
+ { "h4", "li" },
+ { "h4", "p" },
+ { "h4", "table" },
+ { "h5", "fieldset" },
+ { "h5", "form" },
+ { "h5", "li" },
+ { "h5", "p" },
+ { "h5", "table" },
+ { "h6", "fieldset" },
+ { "h6", "form" },
+ { "h6", "li" },
+ { "h6", "p" },
+ { "h6", "table" },
+ { "head", "a" },
+ { "head", "abbr" },
+ { "head", "acronym" },
+ { "head", "address" },
+ { "head", "b" },
+ { "head", "bdo" },
+ { "head", "big" },
+ { "head", "blockquote" },
+ { "head", "body" },
+ { "head", "br" },
+ { "head", "center" },
+ { "head", "cite" },
+ { "head", "code" },
+ { "head", "dd" },
+ { "head", "dfn" },
+ { "head", "dir" },
+ { "head", "div" },
+ { "head", "dl" },
+ { "head", "dt" },
+ { "head", "em" },
+ { "head", "fieldset" },
+ { "head", "font" },
+ { "head", "form" },
+ { "head", "frameset" },
+ { "head", "h1" },
+ { "head", "h2" },
+ { "head", "h3" },
+ { "head", "h4" },
+ { "head", "h5" },
+ { "head", "h6" },
+ { "head", "hr" },
+ { "head", "i" },
+ { "head", "iframe" },
+ { "head", "img" },
+ { "head", "kbd" },
+ { "head", "li" },
+ { "head", "listing" },
+ { "head", "map" },
+ { "head", "menu" },
+ { "head", "ol" },
+ { "head", "p" },
+ { "head", "pre" },
+ { "head", "q" },
+ { "head", "s" },
+ { "head", "samp" },
+ { "head", "small" },
+ { "head", "span" },
+ { "head", "strike" },
+ { "head", "strong" },
+ { "head", "sub" },
+ { "head", "sup" },
+ { "head", "table" },
+ { "head", "tt" },
+ { "head", "u" },
+ { "head", "ul" },
+ { "head", "var" },
+ { "head", "xmp" },
+ { "hr", "form" },
+ { "i", "center" },
+ { "i", "p" },
+ { "i", "td" },
+ { "i", "th" },
+ { "legend", "fieldset" },
+ { "li", "li" },
+ { "link", "body" },
+ { "link", "frameset" },
+ { "listing", "dd" },
+ { "listing", "dl" },
+ { "listing", "dt" },
+ { "listing", "fieldset" },
+ { "listing", "form" },
+ { "listing", "li" },
+ { "listing", "table" },
+ { "listing", "ul" },
+ { "menu", "dd" },
+ { "menu", "dl" },
+ { "menu", "dt" },
+ { "menu", "form" },
+ { "menu", "ul" },
+ { "ol", "form" },
+ { "ol", "ul" },
+ { "option", "optgroup" },
+ { "option", "option" },
+ { "p", "address" },
+ { "p", "blockquote" },
+ { "p", "body" },
+ { "p", "caption" },
+ { "p", "center" },
+ { "p", "col" },
+ { "p", "colgroup" },
+ { "p", "dd" },
+ { "p", "dir" },
+ { "p", "div" },
+ { "p", "dl" },
+ { "p", "dt" },
+ { "p", "fieldset" },
+ { "p", "form" },
+ { "p", "frameset" },
+ { "p", "h1" },
+ { "p", "h2" },
+ { "p", "h3" },
+ { "p", "h4" },
+ { "p", "h5" },
+ { "p", "h6" },
+ { "p", "head" },
+ { "p", "hr" },
+ { "p", "li" },
+ { "p", "listing" },
+ { "p", "menu" },
+ { "p", "ol" },
+ { "p", "p" },
+ { "p", "pre" },
+ { "p", "table" },
+ { "p", "tbody" },
+ { "p", "td" },
+ { "p", "tfoot" },
+ { "p", "th" },
+ { "p", "title" },
+ { "p", "tr" },
+ { "p", "ul" },
+ { "p", "xmp" },
+ { "pre", "dd" },
+ { "pre", "dl" },
+ { "pre", "dt" },
+ { "pre", "fieldset" },
+ { "pre", "form" },
+ { "pre", "li" },
+ { "pre", "table" },
+ { "pre", "ul" },
+ { "s", "p" },
+ { "script", "noscript" },
+ { "small", "p" },
+ { "span", "td" },
+ { "span", "th" },
+ { "strike", "p" },
+ { "style", "body" },
+ { "style", "frameset" },
+ { "tbody", "tbody" },
+ { "tbody", "tfoot" },
+ { "td", "tbody" },
+ { "td", "td" },
+ { "td", "tfoot" },
+ { "td", "th" },
+ { "td", "tr" },
+ { "tfoot", "tbody" },
+ { "th", "tbody" },
+ { "th", "td" },
+ { "th", "tfoot" },
+ { "th", "th" },
+ { "th", "tr" },
+ { "thead", "tbody" },
+ { "thead", "tfoot" },
+ { "title", "body" },
+ { "title", "frameset" },
+ { "tr", "tbody" },
+ { "tr", "tfoot" },
+ { "tr", "tr" },
+ { "tt", "p" },
+ { "u", "p" },
+ { "u", "td" },
+ { "u", "th" },
+ { "ul", "address" },
+ { "ul", "form" },
+ { "ul", "menu" },
+ { "ul", "ol" },
+ { "ul", "pre" },
+ { "xmp", "dd" },
+ { "xmp", "dl" },
+ { "xmp", "dt" },
+ { "xmp", "fieldset" },
+ { "xmp", "form" },
+ { "xmp", "li" },
+ { "xmp", "table" },
+ { "xmp", "ul" }
};
/*
@@ -1211,9 +1401,6 @@ static const elementPriority htmlEndPriority[] = {
{NULL, 100} /* Default priority */
};
-static const char** htmlStartCloseIndex[100];
-static int htmlStartCloseIndexinitialized = 0;
-
/************************************************************************
* *
* functions to handle HTML specific data *
@@ -1223,24 +1410,18 @@ static int htmlStartCloseIndexinitialized = 0;
/**
* htmlInitAutoClose:
*
- * Initialize the htmlStartCloseIndex for fast lookup of closing tags names.
- * This is not reentrant. Call xmlInitParser() once before processing in
- * case of use in multithreaded programs.
+ * This is a no-op now.
*/
void
htmlInitAutoClose(void) {
- int indx, i = 0;
+}
- if (htmlStartCloseIndexinitialized) return;
+static int
+htmlCompareTags(const void *key, const void *member) {
+ const xmlChar *tag = (const xmlChar *) key;
+ const htmlElemDesc *desc = (const htmlElemDesc *) member;
- for (indx = 0;indx < 100;indx ++) htmlStartCloseIndex[indx] = NULL;
- indx = 0;
- while ((htmlStartClose[i] != NULL) && (indx < 100 - 1)) {
- htmlStartCloseIndex[indx++] = (const char**) &htmlStartClose[i];
- while (htmlStartClose[i] != NULL) i++;
- i++;
- }
- htmlStartCloseIndexinitialized = 1;
+ return(xmlStrcasecmp(tag, BAD_CAST desc->name));
}
/**
@@ -1253,14 +1434,12 @@ htmlInitAutoClose(void) {
*/
const htmlElemDesc *
htmlTagLookup(const xmlChar *tag) {
- unsigned int i;
+ if (tag == NULL)
+ return(NULL);
- for (i = 0; i < (sizeof(html40ElementTable) /
- sizeof(html40ElementTable[0]));i++) {
- if (!xmlStrcasecmp(tag, BAD_CAST html40ElementTable[i].name))
- return((htmlElemDescPtr) &html40ElementTable[i]);
- }
- return(NULL);
+ return((const htmlElemDesc *) bsearch(tag, html40ElementTable,
+ sizeof(html40ElementTable) / sizeof(htmlElemDesc),
+ sizeof(htmlElemDesc), htmlCompareTags));
}
/**
@@ -1281,6 +1460,19 @@ htmlGetEndPriority (const xmlChar *name) {
}
+static int
+htmlCompareStartClose(const void *vkey, const void *member) {
+ const htmlStartCloseEntry *key = (const htmlStartCloseEntry *) vkey;
+ const htmlStartCloseEntry *entry = (const htmlStartCloseEntry *) member;
+ int ret;
+
+ ret = strcmp(key->oldTag, entry->oldTag);
+ if (ret == 0)
+ ret = strcmp(key->newTag, entry->newTag);
+
+ return(ret);
+}
+
/**
* htmlCheckAutoClose:
* @newtag: The new tag name
@@ -1288,37 +1480,21 @@ htmlGetEndPriority (const xmlChar *name) {
*
* Checks whether the new tag is one of the registered valid tags for
* closing old.
- * Initialize the htmlStartCloseIndex for fast lookup of closing tags names.
*
* Returns 0 if no, 1 if yes.
*/
static int
htmlCheckAutoClose(const xmlChar * newtag, const xmlChar * oldtag)
{
- int i, indx;
- const char **closed = NULL;
-
- if (htmlStartCloseIndexinitialized == 0)
- htmlInitAutoClose();
-
- /* inefficient, but not a big deal */
- for (indx = 0; indx < 100; indx++) {
- closed = htmlStartCloseIndex[indx];
- if (closed == NULL)
- return (0);
- if (xmlStrEqual(BAD_CAST * closed, newtag))
- break;
- }
-
- i = closed - htmlStartClose;
- i++;
- while (htmlStartClose[i] != NULL) {
- if (xmlStrEqual(BAD_CAST htmlStartClose[i], oldtag)) {
- return (1);
- }
- i++;
- }
- return (0);
+ htmlStartCloseEntry key;
+ void *res;
+
+ key.oldTag = (const char *) oldtag;
+ key.newTag = (const char *) newtag;
+ res = bsearch(&key, htmlStartClose,
+ sizeof(htmlStartClose) / sizeof(htmlStartCloseEntry),
+ sizeof(htmlStartCloseEntry), htmlCompareStartClose);
+ return(res != NULL);
}
/**
@@ -2341,6 +2517,8 @@ htmlNewDocNoDtD(const xmlChar *URI, const xmlChar *ExternalID) {
if ((ExternalID != NULL) ||
(URI != NULL))
xmlCreateIntSubset(cur, BAD_CAST "html", ExternalID, URI);
+ if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
+ xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
return(cur);
}
@@ -2482,7 +2660,6 @@ htmlParseName(htmlParserCtxtPtr ctxt) {
count = in - ctxt->input->cur;
ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
ctxt->input->cur = in;
- ctxt->nbChars += count;
ctxt->input->col += count;
return(ret);
}
@@ -2789,47 +2966,39 @@ htmlParseAttValue(htmlParserCtxtPtr ctxt) {
static xmlChar *
htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
size_t len = 0, startPosition = 0;
+ int err = 0;
+ int quote;
xmlChar *ret = NULL;
- if (CUR == '"') {
- NEXT;
+ if ((CUR != '"') && (CUR != '\'')) {
+ htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
+ "SystemLiteral \" or ' expected\n", NULL, NULL);
+ return(NULL);
+ }
+ quote = CUR;
+ NEXT;
- if (CUR_PTR < BASE_PTR)
- return(ret);
- startPosition = CUR_PTR - BASE_PTR;
+ if (CUR_PTR < BASE_PTR)
+ return(ret);
+ startPosition = CUR_PTR - BASE_PTR;
- while ((IS_CHAR_CH(CUR)) && (CUR != '"')) {
- NEXT;
- len++;
- }
- if (!IS_CHAR_CH(CUR)) {
- htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
- "Unfinished SystemLiteral\n", NULL, NULL);
- } else {
- ret = xmlStrndup((BASE_PTR+startPosition), len);
- NEXT;
+ while ((CUR != 0) && (CUR != quote)) {
+ /* TODO: Handle UTF-8 */
+ if (!IS_CHAR_CH(CUR)) {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Invalid char in SystemLiteral 0x%X\n", CUR);
+ err = 1;
}
- } else if (CUR == '\'') {
NEXT;
-
- if (CUR_PTR < BASE_PTR)
- return(ret);
- startPosition = CUR_PTR - BASE_PTR;
-
- while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) {
- NEXT;
- len++;
- }
- if (!IS_CHAR_CH(CUR)) {
- htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
- "Unfinished SystemLiteral\n", NULL, NULL);
- } else {
- ret = xmlStrndup((BASE_PTR+startPosition), len);
- NEXT;
- }
+ len++;
+ }
+ if (CUR != quote) {
+ htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
+ "Unfinished SystemLiteral\n", NULL, NULL);
} else {
- htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
- " or ' expected\n", NULL, NULL);
+ NEXT;
+ if (err == 0)
+ ret = xmlStrndup((BASE_PTR+startPosition), len);
}
return(ret);
@@ -2849,51 +3018,42 @@ htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
static xmlChar *
htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
size_t len = 0, startPosition = 0;
+ int err = 0;
+ int quote;
xmlChar *ret = NULL;
+
+ if ((CUR != '"') && (CUR != '\'')) {
+ htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
+ "PubidLiteral \" or ' expected\n", NULL, NULL);
+ return(NULL);
+ }
+ quote = CUR;
+ NEXT;
+
/*
* Name ::= (Letter | '_') (NameChar)*
*/
- if (CUR == '"') {
- NEXT;
-
- if (CUR_PTR < BASE_PTR)
- return(ret);
- startPosition = CUR_PTR - BASE_PTR;
-
- while (IS_PUBIDCHAR_CH(CUR)) {
- len++;
- NEXT;
+ if (CUR_PTR < BASE_PTR)
+ return(ret);
+ startPosition = CUR_PTR - BASE_PTR;
+
+ while ((CUR != 0) && (CUR != quote)) {
+ if (!IS_PUBIDCHAR_CH(CUR)) {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Invalid char in PubidLiteral 0x%X\n", CUR);
+ err = 1;
}
-
- if (CUR != '"') {
- htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
- "Unfinished PubidLiteral\n", NULL, NULL);
- } else {
- ret = xmlStrndup((BASE_PTR + startPosition), len);
- NEXT;
- }
- } else if (CUR == '\'') {
+ len++;
NEXT;
+ }
- if (CUR_PTR < BASE_PTR)
- return(ret);
- startPosition = CUR_PTR - BASE_PTR;
-
- while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')){
- len++;
- NEXT;
- }
-
- if (CUR != '\'') {
- htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
- "Unfinished PubidLiteral\n", NULL, NULL);
- } else {
- ret = xmlStrndup((BASE_PTR + startPosition), len);
- NEXT;
- }
+ if (CUR != quote) {
+ htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
+ "Unfinished PubidLiteral\n", NULL, NULL);
} else {
- htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_STARTED,
- "PubidLiteral \" or ' expected\n", NULL, NULL);
+ NEXT;
+ if (err == 0)
+ ret = xmlStrndup((BASE_PTR + startPosition), len);
}
return(ret);
@@ -2928,7 +3088,7 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
SHRINK;
cur = CUR_CHAR(l);
- while (IS_CHAR_CH(cur)) {
+ while (cur != 0) {
if ((cur == '<') && (NXT(1) == '/')) {
/*
* One should break here, the specification is clear:
@@ -2959,7 +3119,12 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
}
}
}
- COPY_BUF(l,buf,nbchar,cur);
+ if (IS_CHAR(cur)) {
+ COPY_BUF(l,buf,nbchar,cur);
+ } else {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Invalid char in CDATA 0x%X\n", cur);
+ }
if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
buf[nbchar] = 0;
if (ctxt->sax->cdataBlock!= NULL) {
@@ -2977,14 +3142,6 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
cur = CUR_CHAR(l);
}
- if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) {
- htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
- "Invalid char in CDATA 0x%X\n", cur);
- if (ctxt->input->cur < ctxt->input->end) {
- NEXT;
- }
- }
-
if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) {
buf[nbchar] = 0;
if (ctxt->sax->cdataBlock!= NULL) {
@@ -3232,7 +3389,7 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
}
SKIP_BLANKS;
cur = CUR_CHAR(l);
- while (IS_CHAR(cur) && (cur != '>')) {
+ while ((cur != 0) && (cur != '>')) {
if (len + 5 >= size) {
xmlChar *tmp;
@@ -3251,7 +3408,13 @@ htmlParsePI(htmlParserCtxtPtr ctxt) {
GROW;
count = 0;
}
- COPY_BUF(l,buf,len,cur);
+ if (IS_CHAR(cur)) {
+ COPY_BUF(l,buf,len,cur);
+ } else {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Invalid char in processing instruction "
+ "0x%X\n", cur);
+ }
NEXTL(l);
cur = CUR_CHAR(l);
if (cur == 0) {
@@ -3300,6 +3463,7 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
int q, ql;
int r, rl;
int cur, l;
+ int next, nl;
xmlParserInputState state;
/*
@@ -3321,17 +3485,32 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
len = 0;
buf[len] = 0;
q = CUR_CHAR(ql);
- if (!IS_CHAR(q))
+ if (q == 0)
goto unfinished;
NEXTL(ql);
r = CUR_CHAR(rl);
- if (!IS_CHAR(r))
+ if (r == 0)
goto unfinished;
NEXTL(rl);
cur = CUR_CHAR(l);
- while (IS_CHAR(cur) &&
+ while ((cur != 0) &&
((cur != '>') ||
(r != '-') || (q != '-'))) {
+ NEXTL(l);
+ next = CUR_CHAR(nl);
+ if (next == 0) {
+ SHRINK;
+ GROW;
+ next = CUR_CHAR(nl);
+ }
+
+ if ((q == '-') && (r == '-') && (cur == '!') && (next == '>')) {
+ htmlParseErr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
+ "Comment incorrectly closed by '--!>'", NULL, NULL);
+ cur = '>';
+ break;
+ }
+
if (len + 5 >= size) {
xmlChar *tmp;
@@ -3345,21 +3524,22 @@ htmlParseComment(htmlParserCtxtPtr ctxt) {
}
buf = tmp;
}
- COPY_BUF(ql,buf,len,q);
+ if (IS_CHAR(q)) {
+ COPY_BUF(ql,buf,len,q);
+ } else {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Invalid char in comment 0x%X\n", q);
+ }
+
q = r;
ql = rl;
r = cur;
rl = l;
- NEXTL(l);
- cur = CUR_CHAR(l);
- if (cur == 0) {
- SHRINK;
- GROW;
- cur = CUR_CHAR(l);
- }
+ cur = next;
+ l = nl;
}
buf[len] = 0;
- if (IS_CHAR(cur)) {
+ if (cur == '>') {
NEXT;
if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
(!ctxt->disableSAX))
@@ -3400,13 +3580,16 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
((NXT(2) == 'x') || NXT(2) == 'X')) {
SKIP(3);
while (CUR != ';') {
- if ((CUR >= '0') && (CUR <= '9'))
- val = val * 16 + (CUR - '0');
- else if ((CUR >= 'a') && (CUR <= 'f'))
- val = val * 16 + (CUR - 'a') + 10;
- else if ((CUR >= 'A') && (CUR <= 'F'))
- val = val * 16 + (CUR - 'A') + 10;
- else {
+ if ((CUR >= '0') && (CUR <= '9')) {
+ if (val < 0x110000)
+ val = val * 16 + (CUR - '0');
+ } else if ((CUR >= 'a') && (CUR <= 'f')) {
+ if (val < 0x110000)
+ val = val * 16 + (CUR - 'a') + 10;
+ } else if ((CUR >= 'A') && (CUR <= 'F')) {
+ if (val < 0x110000)
+ val = val * 16 + (CUR - 'A') + 10;
+ } else {
htmlParseErr(ctxt, XML_ERR_INVALID_HEX_CHARREF,
"htmlParseCharRef: missing semicolon\n",
NULL, NULL);
@@ -3419,9 +3602,10 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
} else if ((CUR == '&') && (NXT(1) == '#')) {
SKIP(2);
while (CUR != ';') {
- if ((CUR >= '0') && (CUR <= '9'))
- val = val * 10 + (CUR - '0');
- else {
+ if ((CUR >= '0') && (CUR <= '9')) {
+ if (val < 0x110000)
+ val = val * 10 + (CUR - '0');
+ } else {
htmlParseErr(ctxt, XML_ERR_INVALID_DEC_CHARREF,
"htmlParseCharRef: missing semicolon\n",
NULL, NULL);
@@ -3440,6 +3624,9 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
*/
if (IS_CHAR(val)) {
return(val);
+ } else if (val >= 0x110000) {
+ htmlParseErr(ctxt, XML_ERR_INVALID_CHAR,
+ "htmlParseCharRef: value too large\n", NULL, NULL);
} else {
htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
"htmlParseCharRef: invalid xmlChar value %d\n",
@@ -3499,9 +3686,12 @@ htmlParseDocTypeDecl(htmlParserCtxtPtr ctxt) {
if (CUR != '>') {
htmlParseErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED,
"DOCTYPE improperly terminated\n", NULL, NULL);
- /* We shouldn't try to resynchronize ... */
+ /* Ignore bogus content */
+ while ((CUR != 0) && (CUR != '>'))
+ NEXT;
}
- NEXT;
+ if (CUR == '>')
+ NEXT;
/*
* Create or update the document accordingly to the DOCTYPE
@@ -3770,16 +3960,28 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
"htmlParseStartTag: invalid element name\n",
NULL, NULL);
+ /*
+ * The recovery code is disabled for now as it can result in
+ * quadratic behavior with the push parser. htmlParseStartTag
+ * must consume all content up to the final '>' in order to avoid
+ * rescanning for this terminator.
+ *
+ * For a proper fix in line with HTML5, htmlParseStartTag and
+ * htmlParseElement should only be called when there's an ASCII
+ * alpha character following the initial '<'. Otherwise, the '<'
+ * should be emitted as text (unless followed by '!', '/' or '?').
+ */
+#if 0
/* if recover preserve text on classic misconstructs */
if ((ctxt->recovery) && ((IS_BLANK_CH(CUR)) || (CUR == '<') ||
(CUR == '=') || (CUR == '>') || (((CUR >= '0') && (CUR <= '9'))))) {
htmlParseCharDataInternal(ctxt, '<');
return(-1);
}
-
+#endif
/* Dump the bogus tag like browsers do */
- while ((IS_CHAR_CH(CUR)) && (CUR != '>') &&
+ while ((CUR != 0) && (CUR != '>') &&
(ctxt->instate != XML_PARSER_EOF))
NEXT;
return -1;
@@ -3835,11 +4037,9 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
* (S Attribute)* S?
*/
SKIP_BLANKS;
- while ((IS_CHAR_CH(CUR)) &&
+ while ((CUR != 0) &&
(CUR != '>') &&
((CUR != '/') || (NXT(1) != '>'))) {
- long cons = ctxt->nbChars;
-
GROW;
attname = htmlParseAttribute(ctxt, &attvalue);
if (attname != NULL) {
@@ -3898,7 +4098,7 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
xmlFree(attvalue);
/* Dump the bogus attribute string up to the next blank or
* the end of the tag. */
- while ((IS_CHAR_CH(CUR)) &&
+ while ((CUR != 0) &&
!(IS_BLANK_CH(CUR)) && (CUR != '>') &&
((CUR != '/') || (NXT(1) != '>')))
NEXT;
@@ -3906,12 +4106,6 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
failed:
SKIP_BLANKS;
- if (cons == ctxt->nbChars) {
- htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
- "htmlParseStartTag: problem parsing attributes\n",
- NULL, NULL);
- break;
- }
}
/*
@@ -3979,19 +4173,14 @@ htmlParseEndTag(htmlParserCtxtPtr ctxt)
* We should definitely be at the ending "S? '>'" part
*/
SKIP_BLANKS;
- if ((!IS_CHAR_CH(CUR)) || (CUR != '>')) {
+ if (CUR != '>') {
htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
"End tag : expected '>'\n", NULL, NULL);
- if (ctxt->recovery) {
- /*
- * We're not at the ending > !!
- * Error, unless in recover mode where we search forwards
- * until we find a >
- */
- while (CUR != '\0' && CUR != '>') NEXT;
- NEXT;
- }
- } else
+ /* Skip to next '>' */
+ while ((CUR != 0) && (CUR != '>'))
+ NEXT;
+ }
+ if (CUR == '>')
NEXT;
/*
@@ -4032,12 +4221,10 @@ htmlParseEndTag(htmlParserCtxtPtr ctxt)
* With the exception that the autoclose may have popped stuff out
* of the stack.
*/
- if (!xmlStrEqual(name, ctxt->name)) {
- if ((ctxt->name != NULL) && (!xmlStrEqual(ctxt->name, name))) {
- htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
- "Opening and ending tag mismatch: %s and %s\n",
- name, ctxt->name);
- }
+ if ((ctxt->name != NULL) && (!xmlStrEqual(ctxt->name, name))) {
+ htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
+ "Opening and ending tag mismatch: %s and %s\n",
+ name, ctxt->name);
}
/*
@@ -4152,8 +4339,6 @@ htmlParseContent(htmlParserCtxtPtr ctxt) {
currentNode = xmlStrdup(ctxt->name);
depth = ctxt->nameNr;
while (1) {
- long cons = ctxt->nbChars;
-
GROW;
if (ctxt->instate == XML_PARSER_EOF)
@@ -4181,7 +4366,7 @@ htmlParseContent(htmlParserCtxtPtr ctxt) {
"htmlParseStartTag: invalid element name\n",
NULL, NULL);
/* Dump the bogus tag like browsers do */
- while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
+ while ((CUR != 0) && (CUR != '>'))
NEXT;
if (currentNode != NULL)
@@ -4273,15 +4458,6 @@ htmlParseContent(htmlParserCtxtPtr ctxt) {
else {
htmlParseCharData(ctxt);
}
-
- if (cons == ctxt->nbChars) {
- if (ctxt->node != NULL) {
- htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
- "detected an error in element content\n",
- NULL, NULL);
- }
- break;
- }
}
GROW;
}
@@ -4396,7 +4572,7 @@ htmlParseElement(htmlParserCtxtPtr ctxt) {
*/
currentNode = xmlStrdup(ctxt->name);
depth = ctxt->nameNr;
- while (IS_CHAR_CH(CUR)) {
+ while (CUR != 0) {
oldptr = ctxt->input->cur;
htmlParseContent(ctxt);
if (oldptr==ctxt->input->cur) break;
@@ -4413,7 +4589,7 @@ htmlParseElement(htmlParserCtxtPtr ctxt) {
node_info.node = ctxt->node;
xmlParserAddNodeInfo(ctxt, &node_info);
}
- if (!IS_CHAR_CH(CUR)) {
+ if (CUR == 0) {
htmlAutoCloseOnEnd(ctxt);
}
@@ -4434,7 +4610,7 @@ htmlParserFinishElementParsing(htmlParserCtxtPtr ctxt) {
xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
htmlNodeInfoPop(ctxt);
}
- if (!IS_CHAR_CH(CUR)) {
+ if (CUR == 0) {
htmlAutoCloseOnEnd(ctxt);
}
}
@@ -4552,8 +4728,6 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
currentNode = xmlStrdup(ctxt->name);
depth = ctxt->nameNr;
while (1) {
- long cons = ctxt->nbChars;
-
GROW;
if (ctxt->instate == XML_PARSER_EOF)
@@ -4583,7 +4757,7 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
"htmlParseStartTag: invalid element name\n",
NULL, NULL);
/* Dump the bogus tag like browsers do */
- while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
+ while ((CUR == 0) && (CUR != '>'))
NEXT;
htmlParserFinishElementParsing(ctxt);
@@ -4687,15 +4861,6 @@ htmlParseContentInternal(htmlParserCtxtPtr ctxt) {
else {
htmlParseCharData(ctxt);
}
-
- if (cons == ctxt->nbChars) {
- if (ctxt->node != NULL) {
- htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
- "detected an error in element content\n",
- NULL, NULL);
- }
- break;
- }
}
GROW;
}
@@ -4959,7 +5124,6 @@ htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
ctxt->vctxt.warning = xmlParserValidityWarning;
ctxt->record_info = 0;
ctxt->validate = 0;
- ctxt->nbChars = 0;
ctxt->checkIndex = 0;
ctxt->catalogs = NULL;
xmlInitNodeInfoSeq(&ctxt->node_seq);
@@ -5035,6 +5199,7 @@ htmlCreateMemoryParserCtxt(const char *buffer, int size) {
input = xmlNewInputStream(ctxt);
if (input == NULL) {
+ xmlFreeParserInputBuffer(buf);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
@@ -5119,7 +5284,7 @@ htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) {
* @first: the first char to lookup
* @next: the next char to lookup or zero
* @third: the next char to lookup or zero
- * @comment: flag to force checking inside comments
+ * @ignoreattrval: skip over attribute values
*
* Try to find if a sequence (first, next, third) or just (first next) or
* (first) is available in the input stream.
@@ -5133,13 +5298,11 @@ htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) {
*/
static int
htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
- xmlChar next, xmlChar third, int iscomment,
- int ignoreattrval)
+ xmlChar next, xmlChar third, int ignoreattrval)
{
int base, len;
htmlParserInputPtr in;
const xmlChar *buf;
- int incomment = 0;
int invalue = 0;
char valdellim = 0x0;
@@ -5151,8 +5314,11 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
if (base < 0)
return (-1);
- if (ctxt->checkIndex > base)
+ if (ctxt->checkIndex > base) {
base = ctxt->checkIndex;
+ /* Abuse hasPErefs member to restore current state. */
+ invalue = ctxt->hasPErefs & 1 ? 1 : 0;
+ }
if (in->buf == NULL) {
buf = in->base;
@@ -5168,14 +5334,6 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
else if (next)
len--;
for (; base < len; base++) {
- if ((!incomment) && (base + 4 < len) && (!iscomment)) {
- if ((buf[base] == '<') && (buf[base + 1] == '!') &&
- (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
- incomment = 1;
- /* do not increment past <! - some people use <!--> */
- base += 2;
- }
- }
if (ignoreattrval) {
if (buf[base] == '"' || buf[base] == '\'') {
if (invalue) {
@@ -5192,16 +5350,6 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
continue;
}
}
- if (incomment) {
- if (base + 3 > len)
- return (-1);
- if ((buf[base] == '-') && (buf[base + 1] == '-') &&
- (buf[base + 2] == '>')) {
- incomment = 0;
- base += 2;
- }
- continue;
- }
if (buf[base] == first) {
if (third != 0) {
if ((buf[base + 1] != next) || (buf[base + 2] != third))
@@ -5228,8 +5376,12 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
return (base - (in->cur - in->base));
}
}
- if ((!incomment) && (!invalue))
- ctxt->checkIndex = base;
+ ctxt->checkIndex = base;
+ /* Abuse hasPErefs member to track current state. */
+ if (invalue)
+ ctxt->hasPErefs |= 1;
+ else
+ ctxt->hasPErefs &= ~1;
#ifdef DEBUG_PUSH
if (next == 0)
xmlGenericError(xmlGenericErrorContext,
@@ -5246,79 +5398,38 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
}
/**
- * htmlParseLookupChars:
+ * htmlParseLookupCommentEnd:
* @ctxt: an HTML parser context
- * @stop: Array of chars, which stop the lookup.
- * @stopLen: Length of stop-Array
*
- * Try to find if any char of the stop-Array is available in the input
- * stream.
+ * Try to find a comment end tag in the input stream
+ * The search includes "-->" as well as WHATWG-recommended incorrectly-closed tags.
+ * (See https://html.spec.whatwg.org/multipage/parsing.html#parse-error-incorrectly-closed-comment)
* This function has a side effect of (possibly) incrementing ctxt->checkIndex
* to avoid rescanning sequences of bytes, it DOES change the state of the
* parser, do not use liberally.
+ * This wraps to htmlParseLookupSequence()
*
- * Returns the index to the current parsing point if a stopChar
- * is available, -1 otherwise.
+ * Returns the index to the current parsing point if the full sequence is available, -1 otherwise.
*/
static int
-htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
- int stopLen)
+htmlParseLookupCommentEnd(htmlParserCtxtPtr ctxt)
{
- int base, len;
- htmlParserInputPtr in;
- const xmlChar *buf;
- int incomment = 0;
- int i;
-
- in = ctxt->input;
- if (in == NULL)
- return (-1);
-
- base = in->cur - in->base;
- if (base < 0)
- return (-1);
-
- if (ctxt->checkIndex > base)
- base = ctxt->checkIndex;
-
- if (in->buf == NULL) {
- buf = in->base;
- len = in->length;
- } else {
- buf = xmlBufContent(in->buf->buffer);
- len = xmlBufUse(in->buf->buffer);
- }
-
- for (; base < len; base++) {
- if (!incomment && (base + 4 < len)) {
- if ((buf[base] == '<') && (buf[base + 1] == '!') &&
- (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
- incomment = 1;
- /* do not increment past <! - some people use <!--> */
- base += 2;
- }
- }
- if (incomment) {
- if (base + 3 > len)
- return (-1);
- if ((buf[base] == '-') && (buf[base + 1] == '-') &&
- (buf[base + 2] == '>')) {
- incomment = 0;
- base += 2;
- }
- continue;
- }
- for (i = 0; i < stopLen; ++i) {
- if (buf[base] == stop[i]) {
- ctxt->checkIndex = 0;
- return (base - (in->cur - in->base));
- }
- }
+ int mark = 0;
+ int cur = CUR_PTR - BASE_PTR;
+
+ while (mark >= 0) {
+ mark = htmlParseLookupSequence(ctxt, '-', '-', 0, 0);
+ if ((mark < 0) ||
+ (NXT(mark+2) == '>') ||
+ ((NXT(mark+2) == '!') && (NXT(mark+3) == '>'))) {
+ return mark;
+ }
+ ctxt->checkIndex = cur + mark + 1;
}
- ctxt->checkIndex = base;
- return (-1);
+ return mark;
}
+
/**
* htmlParseTryOrFinish:
* @ctxt: an HTML parser context
@@ -5332,7 +5443,7 @@ static int
htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
int ret = 0;
htmlParserInputPtr in;
- int avail = 0;
+ ptrdiff_t avail = 0;
xmlChar cur, next;
htmlParserNodeInfo node_info;
@@ -5397,7 +5508,8 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (in->buf == NULL)
avail = in->length - (in->cur - in->base);
else
- avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+ avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+ (in->cur - in->base);
if ((avail == 0) && (terminate)) {
htmlAutoCloseOnEnd(ctxt);
if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) {
@@ -5411,6 +5523,12 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
}
if (avail < 1)
goto done;
+ /*
+ * This is done to make progress and avoid an infinite loop
+ * if a parsing attempt was aborted by hitting a NUL byte. After
+ * changing htmlCurrentChar, this probably isn't necessary anymore.
+ * We should consider removing this check.
+ */
cur = in->cur[0];
if (cur == 0) {
SKIP(1);
@@ -5433,7 +5551,8 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (in->buf == NULL)
avail = in->length - (in->cur - in->base);
else
- avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+ avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+ (in->cur - in->base);
}
if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
ctxt->sax->setDocumentLocator(ctxt->userData,
@@ -5450,7 +5569,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(UPP(6) == 'Y') && (UPP(7) == 'P') &&
(UPP(8) == 'E')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5475,14 +5594,15 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (in->buf == NULL)
avail = in->length - (in->cur - in->base);
else
- avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+ avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+ (in->cur - in->base);
/*
* no chars in buffer
*/
if (avail < 1)
goto done;
/*
- * not enouth chars in buffer
+ * not enough chars in buffer
*/
if (avail < 2) {
if (!terminate)
@@ -5495,8 +5615,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
cur = in->cur[0];
if ((cur == '<') && (next == '!') &&
(in->cur[2] == '-') && (in->cur[3] == '-')) {
- if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+ if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5506,7 +5625,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_MISC;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5520,7 +5639,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(UPP(6) == 'Y') && (UPP(7) == 'P') &&
(UPP(8) == 'E')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5536,7 +5655,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(avail < 9)) {
goto done;
} else {
- ctxt->instate = XML_PARSER_START_TAG;
+ ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"HPP: entering START_TAG\n");
@@ -5548,15 +5667,15 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (in->buf == NULL)
avail = in->length - (in->cur - in->base);
else
- avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+ avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+ (in->cur - in->base);
if (avail < 2)
goto done;
cur = in->cur[0];
next = in->cur[1];
if ((cur == '<') && (next == '!') &&
(in->cur[2] == '-') && (in->cur[3] == '-')) {
- if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+ if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5566,7 +5685,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_PROLOG;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5578,7 +5697,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(avail < 4)) {
goto done;
} else {
- ctxt->instate = XML_PARSER_START_TAG;
+ ctxt->instate = XML_PARSER_CONTENT;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"HPP: entering START_TAG\n");
@@ -5589,7 +5708,8 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (in->buf == NULL)
avail = in->length - (in->cur - in->base);
else
- avail = xmlBufUse(in->buf->buffer) - (in->cur - in->base);
+ avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) -
+ (in->cur - in->base);
if (avail < 1)
goto done;
cur = in->cur[0];
@@ -5602,8 +5722,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
next = in->cur[1];
if ((cur == '<') && (next == '!') &&
(in->cur[2] == '-') && (in->cur[3] == '-')) {
- if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+ if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5613,7 +5732,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_EPILOG;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5648,7 +5767,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (avail < 1)
goto done;
/*
- * not enouth chars in buffer
+ * not enough chars in buffer
*/
if (avail < 2) {
if (!terminate)
@@ -5677,7 +5796,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
break;
}
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
/* Capture start position */
@@ -5769,7 +5888,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
}
case XML_PARSER_CONTENT: {
xmlChar chr[2] = { 0, 0 };
- long cons;
/*
* Handle preparsed entities and charRef
@@ -5814,7 +5932,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
goto done;
cur = in->cur[0];
next = in->cur[1];
- cons = ctxt->nbChars;
if ((xmlStrEqual(ctxt->name, BAD_CAST"script")) ||
(xmlStrEqual(ctxt->name, BAD_CAST"style"))) {
/*
@@ -5824,7 +5941,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
int idx;
xmlChar val;
- idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0, 0);
+ idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0);
if (idx < 0)
goto done;
val = in->cur[idx + 2];
@@ -5851,7 +5968,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(UPP(6) == 'Y') && (UPP(7) == 'P') &&
(UPP(8) == 'E')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
"Misplaced DOCTYPE declaration\n",
@@ -5859,9 +5976,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
htmlParseDocTypeDecl(ctxt);
} else if ((cur == '<') && (next == '!') &&
(in->cur[2] == '-') && (in->cur[3] == '-')) {
- if ((!terminate) &&
- (htmlParseLookupSequence(
- ctxt, '-', '-', '>', 1, 1) < 0))
+ if ((!terminate) && (htmlParseLookupCommentEnd(ctxt) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5871,7 +5986,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_CONTENT;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5890,24 +6005,15 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
#endif
break;
} else if (cur == '<') {
- ctxt->instate = XML_PARSER_START_TAG;
- ctxt->checkIndex = 0;
+ 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");
+ xmlGenericError(xmlGenericErrorContext,
+ "HPP: entering START_TAG\n");
#endif
break;
- } else if (cur == '&') {
- if ((!terminate) &&
- (htmlParseLookupChars(ctxt,
- BAD_CAST "; >/", 4) < 0))
- goto done;
-#ifdef DEBUG_PUSH
- xmlGenericError(xmlGenericErrorContext,
- "HPP: Parsing Reference\n");
-#endif
- /* TODO: check generation of subtrees if noent !!! */
- htmlParseReference(ctxt);
} else {
/*
* check that the text sequence is complete
@@ -5916,24 +6022,23 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
* data detection.
*/
if ((!terminate) &&
- (htmlParseLookupChars(ctxt, BAD_CAST "<&", 2) < 0))
+ (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0))
goto done;
ctxt->checkIndex = 0;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"HPP: Parsing char data\n");
#endif
- htmlParseCharData(ctxt);
- }
- }
- if (cons == ctxt->nbChars) {
- if (ctxt->node != NULL) {
- htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
- "detected an error in element content\n",
- NULL, NULL);
+ while ((ctxt->instate != XML_PARSER_EOF) &&
+ (cur != '<') && (in->cur < in->end)) {
+ if (cur == '&') {
+ htmlParseReference(ctxt);
+ } else {
+ htmlParseCharData(ctxt);
+ }
+ cur = in->cur[0];
+ }
}
- NEXT;
- break;
}
break;
@@ -5942,7 +6047,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (avail < 2)
goto done;
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
htmlParseEndTag(ctxt);
if (ctxt->nameNr == 0) {
@@ -6124,12 +6229,12 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
int res;
res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
+ xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
if (res < 0) {
ctxt->errNo = XML_PARSER_EOF;
ctxt->disableSAX = 1;
return (XML_PARSER_EOF);
}
- xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
#endif
@@ -6148,12 +6253,12 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
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);
}
- xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
}
}
}
@@ -6671,7 +6776,6 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt)
ctxt->vctxt.error = xmlParserValidityError;
ctxt->vctxt.warning = xmlParserValidityWarning;
ctxt->record_info = 0;
- ctxt->nbChars = 0;
ctxt->checkIndex = 0;
ctxt->inSubset = 0;
ctxt->errNo = XML_ERR_OK;
@@ -6890,7 +6994,9 @@ htmlReadMemory(const char *buffer, int size, const char *URL, const char *encodi
* @encoding: the document encoding, or NULL
* @options: a combination of htmlParserOption(s)
*
- * parse an XML from a file descriptor and build a tree.
+ * parse an HTML from a file descriptor and build a tree.
+ * NOTE that the file descriptor will not be closed when the
+ * reader is closed or reset.
*
* Returns the resulting document tree
*/
@@ -6899,17 +7005,17 @@ htmlReadFd(int fd, const char *URL, const char *encoding, int options)
{
htmlParserCtxtPtr ctxt;
xmlParserInputBufferPtr input;
- xmlParserInputPtr stream;
+ htmlParserInputPtr stream;
if (fd < 0)
return (NULL);
- xmlInitParser();
xmlInitParser();
input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
if (input == NULL)
return (NULL);
- ctxt = xmlNewParserCtxt();
+ input->closecallback = NULL;
+ ctxt = htmlNewParserCtxt();
if (ctxt == NULL) {
xmlFreeParserInputBuffer(input);
return (NULL);
@@ -6917,7 +7023,7 @@ htmlReadFd(int fd, const char *URL, const char *encoding, int options)
stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
if (stream == NULL) {
xmlFreeParserInputBuffer(input);
- xmlFreeParserCtxt(ctxt);
+ htmlFreeParserCtxt(ctxt);
return (NULL);
}
inputPush(ctxt, stream);
diff --git a/contrib/libs/libxml/HTMLtree.c b/contrib/libs/libxml/HTMLtree.c
index db63b371f0..7a2b855838 100644
--- a/contrib/libs/libxml/HTMLtree.c
+++ b/contrib/libs/libxml/HTMLtree.c
@@ -226,7 +226,7 @@ found_head:
found_meta:
/*
* Search and update all the remaining the meta elements carrying
- * encoding informations
+ * encoding information
*/
while (cur != NULL) {
if ((cur->type == XML_ELEMENT_NODE) && (cur->name != NULL)) {
@@ -345,7 +345,7 @@ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder);
************************************************************************/
/**
* htmlSaveErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -359,7 +359,7 @@ htmlSaveErrMemory(const char *extra)
* htmlSaveErr:
* @code: the error number
* @node: the location of the error.
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -518,7 +518,7 @@ htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc,
buf = xmlOutputBufferCreateFile(out, handler);
if (buf == NULL) return(0);
- htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
+ htmlNodeDumpFormatOutput(buf, doc, cur, NULL, format);
ret = xmlOutputBufferClose(buf);
return(ret);
@@ -670,13 +670,11 @@ htmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
* @buf: the HTML buffer output
* @doc: the document
* @cur: the attribute pointer
- * @encoding: the encoding string
*
* Dump an HTML attribute
*/
static void
-htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
- const char *encoding ATTRIBUTE_UNUSED) {
+htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
xmlChar *value;
/*
@@ -706,49 +704,22 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
(!xmlStrcasecmp(cur->name, BAD_CAST "src")) ||
((!xmlStrcasecmp(cur->name, BAD_CAST "name")) &&
(!xmlStrcasecmp(cur->parent->name, BAD_CAST "a"))))) {
+ xmlChar *escaped;
xmlChar *tmp = value;
- /* xmlURIEscapeStr() escapes '"' so it can be safely used. */
- xmlBufCCat(buf->buffer, "\"");
while (IS_BLANK_CH(*tmp)) tmp++;
- /* URI Escape everything, except server side includes. */
- for ( ; ; ) {
- xmlChar *escaped;
- xmlChar endChar;
- xmlChar *end = NULL;
- xmlChar *start = (xmlChar *)xmlStrstr(tmp, BAD_CAST "<!--");
- if (start != NULL) {
- end = (xmlChar *)xmlStrstr(tmp, BAD_CAST "-->");
- if (end != NULL) {
- *start = '\0';
- }
- }
-
- /* Escape the whole string, or until start (set to '\0'). */
- escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+");
- if (escaped != NULL) {
- xmlBufCat(buf->buffer, escaped);
- xmlFree(escaped);
- } else {
- xmlBufCat(buf->buffer, tmp);
- }
-
- if (end == NULL) { /* Everything has been written. */
- break;
- }
-
- /* Do not escape anything within server side includes. */
- *start = '<'; /* Restore the first character of "<!--". */
- end += 3; /* strlen("-->") */
- endChar = *end;
- *end = '\0';
- xmlBufCat(buf->buffer, start);
- *end = endChar;
- tmp = end;
+ /*
+ * the < and > have already been escaped at the entity level
+ * And doing so here breaks server side includes
+ */
+ escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+<>");
+ if (escaped != NULL) {
+ xmlBufWriteQuotedString(buf->buffer, escaped);
+ xmlFree(escaped);
+ } else {
+ xmlBufWriteQuotedString(buf->buffer, value);
}
-
- xmlBufCCat(buf->buffer, "\"");
} else {
xmlBufWriteQuotedString(buf->buffer, value);
}
@@ -760,62 +731,21 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
}
/**
- * htmlAttrListDumpOutput:
- * @buf: the HTML buffer output
- * @doc: the document
- * @cur: the first attribute pointer
- * @encoding: the encoding string
- *
- * Dump a list of HTML attributes
- */
-static void
-htmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, const char *encoding) {
- if (cur == NULL) {
- return;
- }
- while (cur != NULL) {
- htmlAttrDumpOutput(buf, doc, cur, encoding);
- cur = cur->next;
- }
-}
-
-
-
-/**
- * htmlNodeListDumpOutput:
- * @buf: the HTML buffer output
- * @doc: the document
- * @cur: the first node
- * @encoding: the encoding string
- * @format: should formatting spaces been added
- *
- * Dump an HTML node list, recursive behaviour,children are printed too.
- */
-static void
-htmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
- xmlNodePtr cur, const char *encoding, int format) {
- if (cur == NULL) {
- return;
- }
- while (cur != NULL) {
- htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
- cur = cur->next;
- }
-}
-
-/**
* htmlNodeDumpFormatOutput:
* @buf: the HTML buffer output
* @doc: the document
* @cur: the current node
- * @encoding: the encoding string
+ * @encoding: the encoding string (unused)
* @format: should formatting spaces been added
*
* Dump an HTML node, recursive behaviour,children are printed too.
*/
void
htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
- xmlNodePtr cur, const char *encoding, int format) {
+ xmlNodePtr cur, const char *encoding ATTRIBUTE_UNUSED,
+ int format) {
+ xmlNodePtr root, parent;
+ xmlAttrPtr attr;
const htmlElemDesc * info;
xmlInitParser();
@@ -823,172 +753,213 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
if ((cur == NULL) || (buf == NULL)) {
return;
}
- /*
- * Special cases.
- */
- if (cur->type == XML_DTD_NODE)
- return;
- if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
- (cur->type == XML_DOCUMENT_NODE)){
- htmlDocContentDumpOutput(buf, (xmlDocPtr) cur, encoding);
- return;
- }
- if (cur->type == XML_ATTRIBUTE_NODE) {
- htmlAttrDumpOutput(buf, doc, (xmlAttrPtr) cur, encoding);
- return;
- }
- if (cur->type == HTML_TEXT_NODE) {
- if (cur->content != NULL) {
- if (((cur->name == (const xmlChar *)xmlStringText) ||
- (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
- ((cur->parent == NULL) ||
- ((xmlStrcasecmp(cur->parent->name, BAD_CAST "script")) &&
- (xmlStrcasecmp(cur->parent->name, BAD_CAST "style"))))) {
- xmlChar *buffer;
-
- buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
- if (buffer != NULL) {
- xmlOutputBufferWriteString(buf, (const char *)buffer);
- xmlFree(buffer);
- }
- } else {
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- }
- }
- return;
- }
- if (cur->type == HTML_COMMENT_NODE) {
- if (cur->content != NULL) {
- xmlOutputBufferWriteString(buf, "<!--");
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- xmlOutputBufferWriteString(buf, "-->");
- }
- return;
- }
- if (cur->type == HTML_PI_NODE) {
- if (cur->name == NULL)
- return;
- xmlOutputBufferWriteString(buf, "<?");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (cur->content != NULL) {
- xmlOutputBufferWriteString(buf, " ");
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- }
- xmlOutputBufferWriteString(buf, ">");
- return;
- }
- if (cur->type == HTML_ENTITY_REF_NODE) {
- xmlOutputBufferWriteString(buf, "&");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWriteString(buf, ";");
- return;
- }
- if (cur->type == HTML_PRESERVE_NODE) {
- if (cur->content != NULL) {
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- }
- return;
- }
- /*
- * Get specific HTML info for that node.
- */
- if (cur->ns == NULL)
- info = htmlTagLookup(cur->name);
- else
- info = NULL;
+ root = cur;
+ parent = cur->parent;
+ while (1) {
+ switch (cur->type) {
+ case XML_HTML_DOCUMENT_NODE:
+ case XML_DOCUMENT_NODE:
+ if (((xmlDocPtr) cur)->intSubset != NULL) {
+ htmlDtdDumpOutput(buf, (xmlDocPtr) cur, NULL);
+ }
+ if (cur->children != NULL) {
+ /* Always validate cur->parent when descending. */
+ if (cur->parent == parent) {
+ parent = cur;
+ cur = cur->children;
+ continue;
+ }
+ } else {
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+ break;
- xmlOutputBufferWriteString(buf, "<");
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
- xmlOutputBufferWriteString(buf, ":");
- }
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (cur->nsDef)
- xmlNsListDumpOutput(buf, cur->nsDef);
- if (cur->properties != NULL)
- htmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
-
- if ((info != NULL) && (info->empty)) {
- xmlOutputBufferWriteString(buf, ">");
- if ((format) && (!info->isinline) && (cur->next != NULL)) {
- if ((cur->next->type != HTML_TEXT_NODE) &&
- (cur->next->type != HTML_ENTITY_REF_NODE) &&
- (cur->parent != NULL) &&
- (cur->parent->name != NULL) &&
- (cur->parent->name[0] != 'p')) /* p, pre, param */
- xmlOutputBufferWriteString(buf, "\n");
- }
- return;
- }
- if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
- (cur->children == NULL)) {
- if ((info != NULL) && (info->saveEndTag != 0) &&
- (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
- (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
- xmlOutputBufferWriteString(buf, ">");
- } else {
- xmlOutputBufferWriteString(buf, "></");
+ case XML_ELEMENT_NODE:
+ /*
+ * 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)) {
+ htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
+ break;
+ }
+
+ /*
+ * Get specific HTML info for that node.
+ */
+ if (cur->ns == NULL)
+ info = htmlTagLookup(cur->name);
+ else
+ info = NULL;
+
+ xmlOutputBufferWriteString(buf, "<");
if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
xmlOutputBufferWriteString(buf, ":");
}
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWriteString(buf, ">");
- }
- if ((format) && (cur->next != NULL) &&
- (info != NULL) && (!info->isinline)) {
- if ((cur->next->type != HTML_TEXT_NODE) &&
- (cur->next->type != HTML_ENTITY_REF_NODE) &&
- (cur->parent != NULL) &&
- (cur->parent->name != NULL) &&
- (cur->parent->name[0] != 'p')) /* p, pre, param */
- xmlOutputBufferWriteString(buf, "\n");
- }
- return;
- }
- xmlOutputBufferWriteString(buf, ">");
- if ((cur->type != XML_ELEMENT_NODE) &&
- (cur->content != NULL)) {
- /*
- * Uses the OutputBuffer property to automatically convert
- * invalids to charrefs
- */
-
- xmlOutputBufferWriteString(buf, (const char *) cur->content);
- }
- if (cur->children != NULL) {
- if ((format) && (info != NULL) && (!info->isinline) &&
- (cur->children->type != HTML_TEXT_NODE) &&
- (cur->children->type != HTML_ENTITY_REF_NODE) &&
- (cur->children != cur->last) &&
- (cur->name != NULL) &&
- (cur->name[0] != 'p')) /* p, pre, param */
- xmlOutputBufferWriteString(buf, "\n");
- htmlNodeListDumpOutput(buf, doc, cur->children, encoding, format);
- if ((format) && (info != NULL) && (!info->isinline) &&
- (cur->last->type != HTML_TEXT_NODE) &&
- (cur->last->type != HTML_ENTITY_REF_NODE) &&
- (cur->children != cur->last) &&
- (cur->name != NULL) &&
- (cur->name[0] != 'p')) /* p, pre, param */
- xmlOutputBufferWriteString(buf, "\n");
- }
- xmlOutputBufferWriteString(buf, "</");
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
- xmlOutputBufferWriteString(buf, ":");
- }
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWriteString(buf, ">");
- if ((format) && (info != NULL) && (!info->isinline) &&
- (cur->next != NULL)) {
- if ((cur->next->type != HTML_TEXT_NODE) &&
- (cur->next->type != HTML_ENTITY_REF_NODE) &&
- (cur->parent != NULL) &&
- (cur->parent->name != NULL) &&
- (cur->parent->name[0] != 'p')) /* p, pre, param */
- xmlOutputBufferWriteString(buf, "\n");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->nsDef)
+ xmlNsListDumpOutput(buf, cur->nsDef);
+ attr = cur->properties;
+ while (attr != NULL) {
+ htmlAttrDumpOutput(buf, doc, attr);
+ attr = attr->next;
+ }
+
+ if ((info != NULL) && (info->empty)) {
+ xmlOutputBufferWriteString(buf, ">");
+ } else if (cur->children == NULL) {
+ if ((info != NULL) && (info->saveEndTag != 0) &&
+ (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
+ (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
+ xmlOutputBufferWriteString(buf, ">");
+ } else {
+ xmlOutputBufferWriteString(buf, "></");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ">");
+ }
+ } else {
+ xmlOutputBufferWriteString(buf, ">");
+ if ((format) && (info != NULL) && (!info->isinline) &&
+ (cur->children->type != HTML_TEXT_NODE) &&
+ (cur->children->type != HTML_ENTITY_REF_NODE) &&
+ (cur->children != cur->last) &&
+ (cur->name != NULL) &&
+ (cur->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ parent = cur;
+ cur = cur->children;
+ continue;
+ }
+
+ if ((format) && (cur->next != NULL) &&
+ (info != NULL) && (!info->isinline)) {
+ if ((cur->next->type != HTML_TEXT_NODE) &&
+ (cur->next->type != HTML_ENTITY_REF_NODE) &&
+ (parent != NULL) &&
+ (parent->name != NULL) &&
+ (parent->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+
+ break;
+
+ case XML_ATTRIBUTE_NODE:
+ htmlAttrDumpOutput(buf, doc, (xmlAttrPtr) cur);
+ break;
+
+ case HTML_TEXT_NODE:
+ if (cur->content == NULL)
+ break;
+ if (((cur->name == (const xmlChar *)xmlStringText) ||
+ (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
+ ((parent == NULL) ||
+ ((xmlStrcasecmp(parent->name, BAD_CAST "script")) &&
+ (xmlStrcasecmp(parent->name, BAD_CAST "style"))))) {
+ xmlChar *buffer;
+
+ buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
+ if (buffer != NULL) {
+ xmlOutputBufferWriteString(buf, (const char *)buffer);
+ xmlFree(buffer);
+ }
+ } else {
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ }
+ break;
+
+ case HTML_COMMENT_NODE:
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, "<!--");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ xmlOutputBufferWriteString(buf, "-->");
+ }
+ break;
+
+ case HTML_PI_NODE:
+ if (cur->name != NULL) {
+ xmlOutputBufferWriteString(buf, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, " ");
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->content);
+ }
+ xmlOutputBufferWriteString(buf, ">");
+ }
+ break;
+
+ case HTML_ENTITY_REF_NODE:
+ xmlOutputBufferWriteString(buf, "&");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ";");
+ break;
+
+ case HTML_PRESERVE_NODE:
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ while (1) {
+ if (cur == root)
+ return;
+ if (cur->next != NULL) {
+ cur = cur->next;
+ break;
+ }
+
+ cur = parent;
+ /* cur->parent was validated when descending. */
+ parent = cur->parent;
+
+ if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
+ (cur->type == XML_DOCUMENT_NODE)) {
+ xmlOutputBufferWriteString(buf, "\n");
+ } else {
+ if ((format) && (cur->ns == NULL))
+ info = htmlTagLookup(cur->name);
+ else
+ info = NULL;
+
+ if ((format) && (info != NULL) && (!info->isinline) &&
+ (cur->last->type != HTML_TEXT_NODE) &&
+ (cur->last->type != HTML_ENTITY_REF_NODE) &&
+ (cur->children != cur->last) &&
+ (cur->name != NULL) &&
+ (cur->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+
+ xmlOutputBufferWriteString(buf, "</");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ">");
+
+ if ((format) && (info != NULL) && (!info->isinline) &&
+ (cur->next != NULL)) {
+ if ((cur->next->type != HTML_TEXT_NODE) &&
+ (cur->next->type != HTML_ENTITY_REF_NODE) &&
+ (parent != NULL) &&
+ (parent->name != NULL) &&
+ (parent->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+ }
+ }
}
}
@@ -997,63 +968,45 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
* @buf: the HTML buffer output
* @doc: the document
* @cur: the current node
- * @encoding: the encoding string
+ * @encoding: the encoding string (unused)
*
* Dump an HTML node, recursive behaviour,children are printed too,
* and formatting returns/spaces are added.
*/
void
htmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
- xmlNodePtr cur, const char *encoding) {
- htmlNodeDumpFormatOutput(buf, doc, cur, encoding, 1);
+ xmlNodePtr cur, const char *encoding ATTRIBUTE_UNUSED) {
+ htmlNodeDumpFormatOutput(buf, doc, cur, NULL, 1);
}
/**
* htmlDocContentDumpFormatOutput:
* @buf: the HTML buffer output
* @cur: the document
- * @encoding: the encoding string
+ * @encoding: the encoding string (unused)
* @format: should formatting spaces been added
*
* Dump an HTML document.
*/
void
htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
- const char *encoding, int format) {
- int type;
-
- xmlInitParser();
-
- if ((buf == NULL) || (cur == NULL))
- return;
-
- /*
- * force to output the stuff as HTML, especially for entities
- */
- type = cur->type;
- cur->type = XML_HTML_DOCUMENT_NODE;
- if (cur->intSubset != NULL) {
- htmlDtdDumpOutput(buf, cur, NULL);
- }
- if (cur->children != NULL) {
- htmlNodeListDumpOutput(buf, cur, cur->children, encoding, format);
- }
- xmlOutputBufferWriteString(buf, "\n");
- cur->type = (xmlElementType) type;
+ const char *encoding ATTRIBUTE_UNUSED,
+ int format) {
+ htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, NULL, format);
}
/**
* htmlDocContentDumpOutput:
* @buf: the HTML buffer output
* @cur: the document
- * @encoding: the encoding string
+ * @encoding: the encoding string (unused)
*
* Dump an HTML document. Formatting return/spaces are added.
*/
void
htmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
- const char *encoding) {
- htmlDocContentDumpFormatOutput(buf, cur, encoding, 1);
+ const char *encoding ATTRIBUTE_UNUSED) {
+ htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, NULL, 1);
}
/************************************************************************
diff --git a/contrib/libs/libxml/README.md b/contrib/libs/libxml/README.md
new file mode 100644
index 0000000000..ce83d6201f
--- /dev/null
+++ b/contrib/libs/libxml/README.md
@@ -0,0 +1,121 @@
+# libxml2
+
+libxml2 is an XML toolkit implemented in C, originally developed for
+the GNOME Project.
+
+Full documentation is available at
+<https://gitlab.gnome.org/GNOME/libxml2/-/wikis>.
+
+Bugs should be reported at
+<https://gitlab.gnome.org/GNOME/libxml2/-/issues>.
+
+A mailing list xml@gnome.org is available. You can subscribe at
+<https://mail.gnome.org/mailman/listinfo/xml>. The list archive is at
+<https://mail.gnome.org/archives/xml/>.
+
+## License
+
+This code is released under the MIT License, see the Copyright file.
+
+## Build instructions
+
+libxml2 can be built with GNU Autotools, CMake, or several other build
+systems in platform-specific subdirectories.
+
+### Autotools (for POSIX systems like Linux, BSD, macOS)
+
+If you build from a Git tree, you have to install Autotools and start
+by generating the configuration files with:
+
+ ./autogen.sh
+
+If you build from a source tarball, extract the archive with:
+
+ tar xf libxml2-xxx.tar.gz
+ cd libxml2-xxx
+
+To see a list of build options:
+
+ ./configure --help
+
+Also see the INSTALL file for additional instructions. Then you can
+configure and build the library:
+
+ ./configure [possible options]
+ make
+
+Now you can run the test suite with:
+
+ make check
+
+Please report test failures to the mailing list or bug tracker.
+
+Then you can install the library:
+
+ make install
+
+At that point you may have to rerun ldconfig or a similar utility to
+update your list of installed shared libs.
+
+### CMake (mainly for Windows)
+
+Another option for compiling libxml is using CMake:
+
+ cmake -E tar xf libxml2-xxx.tar.gz
+ cmake -S libxml2-xxx -B libxml2-xxx-build [possible options]
+ cmake --build libxml2-xxx-build
+ cmake --install libxml2-xxx-build
+
+Common CMake options include:
+
+ -D BUILD_SHARED_LIBS=OFF # build static libraries
+ -D CMAKE_BUILD_TYPE=Release # specify build type
+ -D CMAKE_INSTALL_PREFIX=/usr/local # specify the install path
+ -D LIBXML2_WITH_ICONV=OFF # disable iconv
+ -D LIBXML2_WITH_LZMA=OFF # disable liblzma
+ -D LIBXML2_WITH_PYTHON=OFF # disable Python
+ -D LIBXML2_WITH_ZLIB=OFF # disable libz
+
+You can also open the libxml source directory with its CMakeLists.txt
+directly in various IDEs such as CLion, QtCreator, or Visual Studio.
+
+## Dependencies
+
+Libxml does not require any other libraries. A platform with somewhat
+recent POSIX support should be sufficient (please report any violation
+to this rule you may find).
+
+However, if found at configuration time, libxml will detect and use
+the following libraries:
+
+- [libz](https://zlib.net/), a highly portable and widely available
+ compression library.
+- [liblzma](https://tukaani.org/xz/), another compression library.
+- [libiconv](https://www.gnu.org/software/libiconv/), a character encoding
+ conversion library. The iconv function is part of POSIX.1-2001, so
+ libiconv isn't required on modern UNIX-like systems like Linux, BSD or
+ macOS.
+- [ICU](https://icu.unicode.org/), a Unicode library. Mainly useful as an
+ alternative to iconv on Windows. Unnecessary on most other systems.
+
+## Contributing
+
+The current version of the code can be found in GNOME's GitLab at
+at <https://gitlab.gnome.org/GNOME/libxml2>. The best way to get involved
+is by creating issues and merge requests on GitLab. Alternatively, you can
+start discussions and send patches to the mailing list. If you want to
+work with patches, please format them with git-format-patch and use plain
+text attachments.
+
+All code must conform to C89 and pass the GitLab CI tests. Add regression
+tests if possible.
+
+## Authors
+
+- Daniel Veillard
+- Bjorn Reese
+- William Brack
+- Igor Zlatkovic for the Windows port
+- Aleksey Sanin
+- Nick Wellnhofer
+
diff --git a/contrib/libs/libxml/SAX2.c b/contrib/libs/libxml/SAX2.c
index 5f141f9a3c..031924652a 100644
--- a/contrib/libs/libxml/SAX2.c
+++ b/contrib/libs/libxml/SAX2.c
@@ -590,36 +590,6 @@ xmlSAX2GetEntity(void *ctx, const xmlChar *name)
} else {
ret = xmlGetDocEntity(ctxt->myDoc, name);
}
- if ((ret != NULL) &&
- ((ctxt->validate) || (ctxt->replaceEntities)) &&
- (ret->children == NULL) &&
- (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
- int val;
-
- /*
- * for validation purposes we really need to fetch and
- * parse the external entity
- */
- xmlNodePtr children;
- unsigned long oldnbent = ctxt->nbentities;
-
- val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
- ret->ExternalID, &children);
- if (val == 0) {
- xmlAddChildList((xmlNodePtr) ret, children);
- } else {
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
- "Failure to process entity %s\n", name, NULL);
- ctxt->validate = 0;
- return(NULL);
- }
- ret->owner = 1;
- if (ret->checked == 0) {
- ret->checked = (ctxt->nbentities - oldnbent + 1) * 2;
- if ((ret->content != NULL) && (xmlStrchr(ret->content, '<')))
- ret->checked |= 1;
- }
- }
return(ret);
}
@@ -772,6 +742,7 @@ xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
"SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
name, NULL);
+ xmlFree(name);
xmlFreeEnumeration(tree);
return;
}
@@ -1652,10 +1623,10 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
ctxt->nodemem = -1;
if (ctxt->linenumbers) {
if (ctxt->input != NULL) {
- if (ctxt->input->line < 65535)
- ret->line = (short) ctxt->input->line;
+ if (ctxt->input->line < USHRT_MAX)
+ ret->line = (unsigned short) ctxt->input->line;
else
- ret->line = 65535;
+ ret->line = USHRT_MAX;
}
}
@@ -1693,23 +1664,23 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
}
}
- /*
- * Insert all the defaulted attributes from the DTD especially namespaces
- */
- if ((!ctxt->html) &&
- ((ctxt->myDoc->intSubset != NULL) ||
- (ctxt->myDoc->extSubset != NULL))) {
- xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
- }
+ if (!ctxt->html) {
+ /*
+ * Insert all the defaulted attributes from the DTD especially
+ * namespaces
+ */
+ if ((ctxt->myDoc->intSubset != NULL) ||
+ (ctxt->myDoc->extSubset != NULL)) {
+ xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
+ }
- /*
- * process all the attributes whose name start with "xmlns"
- */
- if (atts != NULL) {
- i = 0;
- att = atts[i++];
- value = atts[i++];
- if (!ctxt->html) {
+ /*
+ * process all the attributes whose name start with "xmlns"
+ */
+ if (atts != NULL) {
+ i = 0;
+ att = atts[i++];
+ value = atts[i++];
while ((att != NULL) && (value != NULL)) {
if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
(att[3] == 'n') && (att[4] == 's'))
@@ -1718,30 +1689,30 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
att = atts[i++];
value = atts[i++];
}
- }
- }
+ }
- /*
- * Search the namespace, note that since the attributes have been
- * processed, the local namespaces are available.
- */
- ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
- if ((ns == NULL) && (parent != NULL))
- ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
- if ((prefix != NULL) && (ns == NULL)) {
- ns = xmlNewNs(ret, NULL, prefix);
- xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
- "Namespace prefix %s is not defined\n",
- prefix, NULL);
- }
+ /*
+ * Search the namespace, note that since the attributes have been
+ * processed, the local namespaces are available.
+ */
+ ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
+ if ((ns == NULL) && (parent != NULL))
+ ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
+ if ((prefix != NULL) && (ns == NULL)) {
+ ns = xmlNewNs(ret, NULL, prefix);
+ xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+ "Namespace prefix %s is not defined\n",
+ prefix, NULL);
+ }
- /*
- * set the namespace node, making sure that if the default namespace
- * is unbound on a parent we simply keep it NULL
- */
- if ((ns != NULL) && (ns->href != NULL) &&
- ((ns->href[0] != 0) || (ns->prefix != NULL)))
- xmlSetNs(ret, ns);
+ /*
+ * set the namespace node, making sure that if the default namespace
+ * is unbound on a parent we simply keep it NULL
+ */
+ if ((ns != NULL) && (ns->href != NULL) &&
+ ((ns->href[0] != 0) || (ns->prefix != NULL)))
+ xmlSetNs(ret, ns);
+ }
/*
* process all the other attributes
@@ -1916,10 +1887,10 @@ skip:
if (ctxt->linenumbers) {
if (ctxt->input != NULL) {
- if (ctxt->input->line < 65535)
- ret->line = (short) ctxt->input->line;
+ if (ctxt->input->line < USHRT_MAX)
+ ret->line = (unsigned short) ctxt->input->line;
else {
- ret->line = 65535;
+ ret->line = USHRT_MAX;
if (ctxt->options & XML_PARSE_BIG_LINES)
ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
}
@@ -2203,7 +2174,7 @@ xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
* attribute values.
*
* SAX2 callback when an element start has been detected by the parser.
- * It provides the namespace informations for the element, as well as
+ * It provides the namespace information for the element, as well as
* the new namespace declarations on the element.
*/
void
@@ -2296,10 +2267,10 @@ xmlSAX2StartElementNs(void *ctx,
}
if (ctxt->linenumbers) {
if (ctxt->input != NULL) {
- if (ctxt->input->line < 65535)
- ret->line = (short) ctxt->input->line;
+ if (ctxt->input->line < USHRT_MAX)
+ ret->line = (unsigned short) ctxt->input->line;
else
- ret->line = 65535;
+ ret->line = USHRT_MAX;
}
}
@@ -2456,7 +2427,7 @@ xmlSAX2StartElementNs(void *ctx,
* @URI: the element namespace name if available
*
* SAX2 callback when an element end has been detected by the parser.
- * It provides the namespace informations for the element.
+ * It provides the namespace information for the element.
*/
void
xmlSAX2EndElementNs(void *ctx,
@@ -2523,20 +2494,21 @@ xmlSAX2Reference(void *ctx, const xmlChar *name)
}
/**
- * xmlSAX2Characters:
+ * xmlSAX2Text:
* @ctx: the user data (XML parser context)
* @ch: a xmlChar string
* @len: the number of xmlChar
+ * @type: text or cdata
*
- * receiving some chars from the parser.
+ * Append characters.
*/
-void
-xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
+static void
+xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
+ xmlElementType type)
{
- xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlNodePtr lastChild;
- if (ctx == NULL) return;
+ if (ctxt == NULL) return;
#ifdef DEBUG_SAX
xmlGenericError(xmlGenericErrorContext,
"SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
@@ -2565,7 +2537,10 @@ xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
* elements. Use an attribute in the structure !!!
*/
if (lastChild == NULL) {
- lastChild = xmlSAX2TextNode(ctxt, ch, len);
+ if (type == XML_TEXT_NODE)
+ lastChild = xmlSAX2TextNode(ctxt, ch, len);
+ else
+ lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
if (lastChild != NULL) {
ctxt->node->children = lastChild;
ctxt->node->last = lastChild;
@@ -2579,8 +2554,9 @@ xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
}
} else {
int coalesceText = (lastChild != NULL) &&
- (lastChild->type == XML_TEXT_NODE) &&
- (lastChild->name == xmlStringText);
+ (lastChild->type == type) &&
+ ((type != XML_TEXT_NODE) ||
+ (lastChild->name == xmlStringText));
if ((coalesceText) && (ctxt->nodemem != 0)) {
/*
* The whole point of maintaining nodelen and nodemem,
@@ -2637,7 +2613,10 @@ xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
}
} else {
/* Mixed content, first time */
- lastChild = xmlSAX2TextNode(ctxt, ch, len);
+ if (type == XML_TEXT_NODE)
+ lastChild = xmlSAX2TextNode(ctxt, ch, len);
+ else
+ lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
if (lastChild != NULL) {
xmlAddChild(ctxt->node, lastChild);
if (ctxt->node->children != NULL) {
@@ -2650,6 +2629,20 @@ xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
}
/**
+ * xmlSAX2Characters:
+ * @ctx: the user data (XML parser context)
+ * @ch: a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some chars from the parser.
+ */
+void
+xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
+{
+ xmlSAX2Text((xmlParserCtxtPtr) ctx, ch, len, XML_TEXT_NODE);
+}
+
+/**
* xmlSAX2IgnorableWhitespace:
* @ctx: the user data (XML parser context)
* @ch: a xmlChar string
@@ -2696,10 +2689,10 @@ xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
if (ctxt->linenumbers) {
if (ctxt->input != NULL) {
- if (ctxt->input->line < 65535)
- ret->line = (short) ctxt->input->line;
+ if (ctxt->input->line < USHRT_MAX)
+ ret->line = (unsigned short) ctxt->input->line;
else
- ret->line = 65535;
+ ret->line = USHRT_MAX;
}
}
if (ctxt->inSubset == 1) {
@@ -2756,10 +2749,10 @@ xmlSAX2Comment(void *ctx, const xmlChar *value)
if (ret == NULL) return;
if (ctxt->linenumbers) {
if (ctxt->input != NULL) {
- if (ctxt->input->line < 65535)
- ret->line = (short) ctxt->input->line;
+ if (ctxt->input->line < USHRT_MAX)
+ ret->line = (unsigned short) ctxt->input->line;
else
- ret->line = 65535;
+ ret->line = USHRT_MAX;
}
}
@@ -2805,27 +2798,7 @@ xmlSAX2Comment(void *ctx, const xmlChar *value)
void
xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
{
- xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
- xmlNodePtr ret, lastChild;
-
- if (ctx == NULL) return;
-#ifdef DEBUG_SAX
- xmlGenericError(xmlGenericErrorContext,
- "SAX.pcdata(%.10s, %d)\n", value, len);
-#endif
- lastChild = xmlGetLastChild(ctxt->node);
-#ifdef DEBUG_SAX_TREE
- xmlGenericError(xmlGenericErrorContext,
- "add chars to %s \n", ctxt->node->name);
-#endif
- if ((lastChild != NULL) &&
- (lastChild->type == XML_CDATA_SECTION_NODE)) {
- xmlTextConcat(lastChild, value, len);
- } else {
- ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
- if (xmlAddChild(ctxt->node, ret) == NULL)
- xmlFreeNode(ret);
- }
+ xmlSAX2Text((xmlParserCtxtPtr) ctx, value, len, XML_CDATA_SECTION_NODE);
}
static int xmlSAX2DefaultVersionValue = 2;
diff --git a/contrib/libs/libxml/TODO b/contrib/libs/libxml/TODO
index 9c32224982..95e1c343bb 100644
--- a/contrib/libs/libxml/TODO
+++ b/contrib/libs/libxml/TODO
@@ -5,8 +5,6 @@
TODO for the XML parser and stuff:
==================================
- $Id$
-
this tend to be outdated :-\ ...
DOCS:
@@ -202,7 +200,7 @@ Done:
by the XML parser, UTF-8 should be checked when there is no "encoding"
declared !
- Support for UTF-8 and UTF-16 encoding
- => added some convertion routines provided by Martin Durst
+ => added some conversion routines provided by Martin Durst
patched them, got fixes from @@@
I plan to keep everything internally as UTF-8 (or ISO-Latin-X)
this is slightly more costly but more compact, and recent processors
@@ -212,7 +210,7 @@ Done:
is enabled, tested the ISO->UTF-8 stuff
- External entities loading:
- allow override by client code
- - make sure it is alled for all external entities referenced
+ - make sure it is called for all external entities referenced
Done, client code should use xmlSetExternalEntityLoader() to set
the default loading routine. It will be called each time an external
entity entity resolution is triggered.
@@ -245,8 +243,8 @@ Done:
most cases !
- progressive reading. The entity support is a first step toward
- asbtraction of an input stream. A large part of the context is still
- located on the stack, moving to a state machine and putting everyting
+ abstraction of an input stream. A large part of the context is still
+ located on the stack, moving to a state machine and putting everything
in the parsing context should provide an adequate solution.
=> Rather than progressive parsing, give more power to the SAX-like
interface. Currently the DOM-like representation is built but
diff --git a/contrib/libs/libxml/buf.c b/contrib/libs/libxml/buf.c
index d46da36514..24368d379f 100644
--- a/contrib/libs/libxml/buf.c
+++ b/contrib/libs/libxml/buf.c
@@ -83,7 +83,7 @@ struct _xmlBuf {
/**
* xmlBufMemoryError:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
* To be improved...
@@ -98,7 +98,7 @@ xmlBufMemoryError(xmlBufPtr buf, const char *extra)
/**
* xmlBufOverflowError:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a buffer overflow error
* To be improved...
@@ -1233,10 +1233,12 @@ xmlBufBackToBuffer(xmlBufPtr buf) {
* Keep the buffer but provide a truncated size value.
*/
xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer");
+ ret->use = (int) buf->use;
ret->size = INT_MAX;
+ } else {
+ ret->use = (int) buf->use;
+ ret->size = (int) buf->size;
}
- ret->use = (int) buf->use;
- ret->size = (int) buf->size;
ret->alloc = buf->alloc;
ret->content = buf->content;
ret->contentIO = buf->contentIO;
@@ -1332,8 +1334,12 @@ xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) {
int
xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
size_t base, size_t cur) {
- 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 = &buf->content[base];
input->cur = input->base + cur;
diff --git a/contrib/libs/libxml/c14n.c b/contrib/libs/libxml/c14n.c
index 5b3fbe70c6..3efcd92eef 100644
--- a/contrib/libs/libxml/c14n.c
+++ b/contrib/libs/libxml/c14n.c
@@ -132,7 +132,7 @@ static xmlChar *xmlC11NNormalizeString(const xmlChar * input,
/**
* xmlC14NErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of memory error
*/
@@ -147,7 +147,7 @@ xmlC14NErrMemory(const char *extra)
/**
* xmlC14NErrParam:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of param error
*/
@@ -162,7 +162,7 @@ xmlC14NErrParam(const char *extra)
/**
* xmlC14NErrInternal:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of internal error
*/
@@ -177,7 +177,7 @@ xmlC14NErrInternal(const char *extra)
/**
* xmlC14NErrInvalidNode:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of invalid node error
*/
@@ -192,7 +192,7 @@ xmlC14NErrInvalidNode(const char *node_type, const char *extra)
/**
* xmlC14NErrUnknownNode:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of unknown node error
*/
@@ -207,7 +207,7 @@ xmlC14NErrUnknownNode(int node_type, const char *extra)
/**
* xmlC14NErrRelativeNamespace:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of relative namespace error
*/
@@ -228,7 +228,7 @@ xmlC14NErrRelativeNamespace(const char *ns_uri)
* @node: the context node
* @error: the error code
* @msg: the message
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -2033,13 +2033,13 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
}
ret = xmlBufUse(buf->buffer);
- if (ret > 0) {
+ if (ret >= 0) {
*doc_txt_ptr = xmlStrndup(xmlBufContent(buf->buffer), ret);
}
(void) xmlOutputBufferClose(buf);
- if ((*doc_txt_ptr == NULL) && (ret > 0)) {
- xmlC14NErrMemory("coping canonicalized document");
+ if ((*doc_txt_ptr == NULL) && (ret >= 0)) {
+ xmlC14NErrMemory("copying canonicalized document");
return (-1);
}
return (ret);
diff --git a/contrib/libs/libxml/catalog.c b/contrib/libs/libxml/catalog.c
index 7328fd319c..e071b4939f 100644
--- a/contrib/libs/libxml/catalog.c
+++ b/contrib/libs/libxml/catalog.c
@@ -216,7 +216,7 @@ static int xmlCatalogInitialized = 0;
/**
* xmlCatalogErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -234,7 +234,7 @@ xmlCatalogErrMemory(const char *extra)
* @catal: the Catalog entry
* @node: the context node
* @msg: the error message
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a catalog error
*/
@@ -915,6 +915,7 @@ xmlParseCatalogFile(const char *filename) {
inputStream = xmlNewInputStream(ctxt);
if (inputStream == NULL) {
+ xmlFreeParserInputBuffer(buf);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
@@ -924,7 +925,7 @@ xmlParseCatalogFile(const char *filename) {
xmlBufResetInput(buf->buffer, inputStream);
inputPush(ctxt, inputStream);
- if ((ctxt->directory == NULL) && (directory == NULL))
+ if (ctxt->directory == NULL)
directory = xmlParserGetDirectory(filename);
if ((ctxt->directory == NULL) && (directory != NULL))
ctxt->directory = directory;
@@ -2069,8 +2070,7 @@ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
if (ret != NULL) {
break;
- } else if ((catal->children != NULL) &&
- (catal->children->depth > MAX_CATAL_DEPTH)) {
+ } else if (catal->children->depth > MAX_CATAL_DEPTH) {
ret = NULL;
break;
}
@@ -2353,12 +2353,13 @@ xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
xmlCatalogEntryType type = XML_CATA_NONE;
cur = xmlParseSGMLCatalogName(cur, &name);
- if (name == NULL) {
+ if (cur == NULL || name == NULL) {
/* error */
break;
}
if (!IS_BLANK_CH(*cur)) {
/* error */
+ xmlFree(name);
break;
}
SKIP_BLANKS;
@@ -3254,6 +3255,7 @@ xmlLoadCatalogs(const char *pathss) {
while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur)))
cur++;
path = xmlStrndup((const xmlChar *)paths, cur - paths);
+ if (path != NULL) {
#ifdef _WIN32
iLen = strlen((const char*)path);
for(i = 0; i < iLen; i++) {
@@ -3262,7 +3264,6 @@ xmlLoadCatalogs(const char *pathss) {
}
}
#endif
- if (path != NULL) {
xmlLoadCatalog((const char *) path);
xmlFree(path);
}
@@ -3427,9 +3428,10 @@ xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace)
(xmlStrEqual(type, BAD_CAST "catalog"))) {
xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
xmlCatalogDefaultPrefer);
- xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
+ if (xmlDefaultCatalog != NULL) {
+ xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
orig, NULL, xmlCatalogDefaultPrefer, NULL);
-
+ }
xmlRMutexUnlock(xmlCatalogMutex);
return(0);
}
diff --git a/contrib/libs/libxml/config-linux.h b/contrib/libs/libxml/config-linux.h
index 86d1ad76f3..04bc93369e 100644
--- a/contrib/libs/libxml/config-linux.h
+++ b/contrib/libs/libxml/config-linux.h
@@ -1,6 +1,9 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
+/* A form that will not confuse apibuild.py */
+#define ATTRIBUTE_DESTRUCTOR __attribute__((destructor))
+
/* Type cast for the gethostbyname() argument */
#define GETHOSTBYNAME_ARG_CAST /**/
@@ -10,13 +13,17 @@
/* Define to 1 if you have the <arpa/nameser.h> header file. */
#define HAVE_ARPA_NAMESER_H 1
+/* Define if __attribute__((destructor)) is accepted */
+#define HAVE_ATTRIBUTE_DESTRUCTOR 1
+
/* Whether struct sockaddr::__ss_family exists */
/* #undef HAVE_BROKEN_SS_FAMILY */
/* Define to 1 if you have the <ctype.h> header file. */
#define HAVE_CTYPE_H 1
-/* Define to 1 if you have the <dirent.h> header file. */
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
#define HAVE_DIRENT_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
@@ -55,18 +62,9 @@
/* Define to 1 if you have the `isascii' function. */
#define HAVE_ISASCII 1
-/* Define if isinf is there */
-#define HAVE_ISINF /**/
-
-/* Define if isnan is there */
-#define HAVE_ISNAN /**/
-
/* Define if history library is there (-lhistory) */
/* #undef HAVE_LIBHISTORY */
-/* Define if pthread library is there (-lpthread) */
-#define HAVE_LIBPTHREAD /**/
-
/* Define if readline library is there (-lreadline) */
/* #undef HAVE_LIBREADLINE */
@@ -85,9 +83,6 @@
/* Define to 1 if you have the <math.h> header file. */
#define HAVE_MATH_H 1
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
/* Define to 1 if you have the `mmap' function. */
#define HAVE_MMAP 1
@@ -156,6 +151,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
@@ -219,7 +217,7 @@
#define HAVE_VSPRINTF 1
/* Define to 1 if you have the <zlib.h> header file. */
-#define HAVE_ZLIB_H 1
+/* #undef HAVE_ZLIB_H */
/* Whether __va_copy() is available */
/* #undef HAVE___VA_COPY */
@@ -237,24 +235,26 @@
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
+#define PACKAGE_NAME "libxml2"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
+#define PACKAGE_STRING "libxml2 2.9.13"
/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
+#define PACKAGE_TARNAME "libxml2"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
+#define PACKAGE_VERSION "2.9.13"
/* Type cast for the send() function 2nd arg */
#define SEND_ARG2_CAST /**/
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
#define STDC_HEADERS 1
/* Support for IPv6 */
@@ -264,7 +264,7 @@
#define VA_LIST_IS_ARRAY 1
/* Version number of package */
-#define VERSION "2.9.10"
+#define VERSION "2.9.13"
/* Determine what socket length (socklen_t) data type is */
#define XML_SOCKLEN_T socklen_t
diff --git a/contrib/libs/libxml/debugXML.c b/contrib/libs/libxml/debugXML.c
index d855555861..7a2ca47d22 100644
--- a/contrib/libs/libxml/debugXML.c
+++ b/contrib/libs/libxml/debugXML.c
@@ -1342,7 +1342,7 @@ xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
* @output: the FILE * for the output
* @str: the string
*
- * Dumps informations about the string, shorten it if necessary
+ * Dumps information about the string, shorten it if necessary
*/
void
xmlDebugDumpString(FILE * output, const xmlChar * str)
@@ -2190,7 +2190,7 @@ xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
* @node2: unused
*
* Implements the XML shell function "grep"
- * dumps informations about the node (namespace, attributes, content).
+ * dumps information about the node (namespace, attributes, content).
*
* Returns 0
*/
@@ -2268,7 +2268,7 @@ xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
* @node2: unused
*
* Implements the XML shell function "dir"
- * dumps informations about the node (namespace, attributes, content).
+ * dumps information about the node (namespace, attributes, content).
*
* Returns 0
*/
@@ -2302,7 +2302,7 @@ xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
* @node2: unused
*
* Implements the XML shell function "dir"
- * dumps informations about the node (namespace, attributes, content).
+ * dumps information about the node (namespace, attributes, content).
*
* Returns 0
*/
@@ -2900,7 +2900,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
fprintf(ctxt->output, "\tbye leave shell\n");
fprintf(ctxt->output, "\tcat [node] display node or current node\n");
fprintf(ctxt->output, "\tcd [path] change directory to path or to root\n");
- fprintf(ctxt->output, "\tdir [path] dumps informations about the node (namespace, attributes, content)\n");
+ fprintf(ctxt->output, "\tdir [path] dumps information about the node (namespace, attributes, content)\n");
fprintf(ctxt->output, "\tdu [path] show the structure of the subtree under path or the current node\n");
fprintf(ctxt->output, "\texit leave shell\n");
fprintf(ctxt->output, "\thelp display this help\n");
diff --git a/contrib/libs/libxml/dict.c b/contrib/libs/libxml/dict.c
index 63febfb00c..e198c22d35 100644
--- a/contrib/libs/libxml/dict.c
+++ b/contrib/libs/libxml/dict.c
@@ -10,7 +10,7 @@
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
* Author: daniel@veillard.com
@@ -429,7 +429,7 @@ xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
unsigned long value = seed;
if (name == NULL) return(0);
- value = *name;
+ value += *name;
value <<= 5;
if (namelen > 10) {
value += name[namelen - 1];
diff --git a/contrib/libs/libxml/elfgcchack.h b/contrib/libs/libxml/elfgcchack.h
index af8ad1148d..301daf303e 100644
--- a/contrib/libs/libxml/elfgcchack.h
+++ b/contrib/libs/libxml/elfgcchack.h
@@ -7973,6 +7973,18 @@ extern __typeof (xmlPopInputCallbacks) xmlPopInputCallbacks__internal_alias __at
#endif
#endif
+#if defined(LIBXML_OUTPUT_ENABLED)
+#ifdef bottom_xmlIO
+#undef xmlPopOutputCallbacks
+extern __typeof (xmlPopOutputCallbacks) xmlPopOutputCallbacks __attribute((alias("xmlPopOutputCallbacks__internal_alias")));
+#else
+#ifndef xmlPopOutputCallbacks
+extern __typeof (xmlPopOutputCallbacks) xmlPopOutputCallbacks__internal_alias __attribute((visibility("hidden")));
+#define xmlPopOutputCallbacks xmlPopOutputCallbacks__internal_alias
+#endif
+#endif
+#endif
+
#if defined(LIBXML_TREE_ENABLED)
#ifdef bottom_tree
#undef xmlPreviousElementSibling
diff --git a/contrib/libs/libxml/encoding.c b/contrib/libs/libxml/encoding.c
index 89ac8dd2c9..945d2c4470 100644
--- a/contrib/libs/libxml/encoding.c
+++ b/contrib/libs/libxml/encoding.c
@@ -80,7 +80,7 @@ static int xmlLittleEndian = 1;
/**
* xmlEncodingErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -174,7 +174,7 @@ closeIcuConverter(uconv_t *conv)
* Returns 0 if success, or -1 otherwise
* 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 consumed.
+ * The value of @outlen after return is the number of octets produced.
*/
static int
asciiToUTF8(unsigned char* out, int *outlen,
@@ -221,7 +221,7 @@ asciiToUTF8(unsigned char* out, int *outlen,
* Returns 0 if success, -2 if the transcoding fails, or -1 otherwise
* 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 consumed.
+ * The value of @outlen after return is the number of octets produced.
*/
static int
UTF8Toascii(unsigned char* out, int *outlen,
@@ -305,7 +305,7 @@ UTF8Toascii(unsigned char* out, int *outlen,
* Returns the number of bytes written if success, or -1 otherwise
* 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 consumed.
+ * The value of @outlen after return is the number of octets produced.
*/
int
isolat1ToUTF8(unsigned char* out, int *outlen,
@@ -377,6 +377,11 @@ UTF8ToUTF8(unsigned char* out, int *outlen,
if (len < 0)
return(-1);
+ /*
+ * FIXME: Conversion functions must assure valid UTF-8, so we have
+ * to check for UTF-8 validity. Preferably, this converter shouldn't
+ * be used at all.
+ */
memcpy(out, inb, len);
*outlen = len;
@@ -400,7 +405,7 @@ UTF8ToUTF8(unsigned char* out, int *outlen,
or -1 otherwise
* 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 consumed.
+ * The value of @outlen after return is the number of octets produced.
*/
int
UTF8Toisolat1(unsigned char* out, int *outlen,
@@ -500,13 +505,18 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
{
unsigned char* outstart = out;
const unsigned char* processed = inb;
- unsigned char* outend = out + *outlen;
+ unsigned char* outend;
unsigned short* in = (unsigned short*) inb;
unsigned short* inend;
unsigned int c, d, inlen;
unsigned char *tmp;
int bits;
+ if (*outlen == 0) {
+ *inlenb = 0;
+ return(0);
+ }
+ outend = out + *outlen;
if ((*inlenb % 2) == 1)
(*inlenb)--;
inlen = *inlenb / 2;
@@ -521,7 +531,7 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
in++;
}
if ((c & 0xFC00) == 0xD800) { /* surrogates */
- if (in >= inend) { /* (in > inend) shouldn't happens */
+ if (in >= inend) { /* handle split mutli-byte characters */
break;
}
if (xmlLittleEndian) {
@@ -738,38 +748,39 @@ UTF16BEToUTF8(unsigned char* out, int *outlen,
{
unsigned char* outstart = out;
const unsigned char* processed = inb;
- unsigned char* outend = out + *outlen;
+ unsigned char* outend;
unsigned short* in = (unsigned short*) inb;
unsigned short* inend;
unsigned int c, d, inlen;
unsigned char *tmp;
int bits;
+ if (*outlen == 0) {
+ *inlenb = 0;
+ return(0);
+ }
+ outend = out + *outlen;
if ((*inlenb % 2) == 1)
(*inlenb)--;
inlen = *inlenb / 2;
inend= in + inlen;
- while (in < inend) {
+ while ((in < inend) && (out - outstart + 5 < *outlen)) {
if (xmlLittleEndian) {
tmp = (unsigned char *) in;
c = *tmp++;
- c = c << 8;
- c = c | (unsigned int) *tmp;
+ c = (c << 8) | (unsigned int) *tmp;
in++;
} else {
c= *in++;
}
if ((c & 0xFC00) == 0xD800) { /* surrogates */
- if (in >= inend) { /* (in > inend) shouldn't happens */
- *outlen = out - outstart;
- *inlenb = processed - inb;
- return(-2);
+ if (in >= inend) { /* handle split mutli-byte characters */
+ break;
}
if (xmlLittleEndian) {
tmp = (unsigned char *) in;
d = *tmp++;
- d = d << 8;
- d = d | (unsigned int) *tmp;
+ d = (d << 8) | (unsigned int) *tmp;
in++;
} else {
d= *in++;
@@ -1493,16 +1504,25 @@ xmlRegisterCharEncodingHandler(xmlCharEncodingHandlerPtr handler) {
if ((handler == NULL) || (handlers == NULL)) {
xmlEncodingErr(XML_I18N_NO_HANDLER,
"xmlRegisterCharEncodingHandler: NULL handler !\n", NULL);
- return;
+ goto free_handler;
}
if (nbCharEncodingHandler >= MAX_ENCODING_HANDLERS) {
xmlEncodingErr(XML_I18N_EXCESS_HANDLER,
"xmlRegisterCharEncodingHandler: Too many handler registered, see %s\n",
"MAX_ENCODING_HANDLERS");
- return;
+ goto free_handler;
}
handlers[nbCharEncodingHandler++] = handler;
+ return;
+
+free_handler:
+ if (handler != NULL) {
+ if (handler->name != NULL) {
+ xmlFree(handler->name);
+ }
+ xmlFree(handler);
+ }
}
/**
@@ -1794,7 +1814,7 @@ xmlFindCharEncodingHandler(const char *name) {
* @cd: iconv converter data structure
* @out: a pointer to an array of bytes to store the result
* @outlen: the length of @out
- * @in: a pointer to an array of ISO Latin 1 chars
+ * @in: a pointer to an array of input bytes
* @inlen: the length of @in
*
* Returns 0 if success, or
@@ -1805,7 +1825,7 @@ xmlFindCharEncodingHandler(const char *name) {
*
* The value of @inlen after return is the number of octets consumed
* as the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
*/
static int
xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
@@ -1813,7 +1833,7 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
size_t icv_inlen, icv_outlen;
const char *icv_in = (const char *) in;
char *icv_out = (char *) out;
- int ret;
+ size_t ret;
if ((out == NULL) || (outlen == NULL) || (inlen == NULL) || (in == NULL)) {
if (outlen != NULL) *outlen = 0;
@@ -1824,7 +1844,7 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
ret = iconv(cd, (ICONV_CONST char **) &icv_in, &icv_inlen, &icv_out, &icv_outlen);
*inlen -= icv_inlen;
*outlen -= icv_outlen;
- if ((icv_inlen != 0) || (ret == -1)) {
+ if ((icv_inlen != 0) || (ret == (size_t) -1)) {
#ifdef EILSEQ
if (errno == EILSEQ) {
return -2;
@@ -1861,7 +1881,7 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
* @toUnicode : non-zero if toUnicode. 0 otherwise.
* @out: a pointer to an array of bytes to store the result
* @outlen: the length of @out
- * @in: a pointer to an array of ISO Latin 1 chars
+ * @in: a pointer to an array of input bytes
* @inlen: the length of @in
* @flush: if true, indicates end of input
*
@@ -1873,7 +1893,7 @@ xmlIconvWrapper(iconv_t cd, unsigned char *out, int *outlen,
*
* The value of @inlen after return is the number of octets consumed
* as the return value is positive, else unpredictable.
- * The value of @outlen after return is the number of octets consumed.
+ * The value of @outlen after return is the number of octets produced.
*/
static int
xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
@@ -1922,6 +1942,25 @@ xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
* *
************************************************************************/
+/**
+ * xmlEncInputChunk:
+ * @handler: encoding handler
+ * @out: a pointer to an array of bytes to store the result
+ * @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.
+ */
static int
xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
int *outlen, const unsigned char *in, int *inlen, int flush) {
@@ -1930,6 +1969,8 @@ xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
if (handler->input != NULL) {
ret = handler->input(out, outlen, in, inlen);
+ if (ret > 0)
+ ret = 0;
}
#ifdef LIBXML_ICONV_ENABLED
else if (handler->iconv_in != NULL) {
@@ -1951,7 +1992,25 @@ xmlEncInputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
return(ret);
}
-/* Returns -4 if no output function was found. */
+/**
+ * xmlEncOutputChunk:
+ * @handler: encoding handler
+ * @out: a pointer to an array of bytes to store the result
+ * @outlen: the length of @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.
+ *
+ * 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.
+ */
static int
xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
int *outlen, const unsigned char *in, int *inlen) {
@@ -1959,6 +2018,8 @@ xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
if (handler->output != NULL) {
ret = handler->output(out, outlen, in, inlen);
+ if (ret > 0)
+ ret = 0;
}
#ifdef LIBXML_ICONV_ENABLED
else if (handler->iconv_out != NULL) {
@@ -1968,7 +2029,7 @@ xmlEncOutputChunk(xmlCharEncodingHandler *handler, unsigned char *out,
#ifdef LIBXML_ICU_ENABLED
else if (handler->uconv_out != NULL) {
ret = xmlUconvWrapper(handler->uconv_out, 0, out, outlen, in, inlen,
- TRUE);
+ 1);
}
#endif /* LIBXML_ICU_ENABLED */
else {
@@ -2064,7 +2125,7 @@ xmlCharEncFirstLineInt(xmlCharEncodingHandler *handler, xmlBufferPtr out,
*/
if (ret == -3) ret = 0;
if (ret == -1) ret = 0;
- return(ret);
+ return(written ? written : ret);
}
/**
@@ -2194,7 +2255,7 @@ xmlCharEncFirstLineInput(xmlParserInputBufferPtr input, int len)
*/
if (ret == -3) ret = 0;
if (ret == -1) ret = 0;
- return(ret);
+ return(c_out ? c_out : ret);
}
/**
@@ -2404,7 +2465,7 @@ xmlCharEncOutput(xmlOutputBufferPtr output, int init)
{
int ret;
size_t written;
- size_t writtentot = 0;
+ int writtentot = 0;
size_t toconv;
int c_in;
int c_out;
@@ -2437,7 +2498,7 @@ retry:
xmlGenericError(xmlGenericErrorContext,
"initialized encoder\n");
#endif
- return(0);
+ return(c_out);
}
/*
@@ -2445,7 +2506,7 @@ retry:
*/
toconv = xmlBufUse(in);
if (toconv == 0)
- return (0);
+ return (writtentot);
if (toconv > 64 * 1024)
toconv = 64 * 1024;
if (toconv * 4 >= written) {
@@ -2550,7 +2611,7 @@ retry:
goto retry;
}
}
- return(ret);
+ return(writtentot ? writtentot : ret);
}
#endif
@@ -2579,7 +2640,6 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
int written;
int writtentot = 0;
int toconv;
- int output = 0;
if (handler == NULL) return(-1);
if (out == NULL) return(-1);
@@ -2632,8 +2692,6 @@ retry:
ret = -3;
}
- if (ret >= 0) output += ret;
-
/*
* Attempt to handle error cases
*/
@@ -2715,7 +2773,7 @@ retry:
goto retry;
}
}
- return(ret);
+ return(writtentot ? writtentot : ret);
}
/**
diff --git a/contrib/libs/libxml/entities.c b/contrib/libs/libxml/entities.c
index d575e9d177..1a8f86f0dc 100644
--- a/contrib/libs/libxml/entities.c
+++ b/contrib/libs/libxml/entities.c
@@ -71,7 +71,7 @@ static xmlEntity xmlEntityApos = {
/**
* xmlEntitiesErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -210,7 +210,7 @@ xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
const xmlChar *content) {
xmlDictPtr dict = NULL;
xmlEntitiesTablePtr table = NULL;
- xmlEntityPtr ret;
+ xmlEntityPtr ret, predef;
if (name == NULL)
return(NULL);
@@ -223,6 +223,44 @@ xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
case XML_INTERNAL_GENERAL_ENTITY:
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
+ predef = xmlGetPredefinedEntity(name);
+ if (predef != NULL) {
+ int valid = 0;
+
+ /* 4.6 Predefined Entities */
+ if ((type == XML_INTERNAL_GENERAL_ENTITY) &&
+ (content != NULL)) {
+ int c = predef->content[0];
+
+ if (((content[0] == c) && (content[1] == 0)) &&
+ ((c == '>') || (c == '\'') || (c == '"'))) {
+ valid = 1;
+ } else if ((content[0] == '&') && (content[1] == '#')) {
+ if (content[2] == 'x') {
+ xmlChar *hex = BAD_CAST "0123456789ABCDEF";
+ xmlChar ref[] = "00;";
+
+ ref[0] = hex[c / 16 % 16];
+ ref[1] = hex[c % 16];
+ if (xmlStrcasecmp(&content[3], ref) == 0)
+ valid = 1;
+ } else {
+ xmlChar ref[] = "00;";
+
+ ref[0] = '0' + c / 10 % 10;
+ ref[1] = '0' + c % 10;
+ if (xmlStrEqual(&content[2], ref))
+ valid = 1;
+ }
+ }
+ }
+ if (!valid) {
+ xmlEntitiesErr(XML_ERR_ENTITY_PROCESSING,
+ "xmlAddEntity: invalid redeclaration of predefined"
+ " entity");
+ return(NULL);
+ }
+ }
if (dtd->entities == NULL)
dtd->entities = xmlHashCreateDict(0, dict);
table = dtd->entities;
@@ -666,11 +704,25 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
} else {
/*
* We assume we have UTF-8 input.
+ * It must match either:
+ * 110xxxxx 10xxxxxx
+ * 1110xxxx 10xxxxxx 10xxxxxx
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * That is:
+ * cur[0] is 11xxxxxx
+ * cur[1] is 10xxxxxx
+ * cur[2] is 10xxxxxx if cur[0] is 111xxxxx
+ * cur[3] is 10xxxxxx if cur[0] is 1111xxxx
+ * cur[0] is not 11111xxx
*/
char buf[11], *ptr;
int val = 0, l = 1;
- if (*cur < 0xC0) {
+ if (((cur[0] & 0xC0) != 0xC0) ||
+ ((cur[1] & 0xC0) != 0x80) ||
+ (((cur[0] & 0xE0) == 0xE0) && ((cur[2] & 0xC0) != 0x80)) ||
+ (((cur[0] & 0xF0) == 0xF0) && ((cur[3] & 0xC0) != 0x80)) ||
+ (((cur[0] & 0xF8) == 0xF8))) {
xmlEntitiesErr(XML_CHECK_NOT_UTF8,
"xmlEncodeEntities: input not UTF-8");
if (doc != NULL)
diff --git a/contrib/libs/libxml/error.c b/contrib/libs/libxml/error.c
index b7d5b36bc7..9ff1c2ba49 100644
--- a/contrib/libs/libxml/error.c
+++ b/contrib/libs/libxml/error.c
@@ -146,7 +146,7 @@ xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
* xmlParserPrintFileInfo:
* @input: an xmlParserInputPtr input
*
- * Displays the associated file and line informations for the current input
+ * Displays the associated file and line information for the current input
*/
void
@@ -557,6 +557,7 @@ __xmlRaiseError(xmlStructuredErrorFunc schannel,
* of the usual "base" (doc->URL) for the node (bug 152623).
*/
xmlNodePtr prev = baseptr;
+ char *href = NULL;
int inclcount = 0;
while (prev != NULL) {
if (prev->prev == NULL)
@@ -564,21 +565,20 @@ __xmlRaiseError(xmlStructuredErrorFunc schannel,
else {
prev = prev->prev;
if (prev->type == XML_XINCLUDE_START) {
- if (--inclcount < 0)
- break;
+ if (inclcount > 0) {
+ --inclcount;
+ } else {
+ href = (char *) xmlGetProp(prev, BAD_CAST "href");
+ if (href != NULL)
+ break;
+ }
} else if (prev->type == XML_XINCLUDE_END)
inclcount++;
}
}
- if (prev != NULL) {
- if (prev->type == XML_XINCLUDE_START) {
- prev->type = XML_ELEMENT_NODE;
- to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
- prev->type = XML_XINCLUDE_START;
- } else {
- to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
- }
- } else
+ if (href != NULL)
+ to->file = href;
+ else
#endif
to->file = (char *) xmlStrdup(baseptr->doc->URL);
if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
@@ -643,7 +643,7 @@ __xmlRaiseError(xmlStructuredErrorFunc schannel,
* @domain: where the error comes from
* @code: the error code
* @node: the context node
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
diff --git a/contrib/libs/libxml/globals.c b/contrib/libs/libxml/globals.c
index 7bf985f487..0c0bdb44a8 100644
--- a/contrib/libs/libxml/globals.c
+++ b/contrib/libs/libxml/globals.c
@@ -215,7 +215,7 @@ int oldXMLWDcompatibility = 0; /* DEPRECATED */
/**
* xmlParserDebugEntities:
*
- * Global setting, asking the parser to print out debugging informations.
+ * Global setting, asking the parser to print out debugging information.
* while handling entities.
* Disabled by default
*/
diff --git a/contrib/libs/libxml/hash.c b/contrib/libs/libxml/hash.c
index a83d979b64..7b82d2f1b5 100644
--- a/contrib/libs/libxml/hash.c
+++ b/contrib/libs/libxml/hash.c
@@ -11,7 +11,7 @@
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
* Author: breese@users.sourceforge.net
@@ -86,7 +86,7 @@ static unsigned long
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
const xmlChar *name2, const xmlChar *name3) {
unsigned long value = 0L;
- char ch;
+ unsigned long ch;
#ifdef HASH_RANDOMIZATION
value = table->random_seed;
@@ -94,19 +94,19 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
if (name != NULL) {
value += 30 * (*name);
while ((ch = *name++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
}
value = value ^ ((value << 5) + (value >> 3));
if (name2 != NULL) {
while ((ch = *name2++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
}
value = value ^ ((value << 5) + (value >> 3));
if (name3 != NULL) {
while ((ch = *name3++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
}
return (value % table->size);
@@ -121,7 +121,7 @@ xmlHashComputeQKey(xmlHashTablePtr table,
const xmlChar *prefix2, const xmlChar *name2,
const xmlChar *prefix3, const xmlChar *name3) {
unsigned long value = 0L;
- char ch;
+ unsigned long ch;
#ifdef HASH_RANDOMIZATION
value = table->random_seed;
@@ -133,37 +133,37 @@ xmlHashComputeQKey(xmlHashTablePtr table,
if (prefix != NULL) {
while ((ch = *prefix++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
}
if (name != NULL) {
while ((ch = *name++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
}
value = value ^ ((value << 5) + (value >> 3));
if (prefix2 != NULL) {
while ((ch = *prefix2++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
}
if (name2 != NULL) {
while ((ch = *name2++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
}
value = value ^ ((value << 5) + (value >> 3));
if (prefix3 != NULL) {
while ((ch = *prefix3++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
value = value ^ ((value << 5) + (value >> 3) + (unsigned long)':');
}
if (name3 != NULL) {
while ((ch = *name3++) != 0) {
- value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
+ value = value ^ ((value << 5) + (value >> 3) + ch);
}
}
return (value % table->size);
diff --git a/contrib/libs/libxml/include/libxml/c14n.h b/contrib/libs/libxml/include/libxml/c14n.h
index 1237d6c366..bca4591dda 100644
--- a/contrib/libs/libxml/include/libxml/c14n.h
+++ b/contrib/libs/libxml/include/libxml/c14n.h
@@ -16,17 +16,19 @@
*/
#ifndef __XML_C14N_H__
#define __XML_C14N_H__
+
+#include "xmlversion.h"
+
#ifdef LIBXML_C14N_ENABLED
#ifdef LIBXML_OUTPUT_ENABLED
+#include "tree.h"
+#include "xpath.h"
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-#include "xmlversion.h"
-#include "tree.h"
-#include "xpath.h"
-
/*
* XML Canonicalization
* http://www.w3.org/TR/xml-c14n
diff --git a/contrib/libs/libxml/include/libxml/parser.h b/contrib/libs/libxml/include/libxml/parser.h
index a4e97caee8..98a91cd9dc 100644
--- a/contrib/libs/libxml/include/libxml/parser.h
+++ b/contrib/libs/libxml/include/libxml/parser.h
@@ -79,7 +79,7 @@ struct _xmlParserInput {
/**
* xmlParserNodeInfo:
*
- * The parser can be asked to collect Node informations, i.e. at what
+ * The parser can be asked to collect Node information, i.e. at what
* place in the file they were detected.
* NOTE: This is off by default and not very well tested.
*/
@@ -169,6 +169,8 @@ typedef enum {
XML_PARSE_READER = 5
} xmlParserMode;
+typedef struct _xmlStartTag xmlStartTag;
+
/**
* xmlParserCtxt:
*
@@ -231,7 +233,7 @@ struct _xmlParserCtxt {
int nameMax; /* Max depth of the parsing stack */
const xmlChar * *nameTab; /* array of nodes */
- long nbChars; /* number of xmlChar processed */
+ long nbChars; /* unused */
long checkIndex; /* used by progressive parsing lookup */
int keepBlanks; /* ugly but ... */
int disableSAX; /* SAX callbacks are disabled */
@@ -280,7 +282,7 @@ struct _xmlParserCtxt {
int nsMax; /* the size of the arrays */
const xmlChar * *nsTab; /* the array of prefix/namespace name */
int *attallocs; /* which attribute were allocated */
- void * *pushTab; /* array of data for push */
+ xmlStartTag *pushTab; /* array of data for push */
xmlHashTablePtr attsDefault; /* defaulted attributes if any */
xmlHashTablePtr attsSpecial; /* non-CDATA attributes if any */
int nsWellFormed; /* is the document XML Namespace okay */
@@ -296,7 +298,7 @@ struct _xmlParserCtxt {
xmlAttrPtr freeAttrs; /* List of freed attributes nodes */
/*
- * the complete error informations for the last error.
+ * the complete error information for the last error.
*/
xmlError lastError;
xmlParserMode parseMode; /* the parser mode */
@@ -329,7 +331,7 @@ struct _xmlSAXLocator {
* xmlSAXHandler:
*
* A SAX handler is bunch of callbacks called by the parser when processing
- * of the input generate data or structure informations.
+ * of the input generate data or structure information.
*/
/**
@@ -685,7 +687,7 @@ typedef int (*hasExternalSubsetSAXFunc) (void *ctx);
* attribute values.
*
* SAX2 callback when an element start has been detected by the parser.
- * It provides the namespace informations for the element, as well as
+ * It provides the namespace information for the element, as well as
* the new namespace declarations on the element.
*/
@@ -707,7 +709,7 @@ typedef void (*startElementNsSAX2Func) (void *ctx,
* @URI: the element namespace name if available
*
* SAX2 callback when an element end has been detected by the parser.
- * It provides the namespace informations for the element.
+ * It provides the namespace information for the element.
*/
typedef void (*endElementNsSAX2Func) (void *ctx,
diff --git a/contrib/libs/libxml/include/libxml/tree.h b/contrib/libs/libxml/include/libxml/tree.h
index f257fb6a9d..981c4a0d4b 100644
--- a/contrib/libs/libxml/include/libxml/tree.h
+++ b/contrib/libs/libxml/include/libxml/tree.h
@@ -443,7 +443,7 @@ struct _xmlAttr {
struct _xmlDoc *doc; /* the containing document */
xmlNs *ns; /* pointer to the associated namespace */
xmlAttributeType atype; /* the attribute type if validating */
- void *psvi; /* for type/PSVI informations */
+ void *psvi; /* for type/PSVI information */
};
/**
@@ -502,7 +502,7 @@ struct _xmlNode {
xmlChar *content; /* the content */
struct _xmlAttr *properties;/* properties list */
xmlNs *nsDef; /* namespace definitions on this node */
- void *psvi; /* for type/PSVI informations */
+ void *psvi; /* for type/PSVI information */
unsigned short line; /* line number */
unsigned short extra; /* extra data for XPath/XSLT */
};
@@ -578,7 +578,7 @@ struct _xmlDoc {
int charset; /* Internal flag for charset handling,
actually an xmlCharEncoding */
struct _xmlDict *dict; /* dict used to allocate names or NULL */
- void *psvi; /* for type/PSVI informations */
+ void *psvi; /* for type/PSVI information */
int parseFlags; /* set of xmlParserOption used to parse the
document */
int properties; /* set of xmlDocProperties for this document
diff --git a/contrib/libs/libxml/include/libxml/xmlIO.h b/contrib/libs/libxml/include/libxml/xmlIO.h
index a2da495f5f..05b5278c49 100644
--- a/contrib/libs/libxml/include/libxml/xmlIO.h
+++ b/contrib/libs/libxml/include/libxml/xmlIO.h
@@ -217,6 +217,8 @@ xmlParserInputBufferPtr
*/
XMLPUBFUN void XMLCALL
xmlCleanupOutputCallbacks (void);
+XMLPUBFUN int XMLCALL
+ xmlPopOutputCallbacks (void);
XMLPUBFUN void XMLCALL
xmlRegisterDefaultOutputCallbacks(void);
XMLPUBFUN xmlOutputBufferPtr XMLCALL
diff --git a/contrib/libs/libxml/include/libxml/xmlexports.h b/contrib/libs/libxml/include/libxml/xmlexports.h
index f03af0d03a..aceede5ec0 100644
--- a/contrib/libs/libxml/include/libxml/xmlexports.h
+++ b/contrib/libs/libxml/include/libxml/xmlexports.h
@@ -3,43 +3,46 @@
* Description: macros for marking symbols as exportable/importable.
*
* Copy: See Copyright for the status of this software.
- *
- * Author: Igor Zlatovic <igor@zlatkovic.com>
*/
#ifndef __XML_EXPORTS_H__
#define __XML_EXPORTS_H__
-/**
- * XMLPUBFUN, XMLPUBVAR, XMLCALL
- *
- * Macros which declare an exportable function, an exportable variable and
- * the calling convention used for functions.
- *
- * Please use an extra block for every platform/compiler combination when
- * modifying this, rather than overlong #ifdef lines. This helps
- * readability as well as the fact that different compilers on the same
- * platform might need different definitions.
- */
+#if defined(_WIN32) || defined(__CYGWIN__)
+/** DOC_DISABLE */
+
+#ifdef LIBXML_STATIC
+ #define XMLPUBLIC
+#elif defined(IN_LIBXML)
+ #define XMLPUBLIC __declspec(dllexport)
+#else
+ #define XMLPUBLIC __declspec(dllimport)
+#endif
+
+#if defined(LIBXML_FASTCALL)
+ #define XMLCALL __fastcall
+#else
+ #define XMLCALL __cdecl
+#endif
+#define XMLCDECL __cdecl
+
+/** DOC_ENABLE */
+#else /* not Windows */
/**
- * XMLPUBFUN:
- *
- * Macros which declare an exportable function
- */
-#define XMLPUBFUN
-/**
- * XMLPUBVAR:
+ * XMLPUBLIC:
*
- * Macros which declare an exportable variable
+ * Macro which declares a public symbol
*/
-#define XMLPUBVAR extern
+#define XMLPUBLIC
+
/**
* XMLCALL:
*
- * Macros which declare the called convention for exported functions
+ * Macro which declares the calling convention for exported functions
*/
#define XMLCALL
+
/**
* XMLCDECL:
*
@@ -48,100 +51,21 @@
*/
#define XMLCDECL
-/** DOC_DISABLE */
-
-/* Windows platform with MS compiler */
-#if defined(_WIN32) && defined(_MSC_VER)
- #undef XMLPUBFUN
- #undef XMLPUBVAR
- #undef XMLCALL
- #undef XMLCDECL
- #if defined(IN_LIBXML) && !defined(LIBXML_STATIC)
- #define XMLPUBFUN __declspec(dllexport)
- #define XMLPUBVAR __declspec(dllexport)
- #else
- #define XMLPUBFUN
- #if !defined(LIBXML_STATIC)
- #define XMLPUBVAR __declspec(dllimport) extern
- #else
- #define XMLPUBVAR extern
- #endif
- #endif
- #if defined(LIBXML_FASTCALL)
- #define XMLCALL __fastcall
- #else
- #define XMLCALL __cdecl
- #endif
- #define XMLCDECL __cdecl
-#endif
+#endif /* platform switch */
-/* Windows platform with Borland compiler */
-#if defined(_WIN32) && defined(__BORLANDC__)
- #undef XMLPUBFUN
- #undef XMLPUBVAR
- #undef XMLCALL
- #undef XMLCDECL
- #if defined(IN_LIBXML) && !defined(LIBXML_STATIC)
- #define XMLPUBFUN __declspec(dllexport)
- #define XMLPUBVAR __declspec(dllexport) extern
- #else
- #define XMLPUBFUN
- #if !defined(LIBXML_STATIC)
- #define XMLPUBVAR __declspec(dllimport) extern
- #else
- #define XMLPUBVAR extern
- #endif
- #endif
- #define XMLCALL __cdecl
- #define XMLCDECL __cdecl
-#endif
-
-/* Windows platform with GNU compiler (Mingw) */
-#if defined(_WIN32) && defined(__MINGW32__)
- #undef XMLPUBFUN
- #undef XMLPUBVAR
- #undef XMLCALL
- #undef XMLCDECL
- /*
- * if defined(IN_LIBXML) this raises problems on mingw with msys
- * _imp__xmlFree listed as missing. Try to workaround the problem
- * by also making that declaration when compiling client code.
- */
- #if defined(IN_LIBXML) && !defined(LIBXML_STATIC)
- #define XMLPUBFUN __declspec(dllexport)
- #define XMLPUBVAR __declspec(dllexport) extern
- #else
- #define XMLPUBFUN
- #if !defined(LIBXML_STATIC)
- #define XMLPUBVAR __declspec(dllimport) extern
- #else
- #define XMLPUBVAR extern
- #endif
- #endif
- #define XMLCALL __cdecl
- #define XMLCDECL __cdecl
-#endif
+/*
+ * XMLPUBFUN:
+ *
+ * Macro which declares an exportable function
+ */
+#define XMLPUBFUN XMLPUBLIC
-/* Cygwin platform (does not define _WIN32), GNU compiler */
-#if defined(__CYGWIN__)
- #undef XMLPUBFUN
- #undef XMLPUBVAR
- #undef XMLCALL
- #undef XMLCDECL
- #if defined(IN_LIBXML) && !defined(LIBXML_STATIC)
- #define XMLPUBFUN __declspec(dllexport)
- #define XMLPUBVAR __declspec(dllexport)
- #else
- #define XMLPUBFUN
- #if !defined(LIBXML_STATIC)
- #define XMLPUBVAR __declspec(dllimport) extern
- #else
- #define XMLPUBVAR extern
- #endif
- #endif
- #define XMLCALL __cdecl
- #define XMLCDECL __cdecl
-#endif
+/**
+ * XMLPUBVAR:
+ *
+ * Macro which declares an exportable variable
+ */
+#define XMLPUBVAR XMLPUBLIC extern
/* Compatibility */
#if !defined(LIBXML_DLL_IMPORT)
diff --git a/contrib/libs/libxml/include/libxml/xmlschemas.h b/contrib/libs/libxml/include/libxml/xmlschemas.h
index 54855e8b8b..c9bd91bc8b 100644
--- a/contrib/libs/libxml/include/libxml/xmlschemas.h
+++ b/contrib/libs/libxml/include/libxml/xmlschemas.h
@@ -122,7 +122,7 @@ typedef xmlSchemaValidCtxt *xmlSchemaValidCtxtPtr;
* @line: returned line information
*
* A schemas validation locator, a callback called by the validator.
- * This is used when file or node informations are not available
+ * This is used when file or node information are not available
* to find out what file and line number are affected
*
* Returns: 0 in case of success and -1 in case of error
diff --git a/contrib/libs/libxml/include/libxml/xmlversion.h b/contrib/libs/libxml/include/libxml/xmlversion.h
index 8d910e5731..d75d20ef15 100644
--- a/contrib/libs/libxml/include/libxml/xmlversion.h
+++ b/contrib/libs/libxml/include/libxml/xmlversion.h
@@ -1,6 +1,6 @@
/*
- * Summary: compile-time version informations
- * Description: compile-time version informations for the XML library
+ * Summary: compile-time version information
+ * Description: compile-time version information for the XML library
*
* Copy: See Copyright for the status of this software.
*
@@ -29,26 +29,26 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version);
*
* the version string like "1.2.3"
*/
-#define LIBXML_DOTTED_VERSION "2.9.10"
+#define LIBXML_DOTTED_VERSION "2.9.13"
/**
* LIBXML_VERSION:
*
* the version number: 1.2.3 value is 10203
*/
-#define LIBXML_VERSION 20910
+#define LIBXML_VERSION 20913
/**
* LIBXML_VERSION_STRING:
*
* the version number string, 1.2.3 value is "10203"
*/
-#define LIBXML_VERSION_STRING "20910"
+#define LIBXML_VERSION_STRING "20913"
/**
* LIBXML_VERSION_EXTRA:
*
- * extra version information, used to show a CVS compilation
+ * extra version information, used to show a git commit description
*/
#define LIBXML_VERSION_EXTRA ""
@@ -58,7 +58,7 @@ XMLPUBFUN void XMLCALL 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(20910);
+#define LIBXML_TEST_VERSION xmlCheckVersion(20913);
#ifndef VMS
#if 0
diff --git a/contrib/libs/libxml/include/libxml/xpath.h b/contrib/libs/libxml/include/libxml/xpath.h
index 91c7578768..3d3de1fcf4 100644
--- a/contrib/libs/libxml/include/libxml/xpath.h
+++ b/contrib/libs/libxml/include/libxml/xpath.h
@@ -359,8 +359,6 @@ struct _xmlXPathContext {
unsigned long opLimit;
unsigned long opCount;
int depth;
- int maxDepth;
- int maxParserDepth;
};
/*
@@ -373,7 +371,7 @@ typedef xmlXPathCompExpr *xmlXPathCompExprPtr;
/**
* xmlXPathParserContext:
*
- * An XPath parser context. It contains pure parsing informations,
+ * An XPath parser context. It contains pure parsing information,
* an xmlXPathContext, and the stack of objects.
*/
struct _xmlXPathParserContext {
diff --git a/contrib/libs/libxml/libxml2.syms b/contrib/libs/libxml/libxml2.syms
index c17d3d98d2..33bc112c14 100644
--- a/contrib/libs/libxml/libxml2.syms
+++ b/contrib/libs/libxml/libxml2.syms
@@ -2286,3 +2286,10 @@ LIBXML2_2.9.8 {
xmlHashDefaultDeallocator;
} LIBXML2_2.9.1;
+LIBXML2_2.9.11 {
+ global:
+
+# xmlIO
+ xmlPopOutputCallbacks;
+} LIBXML2_2.9.8;
+
diff --git a/contrib/libs/libxml/list.c b/contrib/libs/libxml/list.c
index 24da6b1e9b..2020715519 100644
--- a/contrib/libs/libxml/list.c
+++ b/contrib/libs/libxml/list.c
@@ -9,7 +9,7 @@
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
* Author: Gary.Pennington@uk.sun.com
diff --git a/contrib/libs/libxml/nanoftp.c b/contrib/libs/libxml/nanoftp.c
index 54fa026d1b..18c1ce4377 100644
--- a/contrib/libs/libxml/nanoftp.c
+++ b/contrib/libs/libxml/nanoftp.c
@@ -158,7 +158,7 @@ int have_ipv6(void) {
/**
* xmlFTPErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -172,7 +172,7 @@ xmlFTPErrMemory(const char *extra)
* xmlNanoFTPInit:
*
* Initialize the FTP protocol layer.
- * Currently it just checks for proxy informations,
+ * Currently it just checks for proxy information,
* and get the hostname
*/
@@ -218,7 +218,7 @@ xmlNanoFTPInit(void) {
/**
* xmlNanoFTPCleanup:
*
- * Cleanup the FTP protocol layer. This cleanup proxy informations.
+ * Cleanup the FTP protocol layer. This cleanup proxy information.
*/
void
@@ -250,7 +250,7 @@ xmlNanoFTPCleanup(void) {
* @passwd: the proxy password
* @type: the type of proxy 1 for using SITE, 2 for USER a@b
*
- * Setup the FTP proxy informations.
+ * Setup the FTP proxy information.
* This can also be done by using ftp_proxy ftp_proxy_user and
* ftp_proxy_password environment variables.
*/
@@ -412,7 +412,7 @@ xmlNanoFTPUpdateURL(void *ctx, const char *URL) {
* (Re)Initialize the FTP Proxy context by parsing the URL and finding
* the protocol host port it indicates.
* Should be like ftp://myproxy/ or ftp://myproxy:3128/
- * A NULL URL cleans up proxy informations.
+ * A NULL URL cleans up proxy information.
*/
void
@@ -1251,8 +1251,7 @@ xmlNanoFTPConnectTo(const char *server, int port) {
xmlNanoFTPFreeCtxt(ctxt);
return(NULL);
}
- if (port != 0)
- ctxt->port = port;
+ ctxt->port = port;
res = xmlNanoFTPConnect(ctxt);
if (res < 0) {
xmlNanoFTPFreeCtxt(ctxt);
@@ -1268,7 +1267,7 @@ xmlNanoFTPConnectTo(const char *server, int port) {
*
* Tries to change the remote directory
*
- * Returns -1 incase of error, 1 if CWD worked, 0 if it failed
+ * Returns -1 in case of error, 1 if CWD worked, 0 if it failed
*/
int
@@ -1317,7 +1316,7 @@ xmlNanoFTPCwd(void *ctx, const char *directory) {
*
* Tries to delete an item (file or directory) from server
*
- * Returns -1 incase of error, 1 if DELE worked, 0 if it failed
+ * Returns -1 in case of error, 1 if DELE worked, 0 if it failed
*/
int
@@ -1367,7 +1366,7 @@ xmlNanoFTPDele(void *ctx, const char *file) {
* Try to open a data connection to the server. Currently only
* passive mode is supported.
*
- * Returns -1 incase of error, 0 otherwise
+ * Returns -1 in case of error, 0 otherwise
*/
SOCKET
@@ -1540,7 +1539,7 @@ xmlNanoFTPGetConnection(void *ctx) {
*
* Close the data connection from the server
*
- * Returns -1 incase of error, 0 otherwise
+ * Returns -1 in case of error, 0 otherwise
*/
int
@@ -1591,7 +1590,7 @@ xmlNanoFTPCloseConnection(void *ctx) {
*
* Parse at most one entry from the listing.
*
- * Returns -1 incase of error, the length of data parsed otherwise
+ * Returns -1 in case of error, the length of data parsed otherwise
*/
static int
@@ -1719,7 +1718,7 @@ xmlNanoFTPParseList(const char *list, ftpListCallback callback, void *userData)
* Do a listing on the server. All files info are passed back
* in the callbacks.
*
- * Returns -1 incase of error, 0 otherwise
+ * Returns -1 in case of error, 0 otherwise
*/
int
@@ -1894,7 +1893,7 @@ xmlNanoFTPGetSocket(void *ctx, const char *filename) {
* Fetch the given file from the server. All data are passed back
* in the callbacks. The last callback has a size of 0 block.
*
- * Returns -1 incase of error, 0 otherwise
+ * Returns -1 in case of error, 0 otherwise
*/
int
@@ -2024,7 +2023,7 @@ xmlNanoFTPOpen(const char *URL) {
*
* Close the connection and both control and transport
*
- * Returns -1 incase of error, 0 otherwise
+ * Returns -1 in case of error, 0 otherwise
*/
int
diff --git a/contrib/libs/libxml/nanohttp.c b/contrib/libs/libxml/nanohttp.c
index 018b7e189b..8e840f58b7 100644
--- a/contrib/libs/libxml/nanohttp.c
+++ b/contrib/libs/libxml/nanohttp.c
@@ -160,7 +160,7 @@ static int xmlNanoHTTPFetchContent( void * ctx, char ** ptr, int * len );
/**
* xmlHTTPErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -213,7 +213,7 @@ int have_ipv6(void) {
* xmlNanoHTTPInit:
*
* Initialize the HTTP protocol layer.
- * Currently it just checks for proxy informations
+ * Currently it just checks for proxy information
*/
void
@@ -344,7 +344,7 @@ xmlNanoHTTPScanURL(xmlNanoHTTPCtxtPtr ctxt, const char *URL) {
* (Re)Initialize the HTTP Proxy context by parsing the URL and finding
* the protocol host port it indicates.
* Should be like http://myproxy/ or http://myproxy:3128/
- * A NULL URL cleans up proxy informations.
+ * A NULL URL cleans up proxy information.
*/
void
@@ -650,7 +650,7 @@ xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)
* @ctxt: an HTTP context
*
* Read one line in the HTTP server output, usually for extracting
- * the HTTP protocol informations from the answer header.
+ * the HTTP protocol information from the answer header.
*
* Returns a newly allocated string with a copy of the line, or NULL
* which indicate the end of the input.
@@ -693,7 +693,7 @@ xmlNanoHTTPReadLine(xmlNanoHTTPCtxtPtr ctxt) {
* @ctxt: an HTTP context
* @line: an HTTP header line
*
- * Try to extract useful informations from the server answer.
+ * Try to extract useful information from the server answer.
* We currently parse and process:
* - The HTTP revision/ return code
* - The Content-Type, Mime-Type and charset used
@@ -1625,7 +1625,7 @@ xmlNanoHTTPMethod(const char *URL, const char *method, const char *input,
* This function try to fetch the indicated resource via HTTP GET
* and save it's content in the file.
*
- * Returns -1 in case of failure, 0 incase of success. The contentType,
+ * Returns -1 in case of failure, 0 in case of success. The contentType,
* if provided must be freed by the caller
*/
int
@@ -1675,7 +1675,7 @@ xmlNanoHTTPFetch(const char *URL, const char *filename, char **contentType) {
* This function saves the output of the HTTP transaction to a file
* It closes and free the context at the end
*
- * Returns -1 in case of failure, 0 incase of success.
+ * Returns -1 in case of failure, 0 in case of success.
*/
int
xmlNanoHTTPSave(void *ctxt, const char *filename) {
diff --git a/contrib/libs/libxml/parser.c b/contrib/libs/libxml/parser.c
index a34bb6cdd8..8ca9b2ddcf 100644
--- a/contrib/libs/libxml/parser.c
+++ b/contrib/libs/libxml/parser.c
@@ -87,6 +87,13 @@
#include "buf.h"
#include "enc.h"
+struct _xmlStartTag {
+ const xmlChar *prefix;
+ const xmlChar *URI;
+ int line;
+ int nsNr;
+};
+
static void
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
@@ -133,6 +140,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
xmlEntityPtr ent, size_t replacement)
{
size_t consumed = 0;
+ int i;
if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
return (0);
@@ -170,6 +178,28 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
rep = NULL;
}
}
+
+ /*
+ * Prevent entity exponential check, not just replacement while
+ * parsing the DTD
+ * The check is potentially costly so do that only once in a thousand
+ */
+ if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
+ (ctxt->nbentities % 1024 == 0)) {
+ for (i = 0;i < ctxt->inputNr;i++) {
+ consumed += ctxt->inputTab[i]->consumed +
+ (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
+ }
+ if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ ctxt->instate = XML_PARSER_EOF;
+ return (1);
+ }
+ consumed = 0;
+ }
+
+
+
if (replacement != 0) {
if (replacement < XML_MAX_TEXT_LENGTH)
return(0);
@@ -1073,11 +1103,15 @@ xmlHasFeature(xmlFeature feature)
*/
static void
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
+ xmlSAXHandlerPtr sax;
if (ctxt == NULL) return;
+ sax = ctxt->sax;
#ifdef LIBXML_SAX1_ENABLED
- if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
- ((ctxt->sax->startElementNs != NULL) ||
- (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
+ if ((sax) && (sax->initialized == XML_SAX2_MAGIC) &&
+ ((sax->startElementNs != NULL) ||
+ (sax->endElementNs != NULL) ||
+ ((sax->startElement == NULL) && (sax->endElement == NULL))))
+ ctxt->sax2 = 1;
#else
ctxt->sax2 = 1;
#endif /* LIBXML_SAX1_ENABLED */
@@ -1834,6 +1868,8 @@ nodePop(xmlParserCtxtPtr ctxt)
* @value: the element name
* @prefix: the element prefix
* @URI: the element namespace name
+ * @line: the current line number for error messages
+ * @nsNr: the number of namespaces pushed on the namespace table
*
* Pushes a new element name/prefix/URL on top of the name stack
*
@@ -1841,11 +1877,13 @@ nodePop(xmlParserCtxtPtr ctxt)
*/
static int
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
- const xmlChar *prefix, const xmlChar *URI, int nsNr)
+ const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
{
+ xmlStartTag *tag;
+
if (ctxt->nameNr >= ctxt->nameMax) {
const xmlChar * *tmp;
- void **tmp2;
+ xmlStartTag *tmp2;
ctxt->nameMax *= 2;
tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
ctxt->nameMax *
@@ -1855,8 +1893,8 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
goto mem_error;
}
ctxt->nameTab = tmp;
- tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
- ctxt->nameMax * 3 *
+ tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
+ ctxt->nameMax *
sizeof(ctxt->pushTab[0]));
if (tmp2 == NULL) {
ctxt->nameMax /= 2;
@@ -1864,16 +1902,18 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
}
ctxt->pushTab = tmp2;
} else if (ctxt->pushTab == NULL) {
- ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
+ ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
sizeof(ctxt->pushTab[0]));
if (ctxt->pushTab == NULL)
goto mem_error;
}
ctxt->nameTab[ctxt->nameNr] = value;
ctxt->name = value;
- ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
- ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
- ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (ptrdiff_t) nsNr;
+ tag = &ctxt->pushTab[ctxt->nameNr];
+ tag->prefix = prefix;
+ tag->URI = URI;
+ tag->line = line;
+ tag->nsNr = nsNr;
return (ctxt->nameNr++);
mem_error:
xmlErrMemory(ctxt, NULL);
@@ -2055,7 +2095,7 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
((unsigned char *) s)[ 9 ] == c10 )
#define SKIP(val) do { \
- ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val); \
+ ctxt->input->cur += (val),ctxt->input->col+=(val); \
if (*ctxt->input->cur == 0) \
xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
} while (0)
@@ -2066,7 +2106,6 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
if (*(ctxt->input->cur) == '\n') { \
ctxt->input->line++; ctxt->input->col = 1; \
} else ctxt->input->col++; \
- ctxt->nbChars++; \
ctxt->input->cur++; \
} \
if (*ctxt->input->cur == 0) \
@@ -2119,7 +2158,6 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) {
#define NEXT1 { \
ctxt->input->col++; \
ctxt->input->cur++; \
- ctxt->nbChars++; \
if (*ctxt->input->cur == 0) \
xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
}
@@ -2156,7 +2194,8 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
* It's Okay to use CUR/NEXT here since all the blanks are on
* the ASCII range.
*/
- if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
+ if (((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) ||
+ (ctxt->instate == XML_PARSER_START)) {
const xmlChar *cur;
/*
* if we are in the document content, go really fast
@@ -2332,7 +2371,6 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
if (RAW == ';') {
/* on purpose to avoid reentrancy problems with NEXT and SKIP */
ctxt->input->col++;
- ctxt->nbChars ++;
ctxt->input->cur++;
}
} else if ((RAW == '&') && (NXT(1) == '#')) {
@@ -2361,7 +2399,6 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
if (RAW == ';') {
/* on purpose to avoid reentrancy problems with NEXT and SKIP */
ctxt->input->col++;
- ctxt->nbChars ++;
ctxt->input->cur++;
}
} else {
@@ -2684,8 +2721,10 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
0, 0, 0);
ctxt->depth--;
- if (rep == NULL)
+ if (rep == NULL) {
+ ent->content[0] = 0;
goto int_error;
+ }
current = rep;
while (*current != 0) { /* non input consuming loop */
@@ -2740,8 +2779,11 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
0, 0, 0);
ctxt->depth--;
- if (rep == NULL)
+ if (rep == NULL) {
+ if (ent->content != NULL)
+ ent->content[0] = 0;
goto int_error;
+ }
current = rep;
while (*current != 0) { /* non input consuming loop */
buffer[nbchars++] = *current++;
@@ -3333,7 +3375,6 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
}
ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
ctxt->input->cur = in;
- ctxt->nbChars += count;
ctxt->input->col += count;
if (ret == NULL)
xmlErrMemory(ctxt, NULL);
@@ -3456,7 +3497,6 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
}
ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
ctxt->input->cur = in;
- ctxt->nbChars += count;
ctxt->input->col += count;
if (ret == NULL) {
xmlErrMemory(ctxt, NULL);
@@ -3493,10 +3533,10 @@ xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
while (*in != 0 && *in == *cmp) {
++in;
++cmp;
- ctxt->input->col++;
}
if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
/* success */
+ ctxt->input->col += in - ctxt->input->cur;
ctxt->input->cur = in;
return (const xmlChar*) 1;
}
@@ -3912,7 +3952,6 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
"AttValue length too long\n");
goto mem_error;
}
- if (c == 0) break;
if (c == '&') {
in_space = 0;
if (NXT(1) == '#') {
@@ -4207,6 +4246,7 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
}
count++;
if (count > 50) {
+ SHRINK;
GROW;
count = 0;
if (ctxt->instate == XML_PARSER_EOF) {
@@ -4294,6 +4334,7 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
buf[len++] = cur;
count++;
if (count > 50) {
+ SHRINK;
GROW;
count = 0;
if (ctxt->instate == XML_PARSER_EOF) {
@@ -4509,7 +4550,7 @@ get_more:
if (ctxt->instate == XML_PARSER_EOF)
return;
in = ctxt->input->cur;
- } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
+ } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
nbchar = 0;
}
ctxt->input->line = line;
@@ -4547,6 +4588,9 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
}
}
COPY_BUF(l,buf,nbchar,cur);
+ /* move current position before possible calling of ctxt->sax->characters */
+ NEXTL(l);
+ cur = CUR_CHAR(l);
if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
buf[nbchar] = 0;
@@ -4574,13 +4618,12 @@ xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
}
count++;
if (count > 50) {
+ SHRINK;
GROW;
count = 0;
if (ctxt->instate == XML_PARSER_EOF)
return;
}
- NEXTL(l);
- cur = CUR_CHAR(l);
}
if (nbchar != 0) {
buf[nbchar] = 0;
@@ -4779,6 +4822,7 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
count++;
if (count > 50) {
+ SHRINK;
GROW;
count = 0;
if (ctxt->instate == XML_PARSER_EOF) {
@@ -4938,7 +4982,7 @@ get_more:
ctxt->input->cur = in;
in++;
ctxt->input->line++; ctxt->input->col = 1;
- continue; /* while */
+ goto get_more;
}
in--;
}
@@ -4990,7 +5034,7 @@ get_more:
ctxt->input->col++;
goto get_more;
}
- } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
+ } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09) || (*in == 0x0a));
xmlParseCommentComplex(ctxt, buf, len, size);
ctxt->instate = state;
return;
@@ -5054,7 +5098,7 @@ xmlParsePITarget(xmlParserCtxtPtr ctxt) {
* <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
*
* Occurs only if allowed by the user and if happening in the Misc
- * part of the document before any doctype informations
+ * part of the document before any doctype information
* This will add the given catalog to the parsing context in order
* to be used if there is a resolution need further down in the document
*/
@@ -5189,6 +5233,7 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
}
count++;
if (count > 50) {
+ SHRINK;
GROW;
if (ctxt->instate == XML_PARSER_EOF) {
xmlFree(buf);
@@ -6085,14 +6130,20 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
NEXT;
if (elem == NULL) {
ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
- if (ret == NULL) return(NULL);
+ if (ret == NULL) {
+ xmlFreeDocElementContent(ctxt->myDoc, cur);
+ return(NULL);
+ }
ret->c1 = cur;
if (cur != NULL)
cur->parent = ret;
cur = ret;
} else {
n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
- if (n == NULL) return(NULL);
+ if (n == NULL) {
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
if (n->c1 != NULL)
n->c1->parent = n;
@@ -6195,6 +6246,8 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
SKIP_BLANKS;
cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
depth + 1);
+ if (cur == NULL)
+ return(NULL);
SKIP_BLANKS;
GROW;
} else {
@@ -6328,6 +6381,11 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
SKIP_BLANKS;
last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
depth + 1);
+ if (last == NULL) {
+ if (ret != NULL)
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
SKIP_BLANKS;
} else {
elem = xmlParseName(ctxt);
@@ -6853,6 +6911,7 @@ void
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
xmlChar *version;
const xmlChar *encoding;
+ int oldstate;
/*
* We know that '<?xml' is here.
@@ -6864,6 +6923,10 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
return;
}
+ /* Avoid expansion of parameter entities when skipping blanks. */
+ oldstate = ctxt->instate;
+ ctxt->instate = XML_PARSER_START;
+
if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space needed after '<?xml'\n");
@@ -6891,6 +6954,7 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
/*
* The XML REC instructs us to stop parsing right here
*/
+ ctxt->instate = oldstate;
return;
}
if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
@@ -6910,6 +6974,8 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
MOVETO_ENDTAG(CUR_PTR);
NEXT;
}
+
+ ctxt->instate = oldstate;
}
/**
@@ -7147,6 +7213,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
ent->checked |= 1;
if (ret == XML_ERR_ENTITY_LOOP) {
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ xmlHaltParser(ctxt);
xmlFreeNodeList(list);
return;
}
@@ -7160,42 +7227,38 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
(ent->children == NULL)) {
ent->children = list;
- if (ctxt->replaceEntities) {
- /*
- * Prune it directly in the generated document
- * except for single text nodes.
- */
- if (((list->type == XML_TEXT_NODE) &&
- (list->next == NULL)) ||
- (ctxt->parseMode == XML_PARSE_READER)) {
- list->parent = (xmlNodePtr) ent;
- list = NULL;
- ent->owner = 1;
- } else {
- ent->owner = 0;
- while (list != NULL) {
- list->parent = (xmlNodePtr) ctxt->node;
- list->doc = ctxt->myDoc;
- if (list->next == NULL)
- ent->last = list;
- list = list->next;
- }
- list = ent->children;
+ /*
+ * Prune it directly in the generated document
+ * except for single text nodes.
+ */
+ if ((ctxt->replaceEntities == 0) ||
+ (ctxt->parseMode == XML_PARSE_READER) ||
+ ((list->type == XML_TEXT_NODE) &&
+ (list->next == NULL))) {
+ ent->owner = 1;
+ while (list != NULL) {
+ list->parent = (xmlNodePtr) ent;
+ xmlSetTreeDoc(list, ent->doc);
+ if (list->next == NULL)
+ ent->last = list;
+ list = list->next;
+ }
+ list = NULL;
+ } else {
+ ent->owner = 0;
+ while (list != NULL) {
+ list->parent = (xmlNodePtr) ctxt->node;
+ list->doc = ctxt->myDoc;
+ if (list->next == NULL)
+ ent->last = list;
+ list = list->next;
+ }
+ list = ent->children;
#ifdef LIBXML_LEGACY_ENABLED
- if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
- xmlAddEntityReference(ent, list, NULL);
+ if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
+ xmlAddEntityReference(ent, list, NULL);
#endif /* LIBXML_LEGACY_ENABLED */
- }
- } else {
- ent->owner = 1;
- while (list != NULL) {
- list->parent = (xmlNodePtr) ent;
- xmlSetTreeDoc(list, ent->doc);
- if (list->next == NULL)
- ent->last = list;
- list = list->next;
- }
- }
+ }
} else {
xmlFreeNodeList(list);
list = NULL;
@@ -7925,6 +7988,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
xmlChar start[4];
xmlCharEncoding enc;
+ if (xmlParserEntityCheck(ctxt, 0, entity, 0))
+ return;
+
if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
((ctxt->options & XML_PARSE_NOENT) == 0) &&
((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
@@ -8630,7 +8696,7 @@ xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
*
*/
if (name != (xmlChar*)1) {
- if (name == NULL) name = BAD_CAST "unparseable";
+ if (name == NULL) name = BAD_CAST "unparsable";
xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
"Opening and ending tag mismatch: %s line %d and %s\n",
ctxt->name, line, name);
@@ -8823,6 +8889,7 @@ xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
}
if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
/* success */
+ ctxt->input->col += in - ctxt->input->cur;
ctxt->input->cur = in;
return((const xmlChar*) 1);
}
@@ -9623,10 +9690,8 @@ done:
*/
static void
-xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
- const xmlChar *URI, int line, int nsNr, int tlen) {
+xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlStartTag *tag) {
const xmlChar *name;
- size_t curLength;
GROW;
if ((RAW != '<') || (NXT(1) != '/')) {
@@ -9635,24 +9700,10 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
}
SKIP(2);
- curLength = ctxt->input->end - ctxt->input->cur;
- if ((tlen > 0) && (curLength >= (size_t)tlen) &&
- (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
- if ((curLength >= (size_t)(tlen + 1)) &&
- (ctxt->input->cur[tlen] == '>')) {
- ctxt->input->cur += tlen + 1;
- ctxt->input->col += tlen + 1;
- goto done;
- }
- ctxt->input->cur += tlen;
- ctxt->input->col += tlen;
- name = (xmlChar*)1;
- } else {
- if (prefix == NULL)
- name = xmlParseNameAndCompare(ctxt, ctxt->name);
- else
- name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
- }
+ if (tag->prefix == NULL)
+ name = xmlParseNameAndCompare(ctxt, ctxt->name);
+ else
+ name = xmlParseQNameAndCompare(ctxt, ctxt->name, tag->prefix);
/*
* We should definitely be at the ending "S? '>'" part
@@ -9673,26 +9724,23 @@ xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
*
*/
if (name != (xmlChar*)1) {
- if (name == NULL) name = BAD_CAST "unparseable";
- if ((line == 0) && (ctxt->node != NULL))
- line = ctxt->node->line;
+ if (name == NULL) name = BAD_CAST "unparsable";
xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
"Opening and ending tag mismatch: %s line %d and %s\n",
- ctxt->name, line, name);
+ ctxt->name, tag->line, name);
}
/*
* SAX: End of Tag
*/
-done:
if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
(!ctxt->disableSAX))
- ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
+ ctxt->sax->endElementNs(ctxt->userData, ctxt->name, tag->prefix,
+ tag->URI);
spacePop(ctxt);
- if (nsNr != 0)
- nsPop(ctxt, nsNr);
- return;
+ if (tag->nsNr != 0)
+ nsPop(ctxt, tag->nsNr);
}
/**
@@ -9774,6 +9822,7 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
sl = l;
count++;
if (count > 50) {
+ SHRINK;
GROW;
if (ctxt->instate == XML_PARSER_EOF) {
xmlFree(buf);
@@ -9807,16 +9856,15 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
}
/**
- * xmlParseContent:
+ * xmlParseContentInternal:
* @ctxt: an XML parser context
*
- * Parse a content:
- *
- * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
+ * unexpected EOF to the caller.
*/
-void
-xmlParseContent(xmlParserCtxtPtr ctxt) {
+static void
+xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
int nameNr = ctxt->nameNr;
GROW;
@@ -9892,6 +9940,30 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
}
/**
+ * xmlParseContent:
+ * @ctxt: an XML parser context
+ *
+ * Parse a content sequence. Stops at EOF or '</'.
+ *
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ */
+
+void
+xmlParseContent(xmlParserCtxtPtr ctxt) {
+ int nameNr = ctxt->nameNr;
+
+ xmlParseContentInternal(ctxt);
+
+ if ((ctxt->instate != XML_PARSER_EOF) && (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,
+ "Premature end of data in tag %s line %d\n",
+ name, line, NULL);
+ }
+}
+
+/**
* xmlParseElement:
* @ctxt: an XML parser context
*
@@ -9909,9 +9981,20 @@ void
xmlParseElement(xmlParserCtxtPtr ctxt) {
if (xmlParseElementStart(ctxt) != 0)
return;
- xmlParseContent(ctxt);
+
+ xmlParseContentInternal(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);
+ return;
+ }
+
xmlParseElementEnd(ctxt);
}
@@ -9970,12 +10053,7 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) {
spacePop(ctxt);
return(-1);
}
- if (ctxt->sax2)
- nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
-#ifdef LIBXML_SAX1_ENABLED
- else
- namePush(ctxt, name);
-#endif /* LIBXML_SAX1_ENABLED */
+ nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
ret = ctxt->node;
#ifdef LIBXML_VALID_ENABLED
@@ -10068,10 +10146,7 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
* parse the end of tag: '</' should be here.
*/
if (ctxt->sax2) {
- const xmlChar *prefix = ctxt->pushTab[ctxt->nameNr * 3 - 3];
- const xmlChar *URI = ctxt->pushTab[ctxt->nameNr * 3 - 2];
- int nsNr = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 3 - 1];
- xmlParseEndTag2(ctxt, prefix, URI, 0, nsNr, 0);
+ xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
namePop(ctxt);
}
#ifdef LIBXML_SAX1_ENABLED
@@ -10584,16 +10659,16 @@ xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
void
xmlParseMisc(xmlParserCtxtPtr ctxt) {
- while ((ctxt->instate != XML_PARSER_EOF) &&
- (((RAW == '<') && (NXT(1) == '?')) ||
- (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
- IS_BLANK_CH(CUR))) {
+ while (ctxt->instate != XML_PARSER_EOF) {
+ SKIP_BLANKS;
+ GROW;
if ((RAW == '<') && (NXT(1) == '?')) {
xmlParsePI(ctxt);
- } else if (IS_BLANK_CH(CUR)) {
- NEXT;
- } else
+ } else if (CMP4(CUR_PTR, '<', '!', '-', '-')) {
xmlParseComment(ctxt);
+ } else {
+ break;
+ }
}
}
@@ -10699,7 +10774,6 @@ xmlParseDocument(xmlParserCtxtPtr ctxt) {
/*
* The Misc part of the Prolog
*/
- GROW;
xmlParseMisc(ctxt);
/*
@@ -11346,6 +11420,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
const xmlChar *name;
const xmlChar *prefix = NULL;
const xmlChar *URI = NULL;
+ int line = ctxt->input->line;
int nsNr = ctxt->nsNr;
if ((avail < 2) && (ctxt->inputNr == 1))
@@ -11443,12 +11518,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
nodePop(ctxt);
spacePop(ctxt);
}
- if (ctxt->sax2)
- nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
-#ifdef LIBXML_SAX1_ENABLED
- else
- namePush(ctxt, name);
-#endif /* LIBXML_SAX1_ENABLED */
+ nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
ctxt->instate = XML_PARSER_CONTENT;
ctxt->progressive = 1;
@@ -11565,11 +11635,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
}
}
if (ctxt->sax2) {
- xmlParseEndTag2(ctxt,
- (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
- (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
- (int) (ptrdiff_t)
- ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
+ xmlParseEndTag2(ctxt, &ctxt->pushTab[ctxt->nameNr - 1]);
nameNsPop(ctxt);
}
#ifdef LIBXML_SAX1_ENABLED
@@ -12231,12 +12297,12 @@ xmldecl_done:
}
}
res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
+ xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
if (res < 0) {
ctxt->errNo = XML_PARSER_EOF;
xmlHaltParser(ctxt);
return (XML_PARSER_EOF);
}
- xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
#endif
@@ -12251,6 +12317,7 @@ xmldecl_done:
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,
@@ -12258,7 +12325,6 @@ xmldecl_done:
xmlHaltParser(ctxt);
return(XML_ERR_INVALID_ENCODING);
}
- xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
}
}
}
@@ -12560,6 +12626,7 @@ xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
xmlFree(ctxt->sax);
ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
if (ctxt->sax == NULL) {
+ xmlFreeParserInputBuffer(buf);
xmlErrMemory(ctxt, NULL);
xmlFreeParserCtxt(ctxt);
return(NULL);
@@ -12896,196 +12963,28 @@ xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
int
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
const xmlChar *ID, xmlNodePtr *lst) {
- xmlParserCtxtPtr ctxt;
- xmlDocPtr newDoc;
- xmlNodePtr newRoot;
- xmlSAXHandlerPtr oldsax = NULL;
- int ret = 0;
- xmlChar start[4];
- xmlCharEncoding enc;
+ void *userData;
if (ctx == NULL) return(-1);
-
- if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
- (ctx->depth > 1024)) {
- return(XML_ERR_ENTITY_LOOP);
- }
-
- if (lst != NULL)
- *lst = NULL;
- if ((URL == NULL) && (ID == NULL))
- return(-1);
- if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
- return(-1);
-
- ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
- if (ctxt == NULL) {
- return(-1);
- }
-
- oldsax = ctxt->sax;
- ctxt->sax = ctx->sax;
- xmlDetectSAX2(ctxt);
- newDoc = xmlNewDoc(BAD_CAST "1.0");
- if (newDoc == NULL) {
- xmlFreeParserCtxt(ctxt);
- return(-1);
- }
- newDoc->properties = XML_DOC_INTERNAL;
- if (ctx->myDoc->dict) {
- newDoc->dict = ctx->myDoc->dict;
- xmlDictReference(newDoc->dict);
- }
- if (ctx->myDoc != NULL) {
- newDoc->intSubset = ctx->myDoc->intSubset;
- newDoc->extSubset = ctx->myDoc->extSubset;
- }
- if (ctx->myDoc->URL != NULL) {
- newDoc->URL = xmlStrdup(ctx->myDoc->URL);
- }
- newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
- if (newRoot == NULL) {
- ctxt->sax = oldsax;
- xmlFreeParserCtxt(ctxt);
- newDoc->intSubset = NULL;
- newDoc->extSubset = NULL;
- xmlFreeDoc(newDoc);
- return(-1);
- }
- xmlAddChild((xmlNodePtr) newDoc, newRoot);
- nodePush(ctxt, newDoc->children);
- if (ctx->myDoc == NULL) {
- ctxt->myDoc = newDoc;
- } else {
- ctxt->myDoc = ctx->myDoc;
- newDoc->children->doc = ctx->myDoc;
- }
-
/*
- * 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);
- }
- }
-
- /*
- * Parse a possible text declaration first
- */
- 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(ctx->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");
- }
- }
-
- /*
- * If the user provided its own SAX callbacks then reuse the
- * useData callback field, otherwise the expected setup in a
+ * If the user provided their own SAX callbacks, then reuse the
+ * userData callback field, otherwise the expected setup in a
* DOM builder is to have userData == ctxt
*/
if (ctx->userData == ctx)
- ctxt->userData = ctxt;
+ userData = NULL;
else
- ctxt->userData = ctx->userData;
-
- /*
- * Doing validity checking on chunk doesn't make sense
- */
- ctxt->instate = XML_PARSER_CONTENT;
- ctxt->validate = ctx->validate;
- ctxt->valid = ctx->valid;
- ctxt->loadsubset = ctx->loadsubset;
- ctxt->depth = ctx->depth + 1;
- ctxt->replaceEntities = ctx->replaceEntities;
- if (ctxt->validate) {
- ctxt->vctxt.error = ctx->vctxt.error;
- ctxt->vctxt.warning = ctx->vctxt.warning;
- } else {
- ctxt->vctxt.error = NULL;
- ctxt->vctxt.warning = NULL;
- }
- ctxt->vctxt.nodeTab = NULL;
- ctxt->vctxt.nodeNr = 0;
- ctxt->vctxt.nodeMax = 0;
- ctxt->vctxt.node = NULL;
- if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
- ctxt->dict = ctx->dict;
- ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
- ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
- ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
- ctxt->dictNames = ctx->dictNames;
- ctxt->attsDefault = ctx->attsDefault;
- ctxt->attsSpecial = ctx->attsSpecial;
- ctxt->linenumbers = ctx->linenumbers;
-
- xmlParseContent(ctxt);
-
- ctx->validate = ctxt->validate;
- ctx->valid = ctxt->valid;
- if ((RAW == '<') && (NXT(1) == '/')) {
- xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
- } else if (RAW != 0) {
- xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
- }
- if (ctxt->node != newDoc->children) {
- xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
- }
-
- if (!ctxt->wellFormed) {
- if (ctxt->errNo == 0)
- ret = 1;
- else
- ret = ctxt->errNo;
- } else {
- if (lst != NULL) {
- xmlNodePtr cur;
-
- /*
- * Return the newly created nodeset after unlinking it from
- * they pseudo parent.
- */
- cur = newDoc->children->children;
- *lst = cur;
- while (cur != NULL) {
- cur->parent = NULL;
- cur = cur->next;
- }
- newDoc->children->children = NULL;
- }
- ret = 0;
- }
- ctxt->sax = oldsax;
- ctxt->dict = NULL;
- ctxt->attsDefault = NULL;
- ctxt->attsSpecial = NULL;
- xmlFreeParserCtxt(ctxt);
- newDoc->intSubset = NULL;
- newDoc->extSubset = NULL;
- xmlFreeDoc(newDoc);
-
- return(ret);
+ userData = ctx->userData;
+ return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
+ userData, ctx->depth + 1,
+ URL, ID, lst);
}
/**
* xmlParseExternalEntityPrivate:
* @doc: the document the chunk pertains to
* @oldctxt: the previous parser context if available
- * @sax: the SAX handler bloc (possibly NULL)
+ * @sax: the SAX handler block (possibly NULL)
* @user_data: The user data returned on SAX callbacks (possibly NULL)
* @depth: Used for loop detection, use 0
* @URL: the URL for the entity to load
@@ -13128,25 +13027,6 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
ctxt->userData = ctxt;
- if (oldctxt != NULL) {
- ctxt->_private = oldctxt->_private;
- ctxt->loadsubset = oldctxt->loadsubset;
- ctxt->validate = oldctxt->validate;
- ctxt->external = oldctxt->external;
- ctxt->record_info = oldctxt->record_info;
- ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
- ctxt->node_seq.length = oldctxt->node_seq.length;
- ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
- } else {
- /*
- * Doing validity checking on chunk without context
- * doesn't make sense
- */
- ctxt->_private = NULL;
- ctxt->validate = 0;
- ctxt->external = 2;
- ctxt->loadsubset = 0;
- }
if (sax != NULL) {
oldsax = ctxt->sax;
ctxt->sax = sax;
@@ -13156,28 +13036,25 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
xmlDetectSAX2(ctxt);
newDoc = xmlNewDoc(BAD_CAST "1.0");
if (newDoc == NULL) {
- ctxt->node_seq.maximum = 0;
- ctxt->node_seq.length = 0;
- ctxt->node_seq.buffer = NULL;
xmlFreeParserCtxt(ctxt);
return(XML_ERR_INTERNAL_ERROR);
}
newDoc->properties = XML_DOC_INTERNAL;
- newDoc->intSubset = doc->intSubset;
- newDoc->extSubset = doc->extSubset;
- newDoc->dict = doc->dict;
- xmlDictReference(newDoc->dict);
-
- if (doc->URL != NULL) {
- newDoc->URL = xmlStrdup(doc->URL);
+ if (doc) {
+ newDoc->intSubset = doc->intSubset;
+ newDoc->extSubset = doc->extSubset;
+ if (doc->dict) {
+ newDoc->dict = doc->dict;
+ xmlDictReference(newDoc->dict);
+ }
+ if (doc->URL != NULL) {
+ newDoc->URL = xmlStrdup(doc->URL);
+ }
}
newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
if (newRoot == NULL) {
if (sax != NULL)
ctxt->sax = oldsax;
- ctxt->node_seq.maximum = 0;
- ctxt->node_seq.length = 0;
- ctxt->node_seq.buffer = NULL;
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
@@ -13186,8 +13063,12 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
}
xmlAddChild((xmlNodePtr) newDoc, newRoot);
nodePush(ctxt, newDoc->children);
- ctxt->myDoc = doc;
- newRoot->doc = doc;
+ if (doc == NULL) {
+ ctxt->myDoc = newDoc;
+ } else {
+ ctxt->myDoc = doc;
+ newRoot->doc = doc;
+ }
/*
* Get the 4 first bytes and decode the charset
@@ -13211,10 +13092,53 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
*/
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(oldctxt->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");
+ }
}
ctxt->instate = XML_PARSER_CONTENT;
ctxt->depth = depth;
+ if (oldctxt != NULL) {
+ ctxt->_private = oldctxt->_private;
+ ctxt->loadsubset = oldctxt->loadsubset;
+ ctxt->validate = oldctxt->validate;
+ ctxt->valid = oldctxt->valid;
+ ctxt->replaceEntities = oldctxt->replaceEntities;
+ if (oldctxt->validate) {
+ ctxt->vctxt.error = oldctxt->vctxt.error;
+ ctxt->vctxt.warning = oldctxt->vctxt.warning;
+ ctxt->vctxt.userData = oldctxt->vctxt.userData;
+ }
+ ctxt->external = oldctxt->external;
+ if (ctxt->dict) xmlDictFree(ctxt->dict);
+ ctxt->dict = oldctxt->dict;
+ ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
+ ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
+ ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
+ ctxt->dictNames = oldctxt->dictNames;
+ ctxt->attsDefault = oldctxt->attsDefault;
+ ctxt->attsSpecial = oldctxt->attsSpecial;
+ ctxt->linenumbers = oldctxt->linenumbers;
+ ctxt->record_info = oldctxt->record_info;
+ ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
+ ctxt->node_seq.length = oldctxt->node_seq.length;
+ ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
+ } else {
+ /*
+ * Doing validity checking on chunk without context
+ * doesn't make sense
+ */
+ ctxt->_private = NULL;
+ ctxt->validate = 0;
+ ctxt->external = 2;
+ ctxt->loadsubset = 0;
+ }
xmlParseContent(ctxt);
@@ -13274,6 +13198,11 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
if (sax != NULL)
ctxt->sax = oldsax;
if (oldctxt != NULL) {
+ ctxt->dict = NULL;
+ ctxt->attsDefault = NULL;
+ ctxt->attsSpecial = NULL;
+ oldctxt->validate = ctxt->validate;
+ oldctxt->valid = ctxt->valid;
oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
oldctxt->node_seq.length = ctxt->node_seq.length;
oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
@@ -13293,7 +13222,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
/**
* xmlParseExternalEntity:
* @doc: the document the chunk pertains to
- * @sax: the SAX handler bloc (possibly NULL)
+ * @sax: the SAX handler block (possibly NULL)
* @user_data: The user data returned on SAX callbacks (possibly NULL)
* @depth: Used for loop detection, use 0
* @URL: the URL for the entity to load
@@ -13319,8 +13248,8 @@ xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
/**
* xmlParseBalancedChunkMemory:
- * @doc: the document the chunk pertains to
- * @sax: the SAX handler bloc (possibly NULL)
+ * @doc: the document the chunk pertains to (must not be NULL)
+ * @sax: the SAX handler block (possibly NULL)
* @user_data: The user data returned on SAX callbacks (possibly NULL)
* @depth: Used for loop detection, use 0
* @string: the input string in UTF8 or ISO-Latin (zero terminated)
@@ -13771,8 +13700,8 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
#ifdef LIBXML_SAX1_ENABLED
/**
* xmlParseBalancedChunkMemoryRecover:
- * @doc: the document the chunk pertains to
- * @sax: the SAX handler bloc (possibly NULL)
+ * @doc: the document the chunk pertains to (must not be NULL)
+ * @sax: the SAX handler block (possibly NULL)
* @user_data: The user data returned on SAX callbacks (possibly NULL)
* @depth: Used for loop detection, use 0
* @string: the input string in UTF8 or ISO-Latin (zero terminated)
@@ -13843,6 +13772,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
} else {
xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
}
+ /* doc == NULL is only supported for historic reasons */
if (doc != NULL) {
newDoc->intSubset = doc->intSubset;
newDoc->extSubset = doc->extSubset;
@@ -13859,6 +13789,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
}
xmlAddChild((xmlNodePtr) newDoc, newRoot);
nodePush(ctxt, newRoot);
+ /* doc == NULL is only supported for historic reasons */
if (doc == NULL) {
ctxt->myDoc = newDoc;
} else {
@@ -13928,8 +13859,8 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
- if(doc != NULL)
- newDoc->oldNs = NULL;
+ /* This leaks the namespace list if doc == NULL */
+ newDoc->oldNs = NULL;
xmlFreeDoc(newDoc);
return(ret);
@@ -14211,7 +14142,7 @@ xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
if ((ctxt->wellFormed) || recovery) {
ret = ctxt->myDoc;
- if (ret != NULL) {
+ if ((ret != NULL) && (ctxt->input->buf != NULL)) {
if (ctxt->input->buf->compressed > 0)
ret->compression = 9;
else
@@ -14742,6 +14673,11 @@ xmlInitParser(void) {
if (xmlParserInitialized != 0)
return;
+#if defined(_WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+ if (xmlFree == free)
+ atexit(xmlCleanupParser);
+#endif
+
#ifdef LIBXML_THREAD_ENABLED
__xmlGlobalInitMutexLock();
if (xmlParserInitialized == 0) {
@@ -14820,6 +14756,20 @@ xmlCleanupParser(void) {
xmlParserInitialized = 0;
}
+#if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && !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 *
@@ -14908,7 +14858,6 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
ctxt->vctxt.warning = xmlParserValidityWarning;
#endif
ctxt->record_info = 0;
- ctxt->nbChars = 0;
ctxt->checkIndex = 0;
ctxt->inSubset = 0;
ctxt->errNo = XML_ERR_OK;
diff --git a/contrib/libs/libxml/parserInternals.c b/contrib/libs/libxml/parserInternals.c
index b00cd08ec2..c5c0b16dbe 100644
--- a/contrib/libs/libxml/parserInternals.c
+++ b/contrib/libs/libxml/parserInternals.c
@@ -105,7 +105,7 @@ xmlCheckVersion(int version) {
/**
* xmlErrMemory:
* @ctxt: an XML parser context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -165,7 +165,7 @@ __xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr,
* xmlErrInternal:
* @ctxt: an XML parser context
* @msg: the error message
- * @str: error informations
+ * @str: error information
*
* Handle an internal error
*/
@@ -519,8 +519,6 @@ xmlNextChar(xmlParserCtxtPtr ctxt)
} else
/* 1-byte code */
ctxt->input->cur++;
-
- ctxt->nbChars++;
} else {
/*
* Assume it's a fixed length encoding (1) with
@@ -533,7 +531,6 @@ xmlNextChar(xmlParserCtxtPtr ctxt)
} else
ctxt->input->col++;
ctxt->input->cur++;
- ctxt->nbChars++;
}
if (*ctxt->input->cur == 0)
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
@@ -677,7 +674,6 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
}
if (*ctxt->input->cur == 0xD) {
if (ctxt->input->cur[1] == 0xA) {
- ctxt->nbChars++;
ctxt->input->cur++;
}
return(0xA);
@@ -693,7 +689,6 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
*len = 1;
if (*ctxt->input->cur == 0xD) {
if (ctxt->input->cur[1] == 0xA) {
- ctxt->nbChars++;
ctxt->input->cur++;
}
return(0xA);
@@ -1158,6 +1153,11 @@ xmlSwitchInputEncodingInt(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
* Note: this is a bit dangerous, but that's what it
* takes to use nearly compatible signature for different
* encodings.
+ *
+ * FIXME: Encoders might buffer partial byte sequences, so
+ * this probably can't work. We should return an error and
+ * make sure that callers never try to switch the encoding
+ * twice.
*/
xmlCharEncCloseFunc(input->buf->encoder);
input->buf->encoder = handler;
@@ -1546,8 +1546,10 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
}
inputStream = xmlNewInputStream(ctxt);
- if (inputStream == NULL)
+ if (inputStream == NULL) {
+ xmlFreeParserInputBuffer(buf);
return(NULL);
+ }
inputStream->buf = buf;
inputStream = xmlCheckHTTPInput(ctxt, inputStream);
@@ -1748,7 +1750,6 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
ctxt->options |= XML_PARSE_NOENT;
}
ctxt->record_info = 0;
- ctxt->nbChars = 0;
ctxt->checkIndex = 0;
ctxt->inSubset = 0;
ctxt->errNo = XML_ERR_OK;
@@ -1877,7 +1878,7 @@ xmlNewParserCtxt(void)
/************************************************************************
* *
- * Handling of node informations *
+ * Handling of node information *
* *
************************************************************************/
diff --git a/contrib/libs/libxml/relaxng.c b/contrib/libs/libxml/relaxng.c
index 13fd954c7d..c4c26cb00e 100644
--- a/contrib/libs/libxml/relaxng.c
+++ b/contrib/libs/libxml/relaxng.c
@@ -430,7 +430,7 @@ struct _xmlRelaxNGDocument {
/**
* xmlRngPErrMemory:
* @ctxt: an Relax-NG parser context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -465,7 +465,7 @@ xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
/**
* xmlRngVErrMemory:
* @ctxt: a Relax-NG validation context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -1409,7 +1409,7 @@ xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
* @ctxt: a RelaxNG parser context
* @flags: a set of flags values
*
- * Semi private function used to pass informations to a parser context
+ * Semi private function used to pass information to a parser context
* which are a combination of xmlRelaxNGParserFlag .
*
* Returns 0 if success and -1 in case of error
@@ -3654,6 +3654,7 @@ xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
def = xmlRelaxNGNewDefine(ctxt, node);
if (def == NULL) {
+ xmlFree(library);
xmlFree(type);
return (NULL);
}
@@ -6838,6 +6839,7 @@ xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)
(xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
if (ret == NULL) {
xmlRngPErrMemory(NULL, "building parser\n");
+ xmlFreeDoc(copy);
return (NULL);
}
memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
@@ -8165,7 +8167,7 @@ xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt)
@ @inputdata: callback data, the Relax NG validation context
*
* Handle the callback and if needed validate the element children.
- * some of the in/out informations are passed via the context in @inputdata.
+ * some of the in/out information are passed via the context in @inputdata.
*/
static void
xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
@@ -11000,7 +11002,7 @@ xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)
* @warn: the warning function
* @ctx: the functions context
*
- * Set the error and warning callback informations
+ * Set the error and warning callback information
*/
void
xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
@@ -11042,7 +11044,7 @@ xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,
* @warn: the warning function result
* @ctx: the functions context result
*
- * Get the error and warning callback informations
+ * Get the error and warning callback information
*
* Returns -1 in case of error and 0 otherwise
*/
diff --git a/contrib/libs/libxml/schematron.c b/contrib/libs/libxml/schematron.c
index 258ce4091f..ddbb069b12 100644
--- a/contrib/libs/libxml/schematron.c
+++ b/contrib/libs/libxml/schematron.c
@@ -220,7 +220,7 @@ struct _xmlSchematronParserCtxt {
/**
* xmlSchematronPErrMemory:
* @node: a context node
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -268,7 +268,7 @@ xmlSchematronPErr(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr node, int error,
/**
* xmlSchematronVTypeErrMemory:
* @node: a context node
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
diff --git a/contrib/libs/libxml/threads.c b/contrib/libs/libxml/threads.c
index 72df9ba997..503d2bfbec 100644
--- a/contrib/libs/libxml/threads.c
+++ b/contrib/libs/libxml/threads.c
@@ -885,8 +885,6 @@ xmlInitThreads(void)
}
}
#endif /* XML_PTHREAD_WEAK */
-#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
- InitializeCriticalSection(&cleanup_helpers_cs);
#endif
}
@@ -958,6 +956,9 @@ xmlOnceInit(void)
if (!run_once.done) {
if (InterlockedIncrement(&run_once.control) == 1) {
#if !defined(HAVE_COMPILER_TLS)
+#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
+ InitializeCriticalSection(&cleanup_helpers_cs);
+#endif
globalkey = TlsAlloc();
#endif
mainthread = GetCurrentThreadId();
diff --git a/contrib/libs/libxml/tree.c b/contrib/libs/libxml/tree.c
index 08b1a5004d..9d94aa42ae 100644
--- a/contrib/libs/libxml/tree.c
+++ b/contrib/libs/libxml/tree.c
@@ -70,7 +70,7 @@ static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop);
************************************************************************/
/**
* xmlTreeErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -83,7 +83,7 @@ xmlTreeErrMemory(const char *extra)
/**
* xmlTreeErr:
* @code: the error number
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -1064,7 +1064,7 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
* @str: a string
*
* Copy a string using a "dict" dictionary in the current scope,
- * if availabe.
+ * if available.
*/
#define DICT_COPY(str, cpy) \
if (str) { \
@@ -1081,7 +1081,7 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
* @str: a string
*
* Copy a string using a "dict" dictionary in the current scope,
- * if availabe.
+ * if available.
*/
#define DICT_CONST_COPY(str, cpy) \
if (str) { \
@@ -1276,12 +1276,14 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
xmlNodePtr ret = NULL, last = NULL;
xmlNodePtr node;
xmlChar *val;
- const xmlChar *cur = value, *end = cur + len;
+ const xmlChar *cur, *end;
const xmlChar *q;
xmlEntityPtr ent;
xmlBufPtr buf;
if (value == NULL) return(NULL);
+ cur = value;
+ end = cur + len;
buf = xmlBufCreateSize(0);
if (buf == NULL) return(NULL);
@@ -1308,6 +1310,16 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
else
tmp = 0;
while (tmp != ';') { /* Non input consuming loop */
+ /*
+ * If you find an integer overflow here when fuzzing,
+ * the bug is probably elsewhere. This function should
+ * only receive entities that were already validated by
+ * the parser, typically by xmlParseAttValueComplex
+ * calling xmlStringDecodeEntities.
+ *
+ * So it's better *not* to check for overflow to
+ * potentially discover new bugs.
+ */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 16 + (tmp - '0');
else if ((tmp >= 'a') && (tmp <= 'f'))
@@ -1336,6 +1348,7 @@ xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
else
tmp = 0;
while (tmp != ';') { /* Non input consuming loops */
+ /* Don't check for integer overflow, see above. */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 10 + (tmp - '0');
else {
@@ -1515,6 +1528,7 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
cur += 3;
tmp = *cur;
while (tmp != ';') { /* Non input consuming loop */
+ /* Don't check for integer overflow, see above. */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 16 + (tmp - '0');
else if ((tmp >= 'a') && (tmp <= 'f'))
@@ -1537,6 +1551,7 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
cur += 2;
tmp = *cur;
while (tmp != ';') { /* Non input consuming loops */
+ /* Don't check for integer overflow, see above. */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 10 + (tmp - '0');
else {
@@ -1581,6 +1596,10 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
*/
if (!xmlBufIsEmpty(buf)) {
node = xmlNewDocText(doc, NULL);
+ if (node == NULL) {
+ if (val != NULL) xmlFree(val);
+ goto out;
+ }
node->content = xmlBufDetach(buf);
if (last == NULL) {
@@ -1647,6 +1666,10 @@ xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
if (!xmlBufIsEmpty(buf)) {
node = xmlNewDocText(doc, NULL);
+ if (node == NULL) {
+ xmlBufFree(buf);
+ return(NULL);
+ }
node->content = xmlBufDetach(buf);
if (last == NULL) {
@@ -1882,12 +1905,6 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
if (value != NULL) {
xmlNodePtr tmp;
- if(!xmlCheckUTF8(value)) {
- xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) doc,
- NULL);
- if (doc != NULL)
- doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
- }
cur->children = xmlNewDocText(doc, value);
cur->last = NULL;
tmp = cur->children;
@@ -2007,6 +2024,11 @@ xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
* @value: the value of the attribute
*
* Create a new property carried by a document.
+ * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity
+ * references, but XML special chars need to be escaped first by using
+ * xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need
+ * entities support.
+ *
* Returns a pointer to the attribute
*/
xmlAttrPtr
@@ -2834,8 +2856,15 @@ xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
prop = prop->next;
}
}
- if (tree->children != NULL)
+ if (tree->type == XML_ENTITY_REF_NODE) {
+ /*
+ * Clear 'children' which points to the entity declaration
+ * from the original document.
+ */
+ tree->children = NULL;
+ } else if (tree->children != NULL) {
xmlSetListDoc(tree->children, doc);
+ }
tree->doc = doc;
}
}
@@ -3673,17 +3702,14 @@ xmlFreeNodeList(xmlNodePtr cur) {
xmlFreeNsList((xmlNsPtr) cur);
return;
}
- if ((cur->type == XML_DOCUMENT_NODE) ||
-#ifdef LIBXML_DOCB_ENABLED
- (cur->type == XML_DOCB_DOCUMENT_NODE) ||
-#endif
- (cur->type == XML_HTML_DOCUMENT_NODE)) {
- xmlFreeDoc((xmlDocPtr) cur);
- return;
- }
if (cur->doc != NULL) dict = cur->doc->dict;
while (1) {
while ((cur->children != NULL) &&
+ (cur->type != XML_DOCUMENT_NODE) &&
+#ifdef LIBXML_DOCB_ENABLED
+ (cur->type != XML_DOCB_DOCUMENT_NODE) &&
+#endif
+ (cur->type != XML_HTML_DOCUMENT_NODE) &&
(cur->type != XML_DTD_NODE) &&
(cur->type != XML_ENTITY_REF_NODE)) {
cur = cur->children;
@@ -3692,7 +3718,13 @@ xmlFreeNodeList(xmlNodePtr cur) {
next = cur->next;
parent = cur->parent;
- if (cur->type != XML_DTD_NODE) {
+ if ((cur->type == XML_DOCUMENT_NODE) ||
+#ifdef LIBXML_DOCB_ENABLED
+ (cur->type == XML_DOCB_DOCUMENT_NODE) ||
+#endif
+ (cur->type == XML_HTML_DOCUMENT_NODE)) {
+ xmlFreeDoc((xmlDocPtr) cur);
+ } else if (cur->type != XML_DTD_NODE) {
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue(cur);
@@ -4066,7 +4098,7 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
} else {
/*
* we have to find something appropriate here since
- * we cant be sure, that the namespace we found is identified
+ * we can't be sure, that the namespace we found is identified
* by the prefix
*/
if (xmlStrEqual(ns->href, cur->ns->href)) {
@@ -4547,6 +4579,7 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) {
if (doc == NULL) return(NULL);
ret = xmlNewDoc(doc->version);
if (ret == NULL) return(NULL);
+ ret->type = doc->type;
if (doc->name != NULL)
ret->name = xmlMemStrdup(doc->name);
if (doc->encoding != NULL)
@@ -4869,7 +4902,9 @@ xmlGetNodePath(const xmlNode *node)
}
next = ((xmlAttrPtr) cur)->parent;
} else {
- next = cur->parent;
+ xmlFree(buf);
+ xmlFree(buffer);
+ return (NULL);
}
/*
@@ -6564,6 +6599,16 @@ xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,
attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
elemQName, name, NULL);
}
+ } else if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
+ /*
+ * The XML namespace must be bound to prefix 'xml'.
+ */
+ attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,
+ elemQName, name, BAD_CAST "xml");
+ if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
+ attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
+ elemQName, name, BAD_CAST "xml");
+ }
} else {
xmlNsPtr *nsList, *cur;
@@ -6910,12 +6955,6 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
if (value != NULL) {
xmlNodePtr tmp;
- if(!xmlCheckUTF8(value)) {
- xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) node->doc,
- NULL);
- if (node->doc != NULL)
- node->doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
- }
prop->children = xmlNewDocText(node->doc, value);
prop->last = NULL;
tmp = prop->children;
@@ -7243,7 +7282,7 @@ xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
/*
* we just move the content pointer, but also make sure
- * the perceived buffer size has shrinked accordingly
+ * the perceived buffer size has shrunk accordingly
*/
buf->content += len;
buf->size -= len;
@@ -7417,12 +7456,17 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
if (size < buf->size)
return 1;
+ if (size > UINT_MAX - 10) {
+ xmlTreeErrMemory("growing buffer");
+ return 0;
+ }
+
/* figure out new size */
switch (buf->alloc){
case XML_BUFFER_ALLOC_IO:
case XML_BUFFER_ALLOC_DOUBLEIT:
/*take care of empty case*/
- newSize = (buf->size ? buf->size*2 : size + 10);
+ newSize = (buf->size ? buf->size : size + 10);
while (size > newSize) {
if (newSize > UINT_MAX / 2) {
xmlTreeErrMemory("growing buffer");
@@ -7438,7 +7482,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
if (buf->use < BASE_BUFFER_SIZE)
newSize = size;
else {
- newSize = buf->size * 2;
+ newSize = buf->size;
while (size > newSize) {
if (newSize > UINT_MAX / 2) {
xmlTreeErrMemory("growing buffer");
@@ -7595,7 +7639,7 @@ xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
if (start_buf > (unsigned int) len) {
/*
- * We can add it in the space previously shrinked
+ * We can add it in the space previously shrunk
*/
buf->content -= len;
memmove(&buf->content[0], str, len);
diff --git a/contrib/libs/libxml/uri.c b/contrib/libs/libxml/uri.c
index 05d81e5763..ccc26aa594 100644
--- a/contrib/libs/libxml/uri.c
+++ b/contrib/libs/libxml/uri.c
@@ -11,6 +11,7 @@
#define IN_LIBXML
#include "libxml.h"
+#include <limits.h>
#include <string.h>
#include <libxml/xmlmemory.h>
@@ -329,9 +330,14 @@ xmlParse3986Port(xmlURIPtr uri, const char **str)
if (ISA_DIGIT(cur)) {
while (ISA_DIGIT(cur)) {
- port = port * 10 + (*cur - '0');
- if (port > 99999999)
- port = 99999999;
+ int digit = *cur - '0';
+
+ if (port > INT_MAX / 10)
+ return(1);
+ port *= 10;
+ if (port > INT_MAX - digit)
+ return(1);
+ port += digit;
cur++;
}
@@ -348,7 +354,7 @@ xmlParse3986Port(xmlURIPtr uri, const char **str)
* @uri: pointer to an URI structure
* @str: the string to analyze
*
- * Parse an user informations part and fills in the appropriate fields
+ * Parse an user information part and fills in the appropriate fields
* of the @uri structure
*
* userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
@@ -1632,23 +1638,24 @@ xmlURIUnescapeString(const char *str, int len, char *target) {
out = ret;
while(len > 0) {
if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) {
+ int c = 0;
in++;
if ((*in >= '0') && (*in <= '9'))
- *out = (*in - '0');
+ c = (*in - '0');
else if ((*in >= 'a') && (*in <= 'f'))
- *out = (*in - 'a') + 10;
+ c = (*in - 'a') + 10;
else if ((*in >= 'A') && (*in <= 'F'))
- *out = (*in - 'A') + 10;
+ c = (*in - 'A') + 10;
in++;
if ((*in >= '0') && (*in <= '9'))
- *out = *out * 16 + (*in - '0');
+ c = c * 16 + (*in - '0');
else if ((*in >= 'a') && (*in <= 'f'))
- *out = *out * 16 + (*in - 'a') + 10;
+ c = c * 16 + (*in - 'a') + 10;
else if ((*in >= 'A') && (*in <= 'F'))
- *out = *out * 16 + (*in - 'A') + 10;
+ c = c * 16 + (*in - 'A') + 10;
in++;
len -= 3;
- out++;
+ *out++ = (char) c;
} else {
*out++ = *in++;
len--;
@@ -1748,11 +1755,6 @@ xmlURIEscape(const xmlChar * str)
xmlURIPtr uri;
int ret2;
-#define NULLCHK(p) if(!p) { \
- xmlURIErrMemory("escaping URI value\n"); \
- xmlFreeURI(uri); \
- return NULL; } \
-
if (str == NULL)
return (NULL);
@@ -1774,6 +1776,12 @@ xmlURIEscape(const xmlChar * str)
ret = NULL;
+#define NULLCHK(p) if(!p) { \
+ xmlURIErrMemory("escaping URI value\n"); \
+ xmlFreeURI(uri); \
+ xmlFree(ret); \
+ return NULL; } \
+
if (uri->scheme) {
segment = xmlURIEscapeStr(BAD_CAST uri->scheme, BAD_CAST "+-.");
NULLCHK(segment)
@@ -1794,7 +1802,7 @@ xmlURIEscape(const xmlChar * str)
if (uri->user) {
segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,");
NULLCHK(segment)
- ret = xmlStrcat(ret,BAD_CAST "//");
+ ret = xmlStrcat(ret,BAD_CAST "//");
ret = xmlStrcat(ret, segment);
ret = xmlStrcat(ret, BAD_CAST "@");
xmlFree(segment);
@@ -1803,8 +1811,8 @@ xmlURIEscape(const xmlChar * str)
if (uri->server) {
segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@");
NULLCHK(segment)
- if (uri->user == NULL)
- ret = xmlStrcat(ret, BAD_CAST "//");
+ if (uri->user == NULL)
+ ret = xmlStrcat(ret, BAD_CAST "//");
ret = xmlStrcat(ret, segment);
xmlFree(segment);
}
diff --git a/contrib/libs/libxml/valid.c b/contrib/libs/libxml/valid.c
index 07963e7451..8e596f1db3 100644
--- a/contrib/libs/libxml/valid.c
+++ b/contrib/libs/libxml/valid.c
@@ -50,7 +50,7 @@ xmlValidateAttributeValueInternal(xmlDocPtr doc, xmlAttributeType type,
/**
* xmlVErrMemory:
* @ctxt: an XML validation parser context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory error
*/
@@ -89,7 +89,7 @@ xmlVErrMemory(xmlValidCtxtPtr ctxt, const char *extra)
* xmlErrValid:
* @ctxt: an XML validation parser context
* @error: the error number
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a validation error
*/
@@ -131,11 +131,11 @@ xmlErrValid(xmlValidCtxtPtr ctxt, xmlParserErrors error,
* @ctxt: an XML validation parser context
* @node: the node raising the error
* @error: the error number
- * @str1: extra informations
- * @str2: extra informations
- * @str3: extra informations
+ * @str1: extra information
+ * @str2: extra information
+ * @str3: extra information
*
- * Handle a validation error, provide contextual informations
+ * Handle a validation error, provide contextual information
*/
static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNode(xmlValidCtxtPtr ctxt,
@@ -174,11 +174,11 @@ xmlErrValidNode(xmlValidCtxtPtr ctxt,
* @ctxt: an XML validation parser context
* @node: the node raising the error
* @error: the error number
- * @str1: extra informations
- * @int2: extra informations
- * @str3: extra informations
+ * @str1: extra information
+ * @int2: extra information
+ * @str3: extra information
*
- * Handle a validation error, provide contextual informations
+ * Handle a validation error, provide contextual information
*/
static void LIBXML_ATTR_FORMAT(4,0)
xmlErrValidNodeNr(xmlValidCtxtPtr ctxt,
@@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt)
return (ret);
}
+/**
+ * xmlValidNormalizeString:
+ * @str: a string
+ *
+ * Normalize a string in-place.
+ */
+static void
+xmlValidNormalizeString(xmlChar *str) {
+ xmlChar *dst;
+ const xmlChar *src;
+
+ if (str == NULL)
+ return;
+ src = str;
+ dst = str;
+
+ while (*src == 0x20) src++;
+ while (*src != 0) {
+ if (*src == 0x20) {
+ while (*src == 0x20) src++;
+ if (*src != 0)
+ *dst++ = 0x20;
+ } else {
+ *dst++ = *src++;
+ }
+ }
+ *dst = 0;
+}
+
#ifdef DEBUG_VALID_ALGO
static void
xmlValidPrintNode(xmlNodePtr cur) {
@@ -1174,7 +1203,7 @@ xmlFreeElementContent(xmlElementContentPtr cur) {
* @buf: An XML buffer
* @cur: An element table
*
- * Dump the occurence operator of an element.
+ * Dump the occurrence operator of an element.
*/
static void
xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
@@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
xmlFree((char *)(str));
+static int
+xmlIsStreaming(xmlValidCtxtPtr ctxt) {
+ xmlParserCtxtPtr pctxt;
+
+ if (ctxt == NULL)
+ return(0);
+ /*
+ * These magic values are also abused to detect whether we're validating
+ * while parsing a document. In this case, userData points to the parser
+ * context.
+ */
+ if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) &&
+ (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1))
+ return(0);
+ pctxt = ctxt->userData;
+ return(pctxt->parseMode == XML_PARSE_READER);
+}
+
/**
* xmlFreeID:
* @not: A id
@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
if (doc == NULL) {
return(NULL);
}
- if (value == NULL) {
+ if ((value == NULL) || (value[0] == 0)) {
return(NULL);
}
if (attr == NULL) {
@@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
*/
ret->value = xmlStrdup(value);
ret->doc = doc;
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
+ if (xmlIsStreaming(ctxt)) {
/*
* Operating in streaming mode, attr is gonna disappear
*/
@@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
ID = xmlNodeListGetString(doc, attr->children, 1);
if (ID == NULL)
return(-1);
+ xmlValidNormalizeString(ID);
id = xmlHashLookup(table, ID);
if (id == NULL || id->attr != attr) {
@@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
* fill the structure.
*/
ret->value = xmlStrdup(value);
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
+ if (xmlIsStreaming(ctxt)) {
/*
* Operating in streaming mode, attr is gonna disappear
*/
@@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlChar *
xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
- xmlChar *ret, *dst;
- const xmlChar *src;
+ xmlChar *ret;
xmlAttributePtr attrDecl = NULL;
int extsubset = 0;
@@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
ret = xmlStrdup(value);
if (ret == NULL)
return(NULL);
- src = value;
- dst = ret;
- while (*src == 0x20) src++;
- while (*src != 0) {
- if (*src == 0x20) {
- while (*src == 0x20) src++;
- if (*src != 0)
- *dst++ = 0x20;
- } else {
- *dst++ = *src++;
- }
- }
- *dst = 0;
+ xmlValidNormalizeString(ret);
if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
"standalone: %s on %s value had to be normalized based on external subset declaration\n",
@@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlChar *
xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
const xmlChar *name, const xmlChar *value) {
- xmlChar *ret, *dst;
- const xmlChar *src;
+ xmlChar *ret;
xmlAttributePtr attrDecl = NULL;
if (doc == NULL) return(NULL);
@@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
ret = xmlStrdup(value);
if (ret == NULL)
return(NULL);
- src = value;
- dst = ret;
- while (*src == 0x20) src++;
- while (*src != 0) {
- if (*src == 0x20) {
- while (*src == 0x20) src++;
- if (*src != 0)
- *dst++ = 0x20;
- } else {
- *dst++ = *src++;
- }
- }
- *dst = 0;
+ xmlValidNormalizeString(ret);
return(ret);
}
@@ -5434,7 +5456,7 @@ fail:
} else if (ret == -2) {
/*
* An entities reference appeared at this level.
- * Buid a minimal representation of this node content
+ * Build a minimal representation of this node content
* sufficient to run the validation process on it
*/
DEBUG_VALID_MSG("Found an entity reference, linearizing");
@@ -5919,28 +5941,27 @@ xmlValidatePushCData(xmlValidCtxtPtr ctxt, const xmlChar *data, int len) {
break;
case XML_ELEMENT_TYPE_MIXED:
break;
- case XML_ELEMENT_TYPE_ELEMENT:
- if (len > 0) {
- int i;
-
- for (i = 0;i < len;i++) {
- if (!IS_BLANK_CH(data[i])) {
- xmlErrValidNode(ctxt, state->node,
- XML_DTD_CONTENT_MODEL,
- "Element %s content does not follow the DTD, Text not allowed\n",
- state->node->name, NULL, NULL);
- ret = 0;
- goto done;
- }
- }
- /*
- * TODO:
- * VC: Standalone Document Declaration
- * element types with element content, if white space
- * occurs directly within any instance of those types.
- */
- }
- break;
+ case XML_ELEMENT_TYPE_ELEMENT: {
+ int i;
+
+ for (i = 0;i < len;i++) {
+ if (!IS_BLANK_CH(data[i])) {
+ xmlErrValidNode(ctxt, state->node,
+ XML_DTD_CONTENT_MODEL,
+ "Element %s content does not follow the DTD, Text not allowed\n",
+ state->node->name, NULL, NULL);
+ ret = 0;
+ goto done;
+ }
+ }
+ /*
+ * TODO:
+ * VC: Standalone Document Declaration
+ * element types with element content, if white space
+ * occurs directly within any instance of those types.
+ */
+ break;
+ }
}
}
}
diff --git a/contrib/libs/libxml/xinclude.c b/contrib/libs/libxml/xinclude.c
index ba850fa538..2a0614d737 100644
--- a/contrib/libs/libxml/xinclude.c
+++ b/contrib/libs/libxml/xinclude.c
@@ -59,7 +59,7 @@ struct _xmlXIncludeRef {
xmlNodePtr inc; /* the included copy */
int xml; /* xml or txt */
int count; /* how many refs use that specific doc */
- xmlXPathObjectPtr xptr; /* the xpointer if needed */
+ int fallback; /* fallback was loaded */
int emptyFb; /* flag to show fallback empty */
};
@@ -72,7 +72,7 @@ struct _xmlXIncludeCtxt {
int txtNr; /* number of unparsed documents */
int txtMax; /* size of unparsed documents tab */
- xmlNodePtr *txtTab; /* array of unparsed text nodes */
+ xmlChar * *txtTab; /* array of unparsed text strings */
xmlURL *txturlTab; /* array of unparsed text URLs */
xmlChar * url; /* the current URL processed */
@@ -86,10 +86,13 @@ struct _xmlXIncludeCtxt {
xmlChar * base; /* the current xml:base */
void *_private; /* application data */
+
+ unsigned long incTotal; /* total number of processed inclusions */
};
static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
+ int skipRoot);
/************************************************************************
@@ -207,8 +210,6 @@ xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
xmlFree(ref->URI);
if (ref->fragment != NULL)
xmlFree(ref->fragment);
- if (ref->xptr != NULL)
- xmlXPathFreeObject(ref->xptr);
xmlFree(ref);
}
@@ -392,18 +393,22 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
if (ctxt->incTab[i] != NULL)
xmlXIncludeFreeRef(ctxt->incTab[i]);
}
+ if (ctxt->incTab != NULL)
+ xmlFree(ctxt->incTab);
+ if (ctxt->txtTab != NULL) {
+ for (i = 0;i < ctxt->txtNr;i++) {
+ if (ctxt->txtTab[i] != NULL)
+ xmlFree(ctxt->txtTab[i]);
+ }
+ xmlFree(ctxt->txtTab);
+ }
if (ctxt->txturlTab != NULL) {
for (i = 0;i < ctxt->txtNr;i++) {
if (ctxt->txturlTab[i] != NULL)
xmlFree(ctxt->txturlTab[i]);
}
- }
- if (ctxt->incTab != NULL)
- xmlFree(ctxt->incTab);
- if (ctxt->txtTab != NULL)
- xmlFree(ctxt->txtTab);
- if (ctxt->txturlTab != NULL)
xmlFree(ctxt->txturlTab);
+ }
if (ctxt->base != NULL) {
xmlFree(ctxt->base);
}
@@ -626,8 +631,8 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
"detected a local recursion with no xpointer in %s\n",
URL);
- if (fragment != NULL)
- xmlFree(fragment);
+ xmlFree(URL);
+ xmlFree(fragment);
return(-1);
}
@@ -639,12 +644,15 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
if (xmlStrEqual(URL, ctxt->urlTab[i])) {
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
"detected a recursion in %s\n", URL);
+ xmlFree(URL);
+ xmlFree(fragment);
return(-1);
}
}
}
ref = xmlXIncludeNewRef(ctxt, URL, cur);
+ xmlFree(URL);
if (ref == NULL) {
return(-1);
}
@@ -652,7 +660,6 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
ref->doc = NULL;
ref->xml = xml;
ref->count = 1;
- xmlFree(URL);
return(0);
}
@@ -729,7 +736,9 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
* (bug 132597)
*/
newctxt->parseFlags = ctxt->parseFlags;
- xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
+ newctxt->incTotal = ctxt->incTotal;
+ xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc), 0);
+ ctxt->incTotal = newctxt->incTotal;
for (i = 0;i < ctxt->incNr;i++) {
newctxt->incTab[i]->count--;
newctxt->incTab[i] = NULL;
@@ -759,13 +768,14 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
* Add a new text node to the list
*/
static void
-xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
+xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *txt,
+ const xmlURL url) {
#ifdef DEBUG_XINCLUDE
xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
#endif
if (ctxt->txtMax == 0) {
ctxt->txtMax = 4;
- ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
+ ctxt->txtTab = (xmlChar **) xmlMalloc(ctxt->txtMax *
sizeof(ctxt->txtTab[0]));
if (ctxt->txtTab == NULL) {
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
@@ -780,7 +790,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
}
if (ctxt->txtNr >= ctxt->txtMax) {
ctxt->txtMax *= 2;
- ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
+ ctxt->txtTab = (xmlChar **) xmlRealloc(ctxt->txtTab,
ctxt->txtMax * sizeof(ctxt->txtTab[0]));
if (ctxt->txtTab == NULL) {
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
@@ -793,7 +803,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
return;
}
}
- ctxt->txtTab[ctxt->txtNr] = txt;
+ ctxt->txtTab[ctxt->txtNr] = xmlStrdup(txt);
ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
ctxt->txtNr++;
}
@@ -1004,15 +1014,15 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
if (list == NULL) {
list = tmp;
listParent = cur->parent;
+ last = tmp;
} else {
if (level == lastLevel)
- xmlAddNextSibling(last, tmp);
+ last = xmlAddNextSibling(last, tmp);
else {
- xmlAddChild(last, tmp);
+ last = xmlAddChild(last, tmp);
lastLevel = level;
}
}
- last = tmp;
if (index2 > 1) {
end = xmlXIncludeGetNthChild(cur, index2 - 1);
@@ -1071,7 +1081,7 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_NODE:
- /* Do not copy DTD informations */
+ /* Do not copy DTD information */
break;
case XML_ENTITY_DECL:
/* handle crossing entities -> stack needed */
@@ -1093,12 +1103,11 @@ xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
}
if (tmp != NULL) {
if (level == lastLevel)
- xmlAddNextSibling(last, tmp);
+ last = xmlAddNextSibling(last, tmp);
else {
- xmlAddChild(last, tmp);
+ last = xmlAddChild(last, tmp);
lastLevel = level;
}
- last = tmp;
}
}
/*
@@ -1176,8 +1185,7 @@ xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
if (last == NULL) {
list = last = tmp;
} else {
- xmlAddNextSibling(last, tmp);
- last = tmp;
+ last = xmlAddNextSibling(last, tmp);
}
cur = cur->next;
continue;
@@ -1459,7 +1467,7 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
*/
if ((URL[0] == 0) || (URL[0] == '#') ||
((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
- doc = NULL;
+ doc = ctxt->doc;
goto loaded;
}
@@ -1551,15 +1559,8 @@ loaded:
/*
* Add the top children list as the replacement copy.
*/
- if (doc == NULL)
- {
- /* Hopefully a DTD declaration won't be copied from
- * the same document */
- ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
- } else {
- ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
- doc, doc->children);
- }
+ ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
+ doc, doc->children);
}
#ifdef LIBXML_XPTR_ENABLED
else {
@@ -1571,12 +1572,7 @@ loaded:
xmlXPathContextPtr xptrctxt;
xmlNodeSetPtr set;
- if (doc == NULL) {
- xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
- NULL);
- } else {
- xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
- }
+ xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
if (xptrctxt == NULL) {
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
XML_XINCLUDE_XPTR_FAILED,
@@ -1608,6 +1604,7 @@ loaded:
XML_XINCLUDE_XPTR_RESULT,
"XPointer is not a range: #%s\n",
fragment);
+ xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
@@ -1615,6 +1612,7 @@ loaded:
case XPATH_NODESET:
if ((xptr->nodesetval == NULL) ||
(xptr->nodesetval->nodeNr <= 0)) {
+ xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
@@ -1678,14 +1676,9 @@ loaded:
}
}
}
- if (doc == NULL) {
- ctxt->incTab[nr]->xptr = xptr;
- ctxt->incTab[nr]->inc = NULL;
- } else {
- ctxt->incTab[nr]->inc =
- xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
- xmlXPathFreeObject(xptr);
- }
+ ctxt->incTab[nr]->inc =
+ xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
+ xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(fragment);
}
@@ -1855,7 +1848,7 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
*/
for (i = 0; i < ctxt->txtNr; i++) {
if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
- node = xmlCopyNode(ctxt->txtTab[i], 1);
+ node = xmlNewText(ctxt->txtTab[i]);
goto loaded;
}
}
@@ -1945,7 +1938,7 @@ xinclude_multibyte_fallback:
xmlBufShrink(buf->buffer, len);
}
xmlFreeParserCtxt(pctxt);
- xmlXIncludeAddTxt(ctxt, node, URL);
+ xmlXIncludeAddTxt(ctxt, node->content, URL);
xmlFreeInputStream(inputStream);
loaded:
@@ -1988,19 +1981,23 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
newctxt->_private = ctxt->_private;
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
- ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
+ newctxt->incTotal = ctxt->incTotal;
+ if (xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback, 1) < 0)
+ ret = -1;
+ ctxt->incTotal = newctxt->incTotal;
if (ctxt->nbErrors > oldNbErrors)
ret = -1;
- else if (ret > 0)
- ret = 0; /* xmlXIncludeDoProcess can return +ve number */
xmlXIncludeFreeContext(newctxt);
ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
fallback->children);
+ if (ctxt->incTab[nr]->inc == NULL)
+ ctxt->incTab[nr]->emptyFb = 1;
} else {
ctxt->incTab[nr]->inc = NULL;
ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
}
+ ctxt->incTab[nr]->fallback = 1;
return(ret);
}
@@ -2156,8 +2153,7 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
(xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
ret = xmlXIncludeLoadFallback(ctxt, children, nr);
- if (ret == 0)
- break;
+ break;
}
children = children->next;
}
@@ -2204,19 +2200,9 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
return(-1);
- /*
- * If we stored an XPointer a late computation may be needed
- */
- if ((ctxt->incTab[nr]->inc == NULL) &&
- (ctxt->incTab[nr]->xptr != NULL)) {
- ctxt->incTab[nr]->inc =
- xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
- ctxt->incTab[nr]->xptr);
- xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
- ctxt->incTab[nr]->xptr = NULL;
- }
list = ctxt->incTab[nr]->inc;
ctxt->incTab[nr]->inc = NULL;
+ ctxt->incTab[nr]->emptyFb = 0;
/*
* Check against the risk of generating a multi-rooted document
@@ -2236,6 +2222,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
XML_XINCLUDE_MULTIPLE_ROOT,
"XInclude error: would result in multiple root nodes\n",
NULL);
+ xmlFreeNodeList(list);
return(-1);
}
}
@@ -2253,16 +2240,27 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
xmlUnlinkNode(cur);
xmlFreeNode(cur);
} else {
+ xmlNodePtr child, next;
+
/*
* Change the current node as an XInclude start one, and add an
* XInclude end one
*/
+ if (ctxt->incTab[nr]->fallback)
+ xmlUnsetProp(cur, BAD_CAST "href");
cur->type = XML_XINCLUDE_START;
+ /* Remove fallback children */
+ for (child = cur->children; child != NULL; child = next) {
+ next = child->next;
+ xmlUnlinkNode(child);
+ xmlFreeNode(child);
+ }
end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
if (end == NULL) {
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
XML_XINCLUDE_BUILD_FAILED,
"failed to build node\n", NULL);
+ xmlFreeNodeList(list);
return(-1);
}
end->type = XML_XINCLUDE_END;
@@ -2364,6 +2362,7 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* @ctxt: the XInclude processing context
* @doc: an XML document
* @tree: the top of the tree to process
+ * @skipRoot: don't process the root node of the tree
*
* Implement the XInclude substitution on the XML document @doc
*
@@ -2371,13 +2370,16 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* or the number of substitutions done.
*/
static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
+ int skipRoot) {
xmlNodePtr cur;
int ret = 0;
int i, start;
if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
return(-1);
+ if ((skipRoot) && (tree->children == NULL))
+ return(-1);
if (ctxt == NULL)
return(-1);
@@ -2389,40 +2391,58 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
start = ctxt->incNr;
/*
+ * TODO: The phases must run separately for recursive inclusions.
+ *
+ * - Phase 1 should start with top-level XInclude nodes, load documents,
+ * execute XPointer expressions, then process only the result nodes
+ * (not whole document, see bug #324081) and only for phase 1
+ * recursively. We will need a backreference from xmlNodes to
+ * xmlIncludeRefs to detect references that were already visited.
+ * This can also be used for proper cycle detection, see bug #344240.
+ *
+ * - Phase 2 should visit all top-level XInclude nodes and expand
+ * possible subreferences in the replacement recursively.
+ *
+ * - Phase 3 should finally replace the top-level XInclude nodes.
+ * It could also be run together with phase 2.
+ */
+
+ /*
* First phase: lookup the elements in the document
*/
- cur = tree;
- if (xmlXIncludeTestNode(ctxt, cur) == 1)
- xmlXIncludePreProcessNode(ctxt, cur);
- while ((cur != NULL) && (cur != tree->parent)) {
+ if (skipRoot)
+ cur = tree->children;
+ else
+ cur = tree;
+ do {
/* TODO: need to work on entities -> stack */
- if ((cur->children != NULL) &&
- (cur->children->type != XML_ENTITY_DECL) &&
- (cur->children->type != XML_XINCLUDE_START) &&
- (cur->children->type != XML_XINCLUDE_END)) {
- cur = cur->children;
- if (xmlXIncludeTestNode(ctxt, cur))
- xmlXIncludePreProcessNode(ctxt, cur);
- } else if (cur->next != NULL) {
- cur = cur->next;
- if (xmlXIncludeTestNode(ctxt, cur))
- xmlXIncludePreProcessNode(ctxt, cur);
- } else {
- if (cur == tree)
- break;
- do {
- cur = cur->parent;
- if ((cur == NULL) || (cur == tree->parent))
- break; /* do */
- if (cur->next != NULL) {
- cur = cur->next;
- if (xmlXIncludeTestNode(ctxt, cur))
- xmlXIncludePreProcessNode(ctxt, cur);
- break; /* do */
- }
- } while (cur != NULL);
- }
- }
+ if (xmlXIncludeTestNode(ctxt, cur) == 1) {
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /*
+ * Avoid superlinear expansion by limiting the total number
+ * of replacements.
+ */
+ if (ctxt->incTotal >= 20)
+ return(-1);
+#endif
+ ctxt->incTotal++;
+ xmlXIncludePreProcessNode(ctxt, cur);
+ } else if ((cur->children != NULL) &&
+ ((cur->type == XML_DOCUMENT_NODE) ||
+ (cur->type == XML_ELEMENT_NODE))) {
+ cur = cur->children;
+ continue;
+ }
+ do {
+ if (cur == tree)
+ break;
+ if (cur->next != NULL) {
+ cur = cur->next;
+ break;
+ }
+ cur = cur->parent;
+ } while (cur != NULL);
+ } while ((cur != NULL) && (cur != tree));
/*
* Second Phase : collect the infosets fragments
@@ -2445,8 +2465,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
*/
for (i = ctxt->incBase;i < ctxt->incNr; i++) {
if ((ctxt->incTab[i]->inc != NULL) ||
- (ctxt->incTab[i]->xptr != NULL) ||
- (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
+ (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
xmlXIncludeIncludeNode(ctxt, i);
}
@@ -2500,7 +2519,7 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
ctxt->_private = data;
ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
xmlXIncludeSetFlags(ctxt, flags);
- ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
+ ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@@ -2584,7 +2603,7 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
return(-1);
ctxt->base = xmlNodeGetBase(tree->doc, tree);
xmlXIncludeSetFlags(ctxt, flags);
- ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
+ ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@@ -2612,7 +2631,7 @@ xmlXIncludeProcessTree(xmlNodePtr tree) {
* @node: a node in an XML document
*
* Implement the XInclude substitution for the given subtree reusing
- * the informations and data coming from the given context.
+ * the information and data coming from the given context.
*
* Returns 0 if no substitution were done, -1 if some processing failed
* or the number of substitutions done.
@@ -2624,7 +2643,7 @@ xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
(node->doc == NULL) || (ctxt == NULL))
return(-1);
- ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
+ ret = xmlXIncludeDoProcess(ctxt, node->doc, node, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
return(ret);
diff --git a/contrib/libs/libxml/xmlIO.c b/contrib/libs/libxml/xmlIO.c
index 7921e793a0..0898158851 100644
--- a/contrib/libs/libxml/xmlIO.c
+++ b/contrib/libs/libxml/xmlIO.c
@@ -224,7 +224,7 @@ __xmlIOWin32UTF8ToWChar(const char *u8String)
/**
* xmlIOErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -238,7 +238,7 @@ xmlIOErrMemory(const char *extra)
* __xmlIOErr:
* @code: the error number
* @
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an I/O error
*/
@@ -416,7 +416,7 @@ __xmlIOErr(int domain, int code, const char *extra)
/**
* xmlIOErr:
* @code: the error number
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an I/O error
*/
@@ -429,7 +429,7 @@ xmlIOErr(int code, const char *extra)
/**
* __xmlLoaderErr:
* @ctx: the parser context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a resource access error
*/
@@ -560,6 +560,33 @@ xmlCleanupOutputCallbacks(void)
xmlOutputCallbackNr = 0;
xmlOutputCallbackInitialized = 0;
}
+
+/**
+ * xmlPopOutputCallbacks:
+ *
+ * Remove the top output callbacks from the output stack. This includes the
+ * compiled-in I/O.
+ *
+ * Returns the number of output callback registered or -1 in case of error.
+ */
+int
+xmlPopOutputCallbacks(void)
+{
+ if (!xmlOutputCallbackInitialized)
+ return(-1);
+
+ if (xmlOutputCallbackNr <= 0)
+ return(-1);
+
+ xmlOutputCallbackNr--;
+ xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = NULL;
+ xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = NULL;
+ xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = NULL;
+ xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = NULL;
+
+ return(xmlOutputCallbackNr);
+}
+
#endif /* LIBXML_OUTPUT_ENABLED */
/************************************************************************
@@ -2708,6 +2735,8 @@ __xmlOutputBufferCreateFilename(const char *URI,
ret->writecallback = xmlGzfileWrite;
ret->closecallback = xmlGzfileClose;
}
+ else
+ xmlGzfileClose(context);
return(ret);
}
}
@@ -3377,7 +3406,7 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
if (out->writecallback)
nbchars = xmlBufUse(out->conv);
else
- nbchars = ret;
+ nbchars = ret >= 0 ? ret : 0;
} else {
ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
if (ret != 0)
@@ -3575,7 +3604,7 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
if (out->writecallback)
nbchars = xmlBufUse(out->conv);
else
- nbchars = ret;
+ nbchars = ret >= 0 ? ret : 0;
} else {
ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
diff --git a/contrib/libs/libxml/xmlmemory.c b/contrib/libs/libxml/xmlmemory.c
index 6f16c4b3ca..e0b2531a98 100644
--- a/contrib/libs/libxml/xmlmemory.c
+++ b/contrib/libs/libxml/xmlmemory.c
@@ -75,10 +75,10 @@ void xmlMallocBreakpoint(void);
#endif
/*
- * Each of the blocks allocated begin with a header containing informations
+ * Each of the blocks allocated begin with a header containing information
*/
-#define MEMTAG 0x5aa5
+#define MEMTAG 0x5aa5U
#define MALLOC_TYPE 1
#define REALLOC_TYPE 2
diff --git a/contrib/libs/libxml/xmlreader.c b/contrib/libs/libxml/xmlreader.c
index f3891e43af..72e40b0329 100644
--- a/contrib/libs/libxml/xmlreader.c
+++ b/contrib/libs/libxml/xmlreader.c
@@ -48,6 +48,13 @@
#define MAX_ERR_MSG_SIZE 64000
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/* Keeping free objects can hide memory errors. */
+#define MAX_FREE_NODES 1
+#else
+#define MAX_FREE_NODES 100
+#endif
+
/*
* The following VA_COPY was coded following an example in
* the Samba project. It may not be sufficient for some
@@ -279,6 +286,59 @@ xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
}
/**
+ * xmlTextReaderWalkRemoveRef:
+ * @data: Contents of current link
+ * @user: Value supplied by the user
+ *
+ * Returns 0 to abort the walk or 1 to continue
+ */
+static int
+xmlTextReaderWalkRemoveRef(const void *data, void *user)
+{
+ xmlRefPtr ref = (xmlRefPtr)data;
+ xmlAttrPtr attr = (xmlAttrPtr)user;
+
+ if (ref->attr == attr) { /* Matched: remove and terminate walk */
+ ref->name = xmlStrdup(attr->name);
+ ref->attr = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * xmlTextReaderRemoveRef:
+ * @doc: the document
+ * @attr: the attribute
+ *
+ * Remove the given attribute from the Ref table maintained internally.
+ *
+ * Returns -1 if the lookup failed and 0 otherwise
+ */
+static int
+xmlTextReaderRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
+ xmlListPtr ref_list;
+ xmlRefTablePtr table;
+ xmlChar *ID;
+
+ if (doc == NULL) return(-1);
+ if (attr == NULL) return(-1);
+ table = (xmlRefTablePtr) doc->refs;
+ if (table == NULL)
+ return(-1);
+
+ ID = xmlNodeListGetString(doc, attr->children, 1);
+ if (ID == NULL)
+ return(-1);
+ ref_list = xmlHashLookup(table, ID);
+ xmlFree(ID);
+ if(ref_list == NULL)
+ return (-1);
+ xmlListWalk(ref_list, xmlTextReaderWalkRemoveRef, attr);
+ return(0);
+}
+
+/**
* xmlTextReaderFreeProp:
* @reader: the xmlTextReaderPtr used
* @cur: the node
@@ -299,18 +359,20 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
/* Check for ID removal -> leading to invalid references ! */
- if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
- ((cur->parent->doc->intSubset != NULL) ||
- (cur->parent->doc->extSubset != NULL))) {
+ if ((cur->parent != NULL) && (cur->parent->doc != NULL)) {
if (xmlIsID(cur->parent->doc, cur->parent, cur))
xmlTextReaderRemoveID(cur->parent->doc, cur);
+ if (((cur->parent->doc->intSubset != NULL) ||
+ (cur->parent->doc->extSubset != NULL)) &&
+ (xmlIsRef(cur->parent->doc, cur->parent, cur)))
+ xmlTextReaderRemoveRef(cur->parent->doc, cur);
}
if (cur->children != NULL)
xmlTextReaderFreeNodeList(reader, cur->children);
DICT_FREE(cur->name);
if ((reader != NULL) && (reader->ctxt != NULL) &&
- (reader->ctxt->freeAttrsNr < 100)) {
+ (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeAttrs;
reader->ctxt->freeAttrs = cur;
reader->ctxt->freeAttrsNr++;
@@ -411,7 +473,7 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_TEXT_NODE)) &&
(reader != NULL) && (reader->ctxt != NULL) &&
- (reader->ctxt->freeElemsNr < 100)) {
+ (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeElems;
reader->ctxt->freeElems = cur;
reader->ctxt->freeElemsNr++;
@@ -499,7 +561,7 @@ xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_TEXT_NODE)) &&
(reader != NULL) && (reader->ctxt != NULL) &&
- (reader->ctxt->freeElemsNr < 100)) {
+ (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeElems;
reader->ctxt->freeElems = cur;
reader->ctxt->freeElemsNr++;
@@ -1106,20 +1168,9 @@ static void
xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
xmlNodePtr oldnode = reader->node;
xmlNodePtr node = reader->node;
- xmlParserCtxtPtr ctxt = reader->ctxt;
do {
if (node->type == XML_ENTITY_REF_NODE) {
- /*
- * Case where the underlying tree is not available, lookup the entity
- * and walk it.
- */
- if ((node->children == NULL) && (ctxt->sax != NULL) &&
- (ctxt->sax->getEntity != NULL)) {
- node->children = (xmlNodePtr)
- ctxt->sax->getEntity(ctxt, node->name);
- }
-
if ((node->children != NULL) &&
(node->children->type == XML_ENTITY_DECL) &&
(node->children->children != NULL)) {
@@ -1447,6 +1498,8 @@ get_next_node:
(reader->node->prev->type != XML_DTD_NODE)) {
xmlNodePtr tmp = reader->node->prev;
if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
+ if (oldnode == tmp)
+ oldnode = NULL;
xmlUnlinkNode(tmp);
xmlTextReaderFreeNode(reader, tmp);
}
@@ -1532,7 +1585,8 @@ node_found:
/*
* Handle XInclude if asked for
*/
- if ((reader->xinclude) && (reader->node != NULL) &&
+ if ((reader->xinclude) && (reader->in_xinclude == 0) &&
+ (reader->node != NULL) &&
(reader->node->type == XML_ELEMENT_NODE) &&
(reader->node->ns != NULL) &&
((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
@@ -1564,16 +1618,6 @@ node_found:
if ((reader->node != NULL) &&
(reader->node->type == XML_ENTITY_REF_NODE) &&
(reader->ctxt != NULL) && (reader->ctxt->replaceEntities == 1)) {
- /*
- * Case where the underlying tree is not available, lookup the entity
- * and walk it.
- */
- if ((reader->node->children == NULL) && (reader->ctxt->sax != NULL) &&
- (reader->ctxt->sax->getEntity != NULL)) {
- reader->node->children = (xmlNodePtr)
- reader->ctxt->sax->getEntity(reader->ctxt, reader->node->name);
- }
-
if ((reader->node->children != NULL) &&
(reader->node->children->type == XML_ENTITY_DECL) &&
(reader->node->children->children != NULL)) {
@@ -2281,14 +2325,18 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
if (reader->ctxt != NULL) {
if (reader->dict == reader->ctxt->dict)
reader->dict = NULL;
+#ifdef LIBXML_VALID_ENABLED
if ((reader->ctxt->vctxt.vstateTab != NULL) &&
(reader->ctxt->vctxt.vstateMax > 0)){
+#ifdef LIBXML_REGEXP_ENABLED
while (reader->ctxt->vctxt.vstateNr > 0)
xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
+#endif /* LIBXML_REGEXP_ENABLED */
xmlFree(reader->ctxt->vctxt.vstateTab);
reader->ctxt->vctxt.vstateTab = NULL;
reader->ctxt->vctxt.vstateMax = 0;
}
+#endif /* LIBXML_VALID_ENABLED */
if (reader->ctxt->myDoc != NULL) {
if (reader->preserve == 0)
xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
@@ -2971,7 +3019,7 @@ xmlTextReaderConstEncoding(xmlTextReaderPtr reader) {
/************************************************************************
* *
- * Acces API to the current node *
+ * Access API to the current node *
* *
************************************************************************/
/**
@@ -3786,7 +3834,7 @@ xmlTextReaderConstString(xmlTextReaderPtr reader, const xmlChar *str) {
*
* The value indicating whether to normalize white space and attribute values.
* Since attribute value and end of line normalizations are a MUST in the XML
- * specification only the value true is accepted. The broken bahaviour of
+ * specification only the value true is accepted. The broken behaviour of
* accepting out of range character entities like &#0; is of course not
* supported either.
*
@@ -3848,16 +3896,20 @@ xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
return(0);
case XML_PARSER_VALIDATE:
if (value != 0) {
+ ctxt->options |= XML_PARSE_DTDVALID;
ctxt->validate = 1;
reader->validate = XML_TEXTREADER_VALIDATE_DTD;
} else {
+ ctxt->options &= ~XML_PARSE_DTDVALID;
ctxt->validate = 0;
}
return(0);
case XML_PARSER_SUBST_ENTITIES:
if (value != 0) {
+ ctxt->options |= XML_PARSE_NOENT;
ctxt->replaceEntities = 1;
} else {
+ ctxt->options &= ~XML_PARSE_NOENT;
ctxt->replaceEntities = 0;
}
return(0);
diff --git a/contrib/libs/libxml/xmlregexp.c b/contrib/libs/libxml/xmlregexp.c
index c119ff1fb7..8d01c2ba32 100644
--- a/contrib/libs/libxml/xmlregexp.c
+++ b/contrib/libs/libxml/xmlregexp.c
@@ -26,6 +26,9 @@
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#include <libxml/tree.h>
#include <libxml/parserInternals.h>
@@ -36,6 +39,9 @@
#ifndef INT_MAX
#define INT_MAX 123456789 /* easy to flag and big enough for our needs */
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
/* #define DEBUG_REGEXP_GRAPH */
/* #define DEBUG_REGEXP_EXEC */
@@ -267,6 +273,8 @@ struct _xmlAutomata {
int determinist;
int negs;
int flags;
+
+ int depth;
};
struct _xmlRegexp {
@@ -418,6 +426,32 @@ xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra)
************************************************************************/
static int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt);
+
+/**
+ * xmlRegCalloc2:
+ * @dim1: size of first dimension
+ * @dim2: size of second dimension
+ * @elemSize: size of element
+ *
+ * Allocate a two-dimensional array and set all elements to zero.
+ *
+ * Returns the new array or NULL in case of error.
+ */
+static void*
+xmlRegCalloc2(size_t dim1, size_t dim2, size_t elemSize) {
+ size_t totalSize;
+ void *ret;
+
+ /* Check for overflow */
+ if (dim1 > SIZE_MAX / dim2 / elemSize)
+ return (NULL);
+ totalSize = dim1 * dim2 * elemSize;
+ ret = xmlMalloc(totalSize);
+ if (ret != NULL)
+ memset(ret, 0, totalSize);
+ return (ret);
+}
+
/**
* xmlRegEpxFromParse:
* @ctxt: the parser context used to build it
@@ -540,8 +574,8 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
#ifdef DEBUG_COMPACTION
printf("Final: %d atoms\n", nbatoms);
#endif
- transitions = (int *) xmlMalloc((nbstates + 1) *
- (nbatoms + 1) * sizeof(int));
+ transitions = (int *) xmlRegCalloc2(nbstates + 1, nbatoms + 1,
+ sizeof(int));
if (transitions == NULL) {
xmlFree(stateRemap);
xmlFree(stringRemap);
@@ -551,7 +585,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
xmlFree(ret);
return(NULL);
}
- memset(transitions, 0, (nbstates + 1) * (nbatoms + 1) * sizeof(int));
/*
* Allocate the transition table. The first entry for each
@@ -577,12 +610,9 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
continue;
atomno = stringRemap[trans->atom->no];
if ((trans->atom->data != NULL) && (transdata == NULL)) {
- transdata = (void **) xmlMalloc(nbstates * nbatoms *
- sizeof(void *));
- if (transdata != NULL)
- memset(transdata, 0,
- nbstates * nbatoms * sizeof(void *));
- else {
+ transdata = (void **) xmlRegCalloc2(nbstates, nbatoms,
+ sizeof(void *));
+ if (transdata == NULL) {
xmlRegexpErrMemory(ctxt, "compiling regexp");
break;
}
@@ -1862,6 +1892,12 @@ xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr,
* then X and Y are semantically equivalent and X can be eliminated
* If X is the start state then make Y the start state, else replace the
* target of all transitions to X by transitions to Y.
+ *
+ * If X is a final state, skip it.
+ * Otherwise it would be necessary to manipulate counters for this case when
+ * eliminating state 2:
+ * State 1 has a transition with an atom to state 2.
+ * State 2 is final and has an epsilon transition to state 1.
*/
static void
xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
@@ -1874,7 +1910,8 @@ xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
continue;
if (state->nbTrans != 1)
continue;
- if (state->type == XML_REGEXP_UNREACH_STATE)
+ if (state->type == XML_REGEXP_UNREACH_STATE ||
+ state->type == XML_REGEXP_FINAL_STATE)
continue;
/* is the only transition out a basic transition */
if ((state->trans[0].atom == NULL) &&
@@ -2628,7 +2665,6 @@ xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
state->markd = XML_REGEXP_MARK_VISITED;
res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
to, atom);
- state->markd = 0;
if (res == 0) {
ret = 0;
/* t1->nd = 1; */
@@ -2647,6 +2683,30 @@ xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
}
/**
+ * xmlFAFinishRecurseDeterminism:
+ * @ctxt: a regexp parser context
+ *
+ * Reset flags after checking determinism.
+ */
+static void
+xmlFAFinishRecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
+ int transnr, nbTrans;
+
+ if (state == NULL)
+ return;
+ if (state->markd != XML_REGEXP_MARK_VISITED)
+ return;
+ state->markd = 0;
+
+ nbTrans = state->nbTrans;
+ for (transnr = 0; transnr < nbTrans; transnr++) {
+ xmlRegTransPtr t1 = &state->trans[transnr];
+ if ((t1->atom == NULL) && (t1->to >= 0))
+ xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t1->to]);
+ }
+}
+
+/**
* xmlFAComputesDeterminism:
* @ctxt: a regexp parser context
*
@@ -2759,6 +2819,7 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
*/
ret = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
t2->to, t2->atom);
+ xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t1->to]);
/* don't shortcut the computation so all non deterministic
transition get marked down
if (ret == 0)
@@ -4221,7 +4282,7 @@ xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value,
* @values: pointer to the array of acceptable values
* @terminal: return value if this was a terminal state
*
- * Extract informations from the regexp execution, internal routine to
+ * Extract information from the regexp execution, internal routine to
* implement xmlRegExecNextValues() and xmlRegExecErrInfo()
*
* Returns: 0 in case of success or -1 in case of error.
@@ -4380,7 +4441,7 @@ xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
* @values: pointer to the array of acceptable values
* @terminal: return value if this was a terminal state
*
- * Extract informations from the regexp execution,
+ * Extract information from the regexp execution,
* the parameter @values must point to an array of @nbval string pointers
* on return nbval will contain the number of possible strings in that
* state and the @values array will be updated with them. The string values
@@ -4404,7 +4465,7 @@ xmlRegExecNextValues(xmlRegExecCtxtPtr exec, int *nbval, int *nbneg,
* @values: pointer to the array of acceptable values
* @terminal: return value if this was a terminal state
*
- * Extract error informations from the regexp execution, the parameter
+ * Extract error information from the regexp execution, the parameter
* @string will be updated with the value pushed and not accepted,
* the parameter @values must point to an array of @nbval string pointers
* on return nbval will contain the number of possible strings in that
@@ -5101,7 +5162,7 @@ xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) {
} else {
xmlFAParseCharRange(ctxt);
}
- } while ((CUR != ']') && (CUR != '^') && (CUR != '-') &&
+ } while ((CUR != ']') && (CUR != '-') &&
(CUR != 0) && (ctxt->error == 0));
}
@@ -5116,34 +5177,31 @@ xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) {
*/
static void
xmlFAParseCharGroup(xmlRegParserCtxtPtr ctxt) {
- int n = ctxt->neg;
- while ((CUR != ']') && (ctxt->error == 0)) {
- if (CUR == '^') {
- int neg = ctxt->neg;
+ int neg = ctxt->neg;
- NEXT;
- ctxt->neg = !ctxt->neg;
- xmlFAParsePosCharGroup(ctxt);
- ctxt->neg = neg;
- } else if ((CUR == '-') && (NXT(1) == '[')) {
- int neg = ctxt->neg;
- ctxt->neg = 2;
+ if (CUR == '^') {
+ NEXT;
+ ctxt->neg = !ctxt->neg;
+ xmlFAParsePosCharGroup(ctxt);
+ ctxt->neg = neg;
+ }
+ while ((CUR != ']') && (ctxt->error == 0)) {
+ if ((CUR == '-') && (NXT(1) == '[')) {
NEXT; /* eat the '-' */
NEXT; /* eat the '[' */
+ ctxt->neg = 2;
xmlFAParseCharGroup(ctxt);
+ ctxt->neg = neg;
if (CUR == ']') {
NEXT;
} else {
ERROR("charClassExpr: ']' expected");
- break;
}
- ctxt->neg = neg;
break;
- } else if (CUR != ']') {
+ } else {
xmlFAParsePosCharGroup(ctxt);
}
}
- ctxt->neg = n;
}
/**
@@ -5183,13 +5241,24 @@ static int
xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
int ret = 0;
int ok = 0;
+ int overflow = 0;
while ((CUR >= '0') && (CUR <= '9')) {
- ret = ret * 10 + (CUR - '0');
+ if (ret > INT_MAX / 10) {
+ overflow = 1;
+ } else {
+ int digit = CUR - '0';
+
+ ret *= 10;
+ if (ret > INT_MAX - digit)
+ overflow = 1;
+ else
+ ret += digit;
+ }
ok = 1;
NEXT;
}
- if (ok != 1) {
+ if ((ok != 1) || (overflow == 1)) {
return(-1);
}
return(ret);
@@ -5229,6 +5298,9 @@ xmlFAParseQuantifier(xmlRegParserCtxtPtr ctxt) {
cur = xmlFAParseQuantExact(ctxt);
if (cur >= 0)
min = cur;
+ else {
+ ERROR("Improper quantifier");
+ }
if (CUR == ',') {
NEXT;
if (CUR == '}')
@@ -5288,6 +5360,10 @@ xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
xmlRegStatePtr start, oldend, start0;
NEXT;
+ if (ctxt->depth >= 50) {
+ ERROR("xmlFAParseAtom: maximum nesting depth exceeded");
+ return(-1);
+ }
/*
* this extra Epsilon transition is needed if we count with 0 allowed
* unfortunately this can't be known at that point
@@ -5299,7 +5375,9 @@ xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
oldend = ctxt->end;
ctxt->end = NULL;
ctxt->atom = NULL;
+ ctxt->depth++;
xmlFAParseRegExp(ctxt, 0);
+ ctxt->depth--;
if (CUR == ')') {
NEXT;
} else {
@@ -6055,7 +6133,7 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
return(NULL);
if (min < 1)
return(NULL);
- if ((max < min) || (max < 1))
+ if (max < min)
return(NULL);
atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
if (atom == NULL)
@@ -6134,7 +6212,7 @@ xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
return(NULL);
if (min < 1)
return(NULL);
- if ((max < min) || (max < 1))
+ if (max < min)
return(NULL);
atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
if (atom == NULL)
diff --git a/contrib/libs/libxml/xmlsave.c b/contrib/libs/libxml/xmlsave.c
index fa00915371..489505f486 100644
--- a/contrib/libs/libxml/xmlsave.c
+++ b/contrib/libs/libxml/xmlsave.c
@@ -100,7 +100,7 @@ struct _xmlSaveCtxt {
************************************************************************/
/**
* xmlSaveErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -114,7 +114,7 @@ xmlSaveErrMemory(const char *extra)
* xmlSaveErr:
* @code: the error number
* @node: the location of the error.
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -590,7 +590,6 @@ static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
static void
xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
#endif
-static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
@@ -705,6 +704,7 @@ xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
static void
xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
xmlOutputBufferPtr buf;
+ xmlNodePtr cur;
int format, level;
if (dtd == NULL) return;
@@ -742,7 +742,9 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
level = ctxt->level;
ctxt->format = 0;
ctxt->level = -1;
- xmlNodeListDumpOutput(ctxt, dtd->children);
+ for (cur = dtd->children; cur != NULL; cur = cur->next) {
+ xmlNodeDumpOutputInternal(ctxt, cur);
+ }
ctxt->format = format;
ctxt->level = level;
xmlOutputBufferWrite(buf, 2, "]>");
@@ -776,58 +778,9 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
xmlOutputBufferWrite(buf, 1, "\"");
}
-/**
- * xmlAttrListDumpOutput:
- * @buf: the XML buffer output
- * @doc: the document
- * @cur: the first attribute pointer
- * @encoding: an optional encoding string
- *
- * Dump a list of XML attributes
- */
-static void
-xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
- if (cur == NULL) return;
- while (cur != NULL) {
- xmlAttrDumpOutput(ctxt, cur);
- cur = cur->next;
- }
-}
-
-
-
-/**
- * xmlNodeListDumpOutput:
- * @cur: the first node
- *
- * Dump an XML node list, recursive behaviour, children are printed too.
- */
-static void
-xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
- xmlOutputBufferPtr buf;
-
- if (cur == NULL) return;
- buf = ctxt->buf;
- while (cur != NULL) {
- if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
- ((cur->type == XML_ELEMENT_NODE) ||
- (cur->type == XML_COMMENT_NODE) ||
- (cur->type == XML_PI_NODE)))
- xmlOutputBufferWrite(buf, ctxt->indent_size *
- (ctxt->level > ctxt->indent_nr ?
- ctxt->indent_nr : ctxt->level),
- ctxt->indent);
- xmlNodeDumpOutputInternal(ctxt, cur);
- if (ctxt->format == 1) {
- xmlOutputBufferWrite(buf, 1, "\n");
- }
- cur = cur->next;
- }
-}
-
#ifdef LIBXML_HTML_ENABLED
/**
- * xmlNodeDumpOutputInternal:
+ * htmlNodeDumpOutputInternal:
* @cur: the current node
*
* Dump an HTML node, recursive behaviour, children are printed too.
@@ -893,57 +846,126 @@ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
*/
static void
xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
- int format;
- xmlNodePtr tmp;
+ int format = ctxt->format;
+ xmlNodePtr tmp, root, unformattedNode = NULL, parent;
+ xmlAttrPtr attr;
xmlChar *start, *end;
xmlOutputBufferPtr buf;
if (cur == NULL) return;
buf = ctxt->buf;
- if (cur->type == XML_XINCLUDE_START)
- return;
- if (cur->type == XML_XINCLUDE_END)
- return;
- if ((cur->type == XML_DOCUMENT_NODE) ||
- (cur->type == XML_HTML_DOCUMENT_NODE)) {
- xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
- return;
- }
-#ifdef LIBXML_HTML_ENABLED
- if (ctxt->options & XML_SAVE_XHTML) {
- xhtmlNodeDumpOutput(ctxt, cur);
- return;
- }
- if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
- (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
- ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
- (ctxt->options & XML_SAVE_AS_HTML)) {
- htmlNodeDumpOutputInternal(ctxt, cur);
- return;
- }
-#endif
- if (cur->type == XML_DTD_NODE) {
- xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
- return;
- }
- if (cur->type == XML_DOCUMENT_FRAG_NODE) {
- xmlNodeListDumpOutput(ctxt, cur->children);
- return;
- }
- if (cur->type == XML_ELEMENT_DECL) {
- xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
- return;
- }
- if (cur->type == XML_ATTRIBUTE_DECL) {
- xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
- return;
- }
- if (cur->type == XML_ENTITY_DECL) {
- xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
- return;
- }
- if (cur->type == XML_TEXT_NODE) {
- if (cur->content != NULL) {
+
+ root = cur;
+ parent = cur->parent;
+ while (1) {
+ switch (cur->type) {
+ case XML_DOCUMENT_NODE:
+ case XML_HTML_DOCUMENT_NODE:
+ xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
+ break;
+
+ case XML_DTD_NODE:
+ xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
+ break;
+
+ case XML_DOCUMENT_FRAG_NODE:
+ /* Always validate cur->parent when descending. */
+ if ((cur->parent == parent) && (cur->children != NULL)) {
+ parent = cur;
+ cur = cur->children;
+ continue;
+ }
+ break;
+
+ case XML_ELEMENT_DECL:
+ xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
+ break;
+
+ case XML_ATTRIBUTE_DECL:
+ xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
+ break;
+
+ case XML_ENTITY_DECL:
+ xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
+ break;
+
+ case XML_ELEMENT_NODE:
+ if ((cur != root) && (ctxt->format == 1) &&
+ (xmlIndentTreeOutput))
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level > ctxt->indent_nr ?
+ 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)) {
+ xmlNodeDumpOutputInternal(ctxt, cur);
+ break;
+ }
+
+ xmlOutputBufferWrite(buf, 1, "<");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWrite(buf, 1, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->nsDef)
+ xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
+ for (attr = cur->properties; attr != NULL; attr = attr->next)
+ xmlAttrDumpOutput(ctxt, attr);
+
+ if (cur->children == NULL) {
+ if ((ctxt->options & XML_SAVE_NO_EMPTY) == 0) {
+ if (ctxt->format == 2)
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
+ xmlOutputBufferWrite(buf, 2, "/>");
+ } else {
+ if (ctxt->format == 2)
+ xmlOutputBufferWriteWSNonSig(ctxt, 1);
+ xmlOutputBufferWrite(buf, 3, "></");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->ns->prefix);
+ xmlOutputBufferWrite(buf, 1, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (ctxt->format == 2)
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
+ xmlOutputBufferWrite(buf, 1, ">");
+ }
+ } else {
+ if (ctxt->format == 1) {
+ tmp = cur->children;
+ while (tmp != NULL) {
+ if ((tmp->type == XML_TEXT_NODE) ||
+ (tmp->type == XML_CDATA_SECTION_NODE) ||
+ (tmp->type == XML_ENTITY_REF_NODE)) {
+ ctxt->format = 0;
+ unformattedNode = cur;
+ break;
+ }
+ tmp = tmp->next;
+ }
+ }
+ if (ctxt->format == 2)
+ xmlOutputBufferWriteWSNonSig(ctxt, 1);
+ xmlOutputBufferWrite(buf, 1, ">");
+ if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
+ if (ctxt->level >= 0) ctxt->level++;
+ parent = cur;
+ cur = cur->children;
+ continue;
+ }
+
+ break;
+
+ case XML_TEXT_NODE:
+ if (cur->content == NULL)
+ break;
if (cur->name != xmlStringTextNoenc) {
xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
} else {
@@ -952,139 +974,136 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
*/
xmlOutputBufferWriteString(buf, (const char *) cur->content);
}
- }
+ break;
- return;
- }
- if (cur->type == XML_PI_NODE) {
- if (cur->content != NULL) {
- xmlOutputBufferWrite(buf, 2, "<?");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (cur->content != NULL) {
- if (ctxt->format == 2)
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
- else
- xmlOutputBufferWrite(buf, 1, " ");
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- }
- xmlOutputBufferWrite(buf, 2, "?>");
- } else {
- xmlOutputBufferWrite(buf, 2, "<?");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (ctxt->format == 2)
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
- xmlOutputBufferWrite(buf, 2, "?>");
- }
- return;
- }
- if (cur->type == XML_COMMENT_NODE) {
- if (cur->content != NULL) {
- xmlOutputBufferWrite(buf, 4, "<!--");
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- xmlOutputBufferWrite(buf, 3, "-->");
- }
- return;
- }
- if (cur->type == XML_ENTITY_REF_NODE) {
- xmlOutputBufferWrite(buf, 1, "&");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWrite(buf, 1, ";");
- return;
- }
- if (cur->type == XML_CDATA_SECTION_NODE) {
- if (cur->content == NULL || *cur->content == '\0') {
- xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
- } else {
- start = end = cur->content;
- while (*end != '\0') {
- if ((*end == ']') && (*(end + 1) == ']') &&
- (*(end + 2) == '>')) {
- end = end + 2;
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
- xmlOutputBufferWrite(buf, end - start, (const char *)start);
- xmlOutputBufferWrite(buf, 3, "]]>");
- start = end;
- }
- end++;
- }
- if (start != end) {
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
- xmlOutputBufferWriteString(buf, (const char *)start);
- xmlOutputBufferWrite(buf, 3, "]]>");
- }
- }
- return;
- }
- if (cur->type == XML_ATTRIBUTE_NODE) {
- xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
- return;
- }
- if (cur->type == XML_NAMESPACE_DECL) {
- xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
- return;
- }
+ case XML_PI_NODE:
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level),
+ ctxt->indent);
+
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 2, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->content != NULL) {
+ if (ctxt->format == 2)
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
+ else
+ xmlOutputBufferWrite(buf, 1, " ");
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->content);
+ }
+ xmlOutputBufferWrite(buf, 2, "?>");
+ } else {
+ xmlOutputBufferWrite(buf, 2, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (ctxt->format == 2)
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
+ xmlOutputBufferWrite(buf, 2, "?>");
+ }
+ break;
+
+ case XML_COMMENT_NODE:
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level),
+ ctxt->indent);
+
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 4, "<!--");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ xmlOutputBufferWrite(buf, 3, "-->");
+ }
+ break;
+
+ case XML_ENTITY_REF_NODE:
+ xmlOutputBufferWrite(buf, 1, "&");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWrite(buf, 1, ";");
+ break;
+
+ case XML_CDATA_SECTION_NODE:
+ if (cur->content == NULL || *cur->content == '\0') {
+ xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
+ } else {
+ start = end = cur->content;
+ while (*end != '\0') {
+ if ((*end == ']') && (*(end + 1) == ']') &&
+ (*(end + 2) == '>')) {
+ end = end + 2;
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWrite(buf, end - start,
+ (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ start = end;
+ }
+ end++;
+ }
+ if (start != end) {
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWriteString(buf, (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ }
+ }
+ break;
- format = ctxt->format;
- if (format == 1) {
- tmp = cur->children;
- while (tmp != NULL) {
- if ((tmp->type == XML_TEXT_NODE) ||
- (tmp->type == XML_CDATA_SECTION_NODE) ||
- (tmp->type == XML_ENTITY_REF_NODE)) {
- ctxt->format = 0;
- break;
- }
- tmp = tmp->next;
- }
- }
- xmlOutputBufferWrite(buf, 1, "<");
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
- xmlOutputBufferWrite(buf, 1, ":");
- }
+ case XML_ATTRIBUTE_NODE:
+ xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
+ break;
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (cur->nsDef)
- xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
- if (cur->properties != NULL)
- xmlAttrListDumpOutput(ctxt, cur->properties);
-
- if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
- (cur->children == NULL) && ((ctxt->options & XML_SAVE_NO_EMPTY) == 0)) {
- if (ctxt->format == 2)
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
- xmlOutputBufferWrite(buf, 2, "/>");
- ctxt->format = format;
- return;
- }
- if (ctxt->format == 2)
- xmlOutputBufferWriteWSNonSig(ctxt, 1);
- xmlOutputBufferWrite(buf, 1, ">");
- if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
- xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
- }
- if (cur->children != NULL) {
- if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
- if (ctxt->level >= 0) ctxt->level++;
- xmlNodeListDumpOutput(ctxt, cur->children);
- if (ctxt->level > 0) ctxt->level--;
- if ((xmlIndentTreeOutput) && (ctxt->format == 1))
- xmlOutputBufferWrite(buf, ctxt->indent_size *
- (ctxt->level > ctxt->indent_nr ?
- ctxt->indent_nr : ctxt->level),
- ctxt->indent);
- }
- xmlOutputBufferWrite(buf, 2, "</");
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
- xmlOutputBufferWrite(buf, 1, ":");
- }
+ case XML_NAMESPACE_DECL:
+ xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
+ break;
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (ctxt->format == 2)
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
- xmlOutputBufferWrite(buf, 1, ">");
- ctxt->format = format;
+ default:
+ break;
+ }
+
+ while (1) {
+ if (cur == root)
+ return;
+ if ((ctxt->format == 1) &&
+ (cur->type != XML_XINCLUDE_START) &&
+ (cur->type != XML_XINCLUDE_END))
+ xmlOutputBufferWrite(buf, 1, "\n");
+ if (cur->next != NULL) {
+ cur = cur->next;
+ break;
+ }
+
+ cur = parent;
+ /* cur->parent was validated when descending. */
+ parent = cur->parent;
+
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (ctxt->level > 0) ctxt->level--;
+ if ((xmlIndentTreeOutput) && (ctxt->format == 1))
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level),
+ ctxt->indent);
+
+ xmlOutputBufferWrite(buf, 2, "</");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->ns->prefix);
+ xmlOutputBufferWrite(buf, 1, ":");
+ }
+
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (ctxt->format == 2)
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
+ xmlOutputBufferWrite(buf, 1, ">");
+
+ if (cur == unformattedNode) {
+ ctxt->format = format;
+ unformattedNode = NULL;
+ }
+ }
+ }
+ }
}
/**
@@ -1224,7 +1243,9 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
else
#endif
xmlNodeDumpOutputInternal(ctxt, child);
- xmlOutputBufferWrite(buf, 1, "\n");
+ if ((child->type != XML_XINCLUDE_START) &&
+ (child->type != XML_XINCLUDE_END))
+ xmlOutputBufferWrite(buf, 1, "\n");
child = child->next;
}
}
@@ -1396,40 +1417,6 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
}
/**
- * xhtmlNodeListDumpOutput:
- * @buf: the XML buffer output
- * @doc: the XHTML document
- * @cur: the first node
- * @level: the imbrication level for indenting
- * @format: is formatting allowed
- * @encoding: an optional encoding string
- *
- * Dump an XML node list, recursive behaviour, children are printed too.
- * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
- * or xmlKeepBlanksDefault(0) was called
- */
-static void
-xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
- xmlOutputBufferPtr buf;
-
- if (cur == NULL) return;
- buf = ctxt->buf;
- while (cur != NULL) {
- if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
- (cur->type == XML_ELEMENT_NODE))
- xmlOutputBufferWrite(buf, ctxt->indent_size *
- (ctxt->level > ctxt->indent_nr ?
- ctxt->indent_nr : ctxt->level),
- ctxt->indent);
- xhtmlNodeDumpOutput(ctxt, cur);
- if (ctxt->format == 1) {
- xmlOutputBufferWrite(buf, 1, "\n");
- }
- cur = cur->next;
- }
-}
-
-/**
* xhtmlNodeDumpOutput:
* @buf: the XML buffer output
* @doc: the XHTML document
@@ -1442,48 +1429,195 @@ xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
*/
static void
xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
- int format, addmeta = 0;
- xmlNodePtr tmp;
+ int format = ctxt->format, addmeta;
+ xmlNodePtr tmp, root, unformattedNode = NULL;
xmlChar *start, *end;
- xmlOutputBufferPtr buf;
+ xmlOutputBufferPtr buf = ctxt->buf;
if (cur == NULL) return;
- if ((cur->type == XML_DOCUMENT_NODE) ||
- (cur->type == XML_HTML_DOCUMENT_NODE)) {
- xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
- return;
- }
- if (cur->type == XML_XINCLUDE_START)
- return;
- if (cur->type == XML_XINCLUDE_END)
- return;
- if (cur->type == XML_NAMESPACE_DECL) {
- xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
- return;
- }
- if (cur->type == XML_DTD_NODE) {
- xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
- return;
- }
- if (cur->type == XML_DOCUMENT_FRAG_NODE) {
- xhtmlNodeListDumpOutput(ctxt, cur->children);
- return;
- }
- buf = ctxt->buf;
- if (cur->type == XML_ELEMENT_DECL) {
- xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
- return;
- }
- if (cur->type == XML_ATTRIBUTE_DECL) {
- xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
- return;
- }
- if (cur->type == XML_ENTITY_DECL) {
- xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
- return;
- }
- if (cur->type == XML_TEXT_NODE) {
- if (cur->content != NULL) {
+
+ root = cur;
+ while (1) {
+ switch (cur->type) {
+ case XML_DOCUMENT_NODE:
+ case XML_HTML_DOCUMENT_NODE:
+ xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
+ break;
+
+ case XML_NAMESPACE_DECL:
+ xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
+ break;
+
+ case XML_DTD_NODE:
+ xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
+ break;
+
+ case XML_DOCUMENT_FRAG_NODE:
+ if (cur->children) {
+ cur = cur->children;
+ continue;
+ }
+ break;
+
+ case XML_ELEMENT_DECL:
+ xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
+ break;
+
+ case XML_ATTRIBUTE_DECL:
+ xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
+ break;
+
+ case XML_ENTITY_DECL:
+ xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
+ break;
+
+ case XML_ELEMENT_NODE:
+ addmeta = 0;
+
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level),
+ ctxt->indent);
+
+ xmlOutputBufferWrite(buf, 1, "<");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWrite(buf, 1, ":");
+ }
+
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->nsDef)
+ xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
+ if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
+ (cur->ns == NULL) && (cur->nsDef == NULL))) {
+ /*
+ * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
+ */
+ xmlOutputBufferWriteString(buf,
+ " xmlns=\"http://www.w3.org/1999/xhtml\"");
+ }
+ if (cur->properties != NULL)
+ xhtmlAttrListDumpOutput(ctxt, cur->properties);
+
+ if ((cur->parent != NULL) &&
+ (cur->parent->parent == (xmlNodePtr) cur->doc) &&
+ xmlStrEqual(cur->name, BAD_CAST"head") &&
+ xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
+
+ tmp = cur->children;
+ while (tmp != NULL) {
+ if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
+ xmlChar *httpequiv;
+
+ httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
+ if (httpequiv != NULL) {
+ if (xmlStrcasecmp(httpequiv,
+ BAD_CAST"Content-Type") == 0) {
+ xmlFree(httpequiv);
+ break;
+ }
+ xmlFree(httpequiv);
+ }
+ }
+ tmp = tmp->next;
+ }
+ if (tmp == NULL)
+ addmeta = 1;
+ }
+
+ if (cur->children == NULL) {
+ if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
+ ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
+ /*
+ * C.2. Empty Elements
+ */
+ xmlOutputBufferWrite(buf, 3, " />");
+ } else {
+ if (addmeta == 1) {
+ xmlOutputBufferWrite(buf, 1, ">");
+ if (ctxt->format == 1) {
+ xmlOutputBufferWrite(buf, 1, "\n");
+ if (xmlIndentTreeOutput)
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level + 1 > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level + 1),
+ ctxt->indent);
+ }
+ xmlOutputBufferWriteString(buf,
+ "<meta http-equiv=\"Content-Type\" "
+ "content=\"text/html; charset=");
+ if (ctxt->encoding) {
+ xmlOutputBufferWriteString(buf,
+ (const char *)ctxt->encoding);
+ } else {
+ xmlOutputBufferWrite(buf, 5, "UTF-8");
+ }
+ xmlOutputBufferWrite(buf, 4, "\" />");
+ if (ctxt->format == 1)
+ xmlOutputBufferWrite(buf, 1, "\n");
+ } else {
+ xmlOutputBufferWrite(buf, 1, ">");
+ }
+ /*
+ * C.3. Element Minimization and Empty Element Content
+ */
+ xmlOutputBufferWrite(buf, 2, "</");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->ns->prefix);
+ xmlOutputBufferWrite(buf, 1, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWrite(buf, 1, ">");
+ }
+ } else {
+ xmlOutputBufferWrite(buf, 1, ">");
+ if (addmeta == 1) {
+ if (ctxt->format == 1) {
+ xmlOutputBufferWrite(buf, 1, "\n");
+ if (xmlIndentTreeOutput)
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level + 1 > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level + 1),
+ ctxt->indent);
+ }
+ xmlOutputBufferWriteString(buf,
+ "<meta http-equiv=\"Content-Type\" "
+ "content=\"text/html; charset=");
+ if (ctxt->encoding) {
+ xmlOutputBufferWriteString(buf,
+ (const char *)ctxt->encoding);
+ } else {
+ xmlOutputBufferWrite(buf, 5, "UTF-8");
+ }
+ xmlOutputBufferWrite(buf, 4, "\" />");
+ }
+
+ if (ctxt->format == 1) {
+ tmp = cur->children;
+ while (tmp != NULL) {
+ if ((tmp->type == XML_TEXT_NODE) ||
+ (tmp->type == XML_ENTITY_REF_NODE)) {
+ unformattedNode = cur;
+ ctxt->format = 0;
+ break;
+ }
+ tmp = tmp->next;
+ }
+ }
+
+ if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
+ if (ctxt->level >= 0) ctxt->level++;
+ cur = cur->children;
+ continue;
+ }
+
+ break;
+
+ case XML_TEXT_NODE:
+ if (cur->content == NULL)
+ break;
if ((cur->name == xmlStringText) ||
(cur->name != xmlStringTextNoenc)) {
xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
@@ -1493,286 +1627,115 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
*/
xmlOutputBufferWriteString(buf, (const char *) cur->content);
}
- }
-
- return;
- }
- if (cur->type == XML_PI_NODE) {
- if (cur->content != NULL) {
- xmlOutputBufferWrite(buf, 2, "<?");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (cur->content != NULL) {
- xmlOutputBufferWrite(buf, 1, " ");
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- }
- xmlOutputBufferWrite(buf, 2, "?>");
- } else {
- xmlOutputBufferWrite(buf, 2, "<?");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWrite(buf, 2, "?>");
- }
- return;
- }
- if (cur->type == XML_COMMENT_NODE) {
- if (cur->content != NULL) {
- xmlOutputBufferWrite(buf, 4, "<!--");
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
- xmlOutputBufferWrite(buf, 3, "-->");
- }
- return;
- }
- if (cur->type == XML_ENTITY_REF_NODE) {
- xmlOutputBufferWrite(buf, 1, "&");
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWrite(buf, 1, ";");
- return;
- }
- if (cur->type == XML_CDATA_SECTION_NODE) {
- if (cur->content == NULL || *cur->content == '\0') {
- xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
- } else {
- start = end = cur->content;
- while (*end != '\0') {
- if (*end == ']' && *(end + 1) == ']' && *(end + 2) == '>') {
- end = end + 2;
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
- xmlOutputBufferWrite(buf, end - start, (const char *)start);
- xmlOutputBufferWrite(buf, 3, "]]>");
- start = end;
- }
- end++;
- }
- if (start != end) {
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
- xmlOutputBufferWriteString(buf, (const char *)start);
- xmlOutputBufferWrite(buf, 3, "]]>");
- }
- }
- return;
- }
- if (cur->type == XML_ATTRIBUTE_NODE) {
- xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
- return;
- }
+ break;
- format = ctxt->format;
- if (format == 1) {
- tmp = cur->children;
- while (tmp != NULL) {
- if ((tmp->type == XML_TEXT_NODE) ||
- (tmp->type == XML_ENTITY_REF_NODE)) {
- format = 0;
- break;
- }
- tmp = tmp->next;
- }
- }
- xmlOutputBufferWrite(buf, 1, "<");
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
- xmlOutputBufferWrite(buf, 1, ":");
- }
+ case XML_PI_NODE:
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 2, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 1, " ");
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->content);
+ }
+ xmlOutputBufferWrite(buf, 2, "?>");
+ } else {
+ xmlOutputBufferWrite(buf, 2, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWrite(buf, 2, "?>");
+ }
+ break;
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- if (cur->nsDef)
- xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
- if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
- (cur->ns == NULL) && (cur->nsDef == NULL))) {
- /*
- * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
- */
- xmlOutputBufferWriteString(buf,
- " xmlns=\"http://www.w3.org/1999/xhtml\"");
- }
- if (cur->properties != NULL)
- xhtmlAttrListDumpOutput(ctxt, cur->properties);
-
- if ((cur->type == XML_ELEMENT_NODE) &&
- (cur->parent != NULL) &&
- (cur->parent->parent == (xmlNodePtr) cur->doc) &&
- xmlStrEqual(cur->name, BAD_CAST"head") &&
- xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
-
- tmp = cur->children;
- while (tmp != NULL) {
- if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
- xmlChar *httpequiv;
-
- httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
- if (httpequiv != NULL) {
- if (xmlStrcasecmp(httpequiv, BAD_CAST"Content-Type") == 0) {
- xmlFree(httpequiv);
- break;
+ case XML_COMMENT_NODE:
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 4, "<!--");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ xmlOutputBufferWrite(buf, 3, "-->");
+ }
+ break;
+
+ case XML_ENTITY_REF_NODE:
+ xmlOutputBufferWrite(buf, 1, "&");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWrite(buf, 1, ";");
+ break;
+
+ case XML_CDATA_SECTION_NODE:
+ if (cur->content == NULL || *cur->content == '\0') {
+ xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
+ } else {
+ start = end = cur->content;
+ while (*end != '\0') {
+ if (*end == ']' && *(end + 1) == ']' &&
+ *(end + 2) == '>') {
+ end = end + 2;
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWrite(buf, end - start,
+ (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ start = end;
}
- xmlFree(httpequiv);
+ end++;
+ }
+ if (start != end) {
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWriteString(buf, (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
}
}
- tmp = tmp->next;
+ break;
+
+ case XML_ATTRIBUTE_NODE:
+ xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
+ break;
+
+ default:
+ break;
}
- if (tmp == NULL)
- addmeta = 1;
- }
- if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) {
- if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
- ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
- /*
- * C.2. Empty Elements
- */
- xmlOutputBufferWrite(buf, 3, " />");
- } else {
- if (addmeta == 1) {
- xmlOutputBufferWrite(buf, 1, ">");
- if (ctxt->format == 1) {
- xmlOutputBufferWrite(buf, 1, "\n");
- if (xmlIndentTreeOutput)
- xmlOutputBufferWrite(buf, ctxt->indent_size *
- (ctxt->level + 1 > ctxt->indent_nr ?
- ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
- }
- xmlOutputBufferWriteString(buf,
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
- if (ctxt->encoding) {
- xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
- } else {
- xmlOutputBufferWrite(buf, 5, "UTF-8");
- }
- xmlOutputBufferWrite(buf, 4, "\" />");
- if (ctxt->format == 1)
- xmlOutputBufferWrite(buf, 1, "\n");
- } else {
- xmlOutputBufferWrite(buf, 1, ">");
- }
- /*
- * C.3. Element Minimization and Empty Element Content
- */
- xmlOutputBufferWrite(buf, 2, "</");
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
- xmlOutputBufferWrite(buf, 1, ":");
- }
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWrite(buf, 1, ">");
- }
- return;
- }
- xmlOutputBufferWrite(buf, 1, ">");
- if (addmeta == 1) {
- if (ctxt->format == 1) {
- xmlOutputBufferWrite(buf, 1, "\n");
- if (xmlIndentTreeOutput)
- xmlOutputBufferWrite(buf, ctxt->indent_size *
- (ctxt->level + 1 > ctxt->indent_nr ?
- ctxt->indent_nr : ctxt->level + 1), ctxt->indent);
- }
- xmlOutputBufferWriteString(buf,
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
- if (ctxt->encoding) {
- xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
- } else {
- xmlOutputBufferWrite(buf, 5, "UTF-8");
- }
- xmlOutputBufferWrite(buf, 4, "\" />");
- }
- if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
- xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
- }
+ while (1) {
+ if (cur == root)
+ return;
+ if (ctxt->format == 1)
+ xmlOutputBufferWrite(buf, 1, "\n");
+ if (cur->next != NULL) {
+ cur = cur->next;
+ break;
+ }
-#if 0
- /*
- * This was removed due to problems with HTML processors.
- * See bug #345147.
- */
- /*
- * 4.8. Script and Style elements
- */
- if ((cur->type == XML_ELEMENT_NODE) &&
- ((xmlStrEqual(cur->name, BAD_CAST "script")) ||
- (xmlStrEqual(cur->name, BAD_CAST "style"))) &&
- ((cur->ns == NULL) ||
- (xmlStrEqual(cur->ns->href, XHTML_NS_NAME)))) {
- xmlNodePtr child = cur->children;
-
- while (child != NULL) {
- if (child->type == XML_TEXT_NODE) {
- if ((xmlStrchr(child->content, '<') == NULL) &&
- (xmlStrchr(child->content, '&') == NULL) &&
- (xmlStrstr(child->content, BAD_CAST "]]>") == NULL)) {
- /* Nothing to escape, so just output as is... */
- /* FIXME: Should we do something about "--" also? */
- int level = ctxt->level;
- int indent = ctxt->format;
-
- ctxt->level = 0;
- ctxt->format = 0;
- xmlOutputBufferWriteString(buf, (const char *) child->content);
- /* (We cannot use xhtmlNodeDumpOutput() here because
- * we wish to leave '>' unescaped!) */
- ctxt->level = level;
- ctxt->format = indent;
- } else {
- /* We must use a CDATA section. Unfortunately,
- * this will break CSS and JavaScript when read by
- * a browser in HTML4-compliant mode. :-( */
- start = end = child->content;
- while (*end != '\0') {
- if (*end == ']' &&
- *(end + 1) == ']' &&
- *(end + 2) == '>') {
- end = end + 2;
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
- xmlOutputBufferWrite(buf, end - start,
- (const char *)start);
- xmlOutputBufferWrite(buf, 3, "]]>");
- start = end;
- }
- end++;
- }
- if (start != end) {
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
- xmlOutputBufferWrite(buf, end - start,
- (const char *)start);
- xmlOutputBufferWrite(buf, 3, "]]>");
- }
- }
- } else {
- int level = ctxt->level;
- int indent = ctxt->format;
+ /*
+ * The parent should never be NULL here but we want to handle
+ * corrupted documents gracefully.
+ */
+ if (cur->parent == NULL)
+ return;
+ cur = cur->parent;
+
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (ctxt->level > 0) ctxt->level--;
+ if ((xmlIndentTreeOutput) && (ctxt->format == 1))
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
+ (ctxt->level > ctxt->indent_nr ?
+ ctxt->indent_nr : ctxt->level),
+ ctxt->indent);
+
+ xmlOutputBufferWrite(buf, 2, "</");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf,
+ (const char *)cur->ns->prefix);
+ xmlOutputBufferWrite(buf, 1, ":");
+ }
- ctxt->level = 0;
- ctxt->format = 0;
- xhtmlNodeDumpOutput(ctxt, child);
- ctxt->level = level;
- ctxt->format = indent;
- }
- child = child->next;
- }
- }
-#endif
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWrite(buf, 1, ">");
- if (cur->children != NULL) {
- int indent = ctxt->format;
-
- if (format == 1) xmlOutputBufferWrite(buf, 1, "\n");
- if (ctxt->level >= 0) ctxt->level++;
- ctxt->format = format;
- xhtmlNodeListDumpOutput(ctxt, cur->children);
- if (ctxt->level > 0) ctxt->level--;
- ctxt->format = indent;
- if ((xmlIndentTreeOutput) && (format == 1))
- xmlOutputBufferWrite(buf, ctxt->indent_size *
- (ctxt->level > ctxt->indent_nr ?
- ctxt->indent_nr : ctxt->level),
- ctxt->indent);
- }
- xmlOutputBufferWrite(buf, 2, "</");
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
- xmlOutputBufferWrite(buf, 1, ":");
+ if (cur == unformattedNode) {
+ ctxt->format = format;
+ unformattedNode = NULL;
+ }
+ }
+ }
}
-
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
- xmlOutputBufferWrite(buf, 1, ">");
}
#endif
@@ -1802,6 +1765,7 @@ xmlSaveToFd(int fd, const char *encoding, int options)
if (ret == NULL) return(NULL);
ret->buf = xmlOutputBufferCreateFd(fd, ret->handler);
if (ret->buf == NULL) {
+ xmlCharEncCloseFunc(ret->handler);
xmlFreeSaveCtxt(ret);
return(NULL);
}
@@ -1831,6 +1795,7 @@ xmlSaveToFilename(const char *filename, const char *encoding, int options)
ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler,
compression);
if (ret->buf == NULL) {
+ xmlCharEncCloseFunc(ret->handler);
xmlFreeSaveCtxt(ret);
return(NULL);
}
@@ -1853,28 +1818,15 @@ xmlSaveCtxtPtr
xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
{
xmlSaveCtxtPtr ret;
- xmlOutputBufferPtr out_buff;
- xmlCharEncodingHandlerPtr handler;
ret = xmlNewSaveCtxt(encoding, options);
if (ret == NULL) return(NULL);
-
- if (encoding != NULL) {
- handler = xmlFindCharEncodingHandler(encoding);
- if (handler == NULL) {
- xmlFree(ret);
- return(NULL);
- }
- } else
- handler = NULL;
- out_buff = xmlOutputBufferCreateBuffer(buffer, handler);
- if (out_buff == NULL) {
- xmlFree(ret);
- if (handler) xmlCharEncCloseFunc(handler);
- return(NULL);
+ ret->buf = xmlOutputBufferCreateBuffer(buffer, ret->handler);
+ if (ret->buf == NULL) {
+ xmlCharEncCloseFunc(ret->handler);
+ xmlFreeSaveCtxt(ret);
+ return(NULL);
}
-
- ret->buf = out_buff;
return(ret);
}
@@ -1902,6 +1854,7 @@ xmlSaveToIO(xmlOutputWriteCallback iowrite,
if (ret == NULL) return(NULL);
ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler);
if (ret->buf == NULL) {
+ xmlCharEncCloseFunc(ret->handler);
xmlFreeSaveCtxt(ret);
return(NULL);
}
@@ -1942,12 +1895,25 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
* Returns the number of byte written or -1 in case of error
*/
long
-xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node)
+xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur)
{
long ret = 0;
- if ((ctxt == NULL) || (node == NULL)) return(-1);
- xmlNodeDumpOutputInternal(ctxt, node);
+ if ((ctxt == NULL) || (cur == NULL)) return(-1);
+#ifdef LIBXML_HTML_ENABLED
+ if (ctxt->options & XML_SAVE_XHTML) {
+ xhtmlNodeDumpOutput(ctxt, cur);
+ return(ret);
+ }
+ if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
+ (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
+ ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
+ (ctxt->options & XML_SAVE_AS_HTML)) {
+ htmlNodeDumpOutputInternal(ctxt, cur);
+ return(ret);
+ }
+#endif
+ xmlNodeDumpOutputInternal(ctxt, cur);
return(ret);
}
@@ -2197,7 +2163,7 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
int format)
{
xmlBufPtr buffer;
- int ret;
+ size_t ret;
if ((buf == NULL) || (cur == NULL))
return(-1);
diff --git a/contrib/libs/libxml/xmlschemas.c b/contrib/libs/libxml/xmlschemas.c
index b83982eb5a..bae7669723 100644
--- a/contrib/libs/libxml/xmlschemas.c
+++ b/contrib/libs/libxml/xmlschemas.c
@@ -860,6 +860,7 @@ struct _xmlSchemaIDCMatcher {
int sizeKeySeqs;
xmlSchemaItemListPtr targets; /* list of target-node
(xmlSchemaPSVIIDCNodePtr) entries */
+ xmlHashTablePtr htab;
};
/*
@@ -1002,11 +1003,11 @@ struct _xmlSchemaValidCtxt {
int xsiAssemble;
int depth;
- xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
+ xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
int sizeElemInfos;
xmlSchemaNodeInfoPtr inode; /* the current element information */
- xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
+ xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
@@ -1055,6 +1056,18 @@ struct _xmlSchemaSubstGroup {
xmlSchemaItemListPtr members;
};
+/**
+ * xmlIDCHashEntry:
+ *
+ * an entry in hash tables to quickly look up keys/uniques
+ */
+typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
+typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
+struct _xmlIDCHashEntry {
+ xmlIDCHashEntryPtr next; /* next item with same hash */
+ int index; /* index into associated item list */
+};
+
/************************************************************************
* *
* Some predeclarations *
@@ -1329,6 +1342,9 @@ xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
{
+ if (item == NULL) {
+ return (NULL);
+ }
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return (((xmlSchemaElementPtr) item)->name);
@@ -1384,6 +1400,9 @@ xmlSchemaGetQNameRefTargetNs(void *ref)
static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
{
+ if (item == NULL) {
+ return (NULL);
+ }
switch (item->type) {
case XML_SCHEMA_TYPE_ELEMENT:
return (((xmlSchemaElementPtr) item)->targetNamespace);
@@ -1478,6 +1497,7 @@ xmlSchemaWildcardPCToString(int pc)
* @val: the precomputed value
* @retValue: the returned value
* @ws: the whitespace type of the value
+ * @for_hash: non-zero if this is supposed to generate a string for hashing
*
* Get a the canonical representation of the value.
* The caller has to free the returned retValue.
@@ -1486,9 +1506,10 @@ xmlSchemaWildcardPCToString(int pc)
* API errors or if the value type is not supported yet.
*/
static int
-xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
- xmlSchemaWhitespaceValueType ws,
- xmlChar **retValue)
+xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
+ xmlSchemaWhitespaceValueType ws,
+ xmlChar **retValue,
+ int for_hash)
{
int list;
xmlSchemaValType valType;
@@ -1522,6 +1543,20 @@ xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
xmlFree((xmlChar *) value2);
goto internal_error;
}
+ if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
+ /* We can mostly use the canonical value for hashing,
+ except in the case of decimal. There the canonical
+ representation requires a trailing '.0' even for
+ non-fractional numbers, but for the derived integer
+ types it forbids any decimal point. Nevertheless they
+ compare equal if the value is equal. We need to generate
+ the same hash value for this to work, and it's easiest
+ to just cut off the useless '.0' suffix for the
+ decimal type. */
+ int len = xmlStrlen(value2);
+ if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
+ ((xmlChar*)value2)[len-2] = 0;
+ }
value = value2;
}
if (*retValue == NULL)
@@ -1548,6 +1583,22 @@ internal_error:
return (-1);
}
+static int
+xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
+ xmlSchemaWhitespaceValueType ws,
+ xmlChar **retValue)
+{
+ return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
+}
+
+static int
+xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
+ xmlChar **retValue)
+{
+ return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
+ retValue, 1);
+}
+
/**
* xmlSchemaFormatItemForReport:
* @buf: the string buffer
@@ -1873,7 +1924,7 @@ xmlSchemaPSimpleErr(const char *msg)
/**
* xmlSchemaPErrMemory:
* @node: a context node
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -1995,7 +2046,7 @@ xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
/**
* xmlSchemaVTypeErrMemory:
* @node: a context node
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -5848,7 +5899,7 @@ xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
if (!strchr((char *) value, ':')) {
ns = xmlSearchNs(attr->doc, attr->parent, NULL);
- if (ns)
+ if (ns && ns->href && ns->href[0])
*uri = xmlDictLookup(ctxt->dict, ns->href, -1);
else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
/* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
@@ -6031,7 +6082,7 @@ xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
/**
* xmlGetMaxOccurs:
* @ctxt: a schema validation context
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Get the maxOccurs property
*
@@ -6074,7 +6125,16 @@ xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
return (def);
}
while ((*cur >= '0') && (*cur <= '9')) {
- ret = ret * 10 + (*cur - '0');
+ if (ret > INT_MAX / 10) {
+ ret = INT_MAX;
+ } else {
+ int digit = *cur - '0';
+ ret *= 10;
+ if (ret > INT_MAX - digit)
+ ret = INT_MAX;
+ else
+ ret += digit;
+ }
cur++;
}
while (IS_BLANK_CH(*cur))
@@ -6096,7 +6156,7 @@ xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
/**
* xmlGetMinOccurs:
* @ctxt: a schema validation context
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Get the minOccurs property
*
@@ -6126,7 +6186,16 @@ xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
return (def);
}
while ((*cur >= '0') && (*cur <= '9')) {
- ret = ret * 10 + (*cur - '0');
+ if (ret > INT_MAX / 10) {
+ ret = INT_MAX;
+ } else {
+ int digit = *cur - '0';
+ ret *= 10;
+ if (ret > INT_MAX - digit)
+ ret = INT_MAX;
+ else
+ ret += digit;
+ }
cur++;
}
while (IS_BLANK_CH(*cur))
@@ -6193,7 +6262,7 @@ xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
/**
* xmlGetBooleanProp:
* @ctxt: a schema validation context
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
* @name: the attribute name
* @def: the default value
*
@@ -6481,7 +6550,7 @@ xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
* xmlSchemaParseLocalAttributes:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
* @type: the hosting type where the attributes will be anchored
*
* Parses attribute uses and attribute declarations and
@@ -6523,7 +6592,7 @@ xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseAnnotation:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Attribute declaration
* *WARNING* this interface is highly subject to change
@@ -6643,7 +6712,7 @@ xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int neede
* xmlSchemaParseFacet:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Facet declaration
* *WARNING* this interface is highly subject to change
@@ -6734,7 +6803,7 @@ xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseWildcardNs:
* @ctxt: a schema parser context
* @wildc: the wildcard, already created
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parses the attribute "processContents" and "namespace"
* of a xsd:anyAttribute and xsd:any.
@@ -6901,7 +6970,7 @@ xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
* xmlSchemaParseAny:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parsea a XML schema <any> element. A particle and wildcard
* will be created (except if minOccurs==maxOccurs==0, in this case
@@ -6996,7 +7065,7 @@ xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseNotation:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Notation declaration
*
@@ -7043,7 +7112,7 @@ xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseAnyAttribute:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema AnyAttribute declaration
* *WARNING* this interface is highly subject to change
@@ -7113,7 +7182,7 @@ xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
* xmlSchemaParseAttribute:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Attribute declaration
* *WARNING* this interface is highly subject to change
@@ -7656,7 +7725,7 @@ xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
* xmlSchemaParseAttributeGroupRef:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parse an attribute group definition reference.
* Note that a reference to an attribute group does not
@@ -7789,7 +7858,7 @@ xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
* xmlSchemaParseAttributeGroupDefinition:
* @pctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Attribute Group declaration
* *WARNING* this interface is highly subject to change
@@ -8220,7 +8289,7 @@ xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
* xmlSchemaParseIDCSelectorAndField:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parses a XML Schema identity-constraint definition's
* <selector> and <field> elements.
@@ -8318,7 +8387,7 @@ xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
* xmlSchemaParseIDC:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parses a XML Schema identity-constraint definition.
*
@@ -8465,7 +8534,7 @@ xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
* xmlSchemaParseElement:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
* @topLevel: indicates if this is global declaration
*
* Parses a XML schema element declaration.
@@ -8864,7 +8933,7 @@ return_null:
* xmlSchemaParseUnion:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Union definition
* *WARNING* this interface is highly subject to change
@@ -9033,7 +9102,7 @@ xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseList:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema List definition
* *WARNING* this interface is highly subject to change
@@ -9144,7 +9213,7 @@ xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseSimpleType:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Simple Type definition
* *WARNING* this interface is highly subject to change
@@ -9455,7 +9524,7 @@ xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
* xmlSchemaParseModelGroupDefinition:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parses a XML schema model group definition.
*
@@ -10293,7 +10362,7 @@ xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
* xmlSchemaAddSchemaDoc:
* @pctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parse an included (and to-be-redefined) XML schema document.
*
@@ -10717,7 +10786,7 @@ exit_failure:
* xmlSchemaParseImport:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Import definition
* *WARNING* this interface is highly subject to change
@@ -11209,7 +11278,7 @@ xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
* xmlSchemaParseModelGroup:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
* @type: the "compositor" type
* @particleNeeded: if a a model group with a particle
*
@@ -11489,7 +11558,7 @@ xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseRestriction:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Restriction definition
* *WARNING* this interface is highly subject to change
@@ -11792,7 +11861,7 @@ xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseExtension:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* Parses an <extension>, which is found inside a
* <simpleContent> or <complexContent>.
@@ -11928,7 +11997,7 @@ xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* xmlSchemaParseSimpleContent:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema SimpleContent definition
* *WARNING* this interface is highly subject to change
@@ -12018,7 +12087,7 @@ xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
* xmlSchemaParseComplexContent:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema ComplexContent definition
* *WARNING* this interface is highly subject to change
@@ -12113,7 +12182,7 @@ xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
* xmlSchemaParseComplexType:
* @ctxt: a schema validation context
* @schema: the schema being built
- * @node: a subtree containing XML Schema informations
+ * @node: a subtree containing XML Schema information
*
* parse a XML schema Complex Type definition
* *WARNING* this interface is highly subject to change
@@ -14658,6 +14727,7 @@ xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
return (NULL);
}
+#if 0
/**
* xmlSchemaGetParticleTotalRangeMin:
* @particle: the particle
@@ -14713,7 +14783,6 @@ xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
}
}
-#if 0
/**
* xmlSchemaGetParticleTotalRangeMax:
* @particle: the particle
@@ -14776,6 +14845,48 @@ xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
#endif
/**
+ * xmlSchemaGetParticleEmptiable:
+ * @particle: the particle
+ *
+ * Returns 1 if emptiable, 0 otherwise.
+ */
+static int
+xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
+{
+ xmlSchemaParticlePtr part;
+ int emptiable;
+
+ if ((particle->children == NULL) || (particle->minOccurs == 0))
+ return (1);
+
+ part = (xmlSchemaParticlePtr) particle->children->children;
+ if (part == NULL)
+ return (1);
+
+ while (part != NULL) {
+ if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
+ (part->children->type == XML_SCHEMA_TYPE_ANY))
+ emptiable = (part->minOccurs == 0);
+ else
+ emptiable = xmlSchemaGetParticleEmptiable(part);
+ if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
+ if (emptiable)
+ return (1);
+ } else {
+ /* <all> and <sequence> */
+ if (!emptiable)
+ return (0);
+ }
+ part = (xmlSchemaParticlePtr) part->next;
+ }
+
+ if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
+ return (0);
+ else
+ return (1);
+}
+
+/**
* xmlSchemaIsParticleEmptiable:
* @particle: the particle
*
@@ -14797,10 +14908,8 @@ xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
* SPEC (2) "Its {term} is a group and the minimum part of the
* effective total range of that group, [...] is 0."
*/
- if (WXS_IS_MODEL_GROUP(particle->children)) {
- if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
- return (1);
- }
+ if (WXS_IS_MODEL_GROUP(particle->children))
+ return (xmlSchemaGetParticleEmptiable(particle));
return (0);
}
@@ -14938,7 +15047,7 @@ xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
}
if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
/*
- * Avoid inifinite recursion on circular types not yet checked.
+ * Avoid infinite recursion on circular types not yet checked.
*/
return (0);
}
@@ -20961,7 +21070,7 @@ xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
break;
case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
/*
- * Handle attribue prohibition which had a
+ * Handle attribute prohibition which had a
* "ref" attribute.
*/
xmlSchemaResolveAttrUseProhibReferences(
@@ -22293,6 +22402,17 @@ xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
}
}
+static void
+xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
+{
+ xmlIDCHashEntryPtr e = payload, n;
+ while (e) {
+ n = e->next;
+ xmlFree(e);
+ e = n;
+ }
+}
+
/**
* xmlSchemaIDCFreeMatcherList:
* @matcher: the first IDC matcher in the list
@@ -22331,6 +22451,8 @@ xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
}
xmlSchemaItemListFree(matcher->targets);
}
+ if (matcher->htab != NULL)
+ xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
xmlFree(matcher);
matcher = next;
}
@@ -22381,6 +22503,10 @@ xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
xmlSchemaItemListFree(matcher->targets);
matcher->targets = NULL;
}
+ if (matcher->htab != NULL) {
+ xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
+ matcher->htab = NULL;
+ }
matcher->next = NULL;
/*
* Cache the matcher.
@@ -22615,10 +22741,10 @@ next_sto:
}
static const xmlChar *
-xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
- xmlChar **buf,
- xmlSchemaPSVIIDCKeyPtr *seq,
- int count)
+xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
+ xmlChar **buf,
+ xmlSchemaPSVIIDCKeyPtr *seq,
+ int count, int for_hash)
{
int i, res;
xmlChar *value = NULL;
@@ -22626,9 +22752,13 @@ xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
*buf = xmlStrdup(BAD_CAST "[");
for (i = 0; i < count; i++) {
*buf = xmlStrcat(*buf, BAD_CAST "'");
- res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
- xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
- &value);
+ if (!for_hash)
+ res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
+ xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
+ &value);
+ else {
+ res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
+ }
if (res == 0)
*buf = xmlStrcat(*buf, BAD_CAST value);
else {
@@ -22650,6 +22780,24 @@ xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
return (BAD_CAST *buf);
}
+static const xmlChar *
+xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
+ xmlChar **buf,
+ xmlSchemaPSVIIDCKeyPtr *seq,
+ int count)
+{
+ return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
+}
+
+static const xmlChar *
+xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
+ xmlChar **buf,
+ xmlSchemaPSVIIDCKeyPtr *seq,
+ int count)
+{
+ return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
+}
+
/**
* xmlSchemaXPathPop:
* @vctxt: the WXS validation context
@@ -23011,15 +23159,25 @@ create_key:
if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
(targets->nbItems != 0)) {
xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
+ xmlIDCHashEntryPtr e;
- i = 0;
res = 0;
+
+ if (!matcher->htab)
+ e = NULL;
+ else {
+ xmlChar *value = NULL;
+ xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
+ e = xmlHashLookup(matcher->htab, value);
+ FREE_AND_NULL(value);
+ }
+
/*
* Compare the key-sequences, key by key.
*/
- do {
+ for (;e; e = e->next) {
bkeySeq =
- ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
+ ((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
for (j = 0; j < nbKeys; j++) {
ckey = (*keySeq)[j];
bkey = bkeySeq[j];
@@ -23040,9 +23198,8 @@ create_key:
*/
break;
}
- i++;
- } while (i < targets->nbItems);
- if (i != targets->nbItems) {
+ }
+ if (e) {
xmlChar *str = NULL, *strB = NULL;
/*
* TODO: Try to report the key-sequence.
@@ -23120,6 +23277,24 @@ create_key:
}
return (-1);
}
+ if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
+ xmlChar *value = NULL;
+ xmlIDCHashEntryPtr r, e;
+ if (!matcher->htab)
+ matcher->htab = xmlHashCreate(4);
+ xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
+ e = xmlMalloc(sizeof *e);
+ e->index = targets->nbItems - 1;
+ r = xmlHashLookup(matcher->htab, value);
+ if (r) {
+ e->next = r->next;
+ r->next = e;
+ } else {
+ e->next = NULL;
+ xmlHashAddEntry(matcher->htab, value, e);
+ }
+ FREE_AND_NULL(value);
+ }
goto selector_leave;
selector_key_error:
@@ -23376,6 +23551,10 @@ xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
matcher->targets->items = NULL;
matcher->targets->sizeItems = 0;
matcher->targets->nbItems = 0;
+ if (matcher->htab) {
+ xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
+ matcher->htab = NULL;
+ }
} else {
/*
* Compare the key-sequences and add to the IDC node-table.
@@ -23823,6 +24002,7 @@ xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
int i, j, k, res, nbFields, hasDupls;
xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
xmlSchemaPSVIIDCNodePtr refNode = NULL;
+ xmlHashTablePtr table = NULL;
nbFields = matcher->aidc->def->nbFields;
@@ -23840,26 +24020,52 @@ xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
/*
* Search for a matching key-sequences.
*/
+ if (bind) {
+ table = xmlHashCreate(bind->nbNodes * 2);
+ for (j = 0; j < bind->nbNodes; j++) {
+ xmlChar *value;
+ xmlIDCHashEntryPtr r, e;
+ keys = bind->nodeTable[j]->keys;
+ xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
+ e = xmlMalloc(sizeof *e);
+ e->index = j;
+ r = xmlHashLookup(table, value);
+ if (r) {
+ e->next = r->next;
+ r->next = e;
+ } else {
+ e->next = NULL;
+ xmlHashAddEntry(table, value, e);
+ }
+ FREE_AND_NULL(value);
+ }
+ }
for (i = 0; i < matcher->targets->nbItems; i++) {
res = 0;
refNode = matcher->targets->items[i];
if (bind != NULL) {
+ xmlChar *value;
+ xmlIDCHashEntryPtr e;
refKeys = refNode->keys;
- for (j = 0; j < bind->nbNodes; j++) {
- keys = bind->nodeTable[j]->keys;
+ xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
+ e = xmlHashLookup(table, value);
+ FREE_AND_NULL(value);
+ res = 0;
+ for (;e; e = e->next) {
+ keys = bind->nodeTable[e->index]->keys;
for (k = 0; k < nbFields; k++) {
res = xmlSchemaAreValuesEqual(keys[k]->val,
- refKeys[k]->val);
+ refKeys[k]->val);
if (res == 0)
- break;
+ break;
else if (res == -1) {
return (-1);
}
}
if (res == 1) {
/*
- * Match found.
- */
+ * Match found.
+ */
break;
}
}
@@ -23914,6 +24120,9 @@ xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
FREE_AND_NULL(strB);
}
}
+ if (table) {
+ xmlHashFree(table, xmlFreeIDCHashEntry);
+ }
}
matcher = matcher->next;
}
@@ -24184,7 +24393,7 @@ xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
unsigned long length,
int fireErrors)
{
- int ret, error = 0;
+ int ret, error = 0, found;
xmlSchemaTypePtr tmpType;
xmlSchemaFacetLinkPtr facetLink;
@@ -24308,103 +24517,98 @@ WXS_IS_LIST:
}
pattern_and_enum:
- if (error >= 0) {
- int found = 0;
- /*
- * Process enumerations. Facet values are in the value space
- * of the defining type's base type. This seems to be a bug in the
- * XML Schema 1.0 spec. Use the whitespace type of the base type.
- * Only the first set of enumerations in the ancestor-or-self axis
- * is used for validation.
- */
- ret = 0;
- tmpType = type;
- do {
- for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
- if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
- continue;
- found = 1;
- ret = xmlSchemaAreValuesEqual(facet->val, val);
- if (ret == 1)
- break;
- else if (ret < 0) {
- AERROR_INT("xmlSchemaValidateFacets",
- "validating against an enumeration facet");
- return (-1);
- }
- }
- if (ret != 0)
- break;
- /*
- * Break on the first set of enumerations. Any additional
- * enumerations which might be existent on the ancestors
- * of the current type are restricted by this set; thus
- * *must* *not* be taken into account.
- */
- if (found)
- break;
- tmpType = tmpType->baseType;
- } while ((tmpType != NULL) &&
- (tmpType->type != XML_SCHEMA_TYPE_BASIC));
- if (found && (ret == 0)) {
- ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
- if (fireErrors) {
- xmlSchemaFacetErr(actxt, ret, node,
- value, 0, type, NULL, NULL, NULL, NULL);
- } else
- return (ret);
- if (error == 0)
- error = ret;
- }
- }
-
- if (error >= 0) {
- int found;
- /*
- * Process patters. Pattern facets are ORed at type level
- * and ANDed if derived. Walk the base type axis.
- */
- tmpType = type;
- facet = NULL;
- do {
- found = 0;
- for (facetLink = tmpType->facetSet; facetLink != NULL;
- facetLink = facetLink->next) {
- if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
- continue;
- found = 1;
- /*
- * NOTE that for patterns, @value needs to be the
- * normalized value.
- */
- ret = xmlRegexpExec(facetLink->facet->regexp, value);
- if (ret == 1)
- break;
- else if (ret < 0) {
- AERROR_INT("xmlSchemaValidateFacets",
- "validating against a pattern facet");
- return (-1);
- } else {
- /*
- * Save the last non-validating facet.
- */
- facet = facetLink->facet;
- }
- }
- if (found && (ret != 1)) {
- ret = XML_SCHEMAV_CVC_PATTERN_VALID;
- if (fireErrors) {
- xmlSchemaFacetErr(actxt, ret, node,
- value, 0, type, facet, NULL, NULL, NULL);
- } else
- return (ret);
- if (error == 0)
- error = ret;
- break;
- }
- tmpType = tmpType->baseType;
- } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
- }
+ found = 0;
+ /*
+ * Process enumerations. Facet values are in the value space
+ * of the defining type's base type. This seems to be a bug in the
+ * XML Schema 1.0 spec. Use the whitespace type of the base type.
+ * Only the first set of enumerations in the ancestor-or-self axis
+ * is used for validation.
+ */
+ ret = 0;
+ tmpType = type;
+ do {
+ for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
+ if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
+ continue;
+ found = 1;
+ ret = xmlSchemaAreValuesEqual(facet->val, val);
+ if (ret == 1)
+ break;
+ else if (ret < 0) {
+ AERROR_INT("xmlSchemaValidateFacets",
+ "validating against an enumeration facet");
+ return (-1);
+ }
+ }
+ if (ret != 0)
+ break;
+ /*
+ * Break on the first set of enumerations. Any additional
+ * enumerations which might be existent on the ancestors
+ * of the current type are restricted by this set; thus
+ * *must* *not* be taken into account.
+ */
+ if (found)
+ break;
+ tmpType = tmpType->baseType;
+ } while ((tmpType != NULL) &&
+ (tmpType->type != XML_SCHEMA_TYPE_BASIC));
+ if (found && (ret == 0)) {
+ ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
+ if (fireErrors) {
+ xmlSchemaFacetErr(actxt, ret, node,
+ value, 0, type, NULL, NULL, NULL, NULL);
+ } else
+ return (ret);
+ if (error == 0)
+ error = ret;
+ }
+
+ /*
+ * Process patters. Pattern facets are ORed at type level
+ * and ANDed if derived. Walk the base type axis.
+ */
+ tmpType = type;
+ facet = NULL;
+ do {
+ found = 0;
+ for (facetLink = tmpType->facetSet; facetLink != NULL;
+ facetLink = facetLink->next) {
+ if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
+ continue;
+ found = 1;
+ /*
+ * NOTE that for patterns, @value needs to be the
+ * normalized value.
+ */
+ ret = xmlRegexpExec(facetLink->facet->regexp, value);
+ if (ret == 1)
+ break;
+ else if (ret < 0) {
+ AERROR_INT("xmlSchemaValidateFacets",
+ "validating against a pattern facet");
+ return (-1);
+ } else {
+ /*
+ * Save the last non-validating facet.
+ */
+ facet = facetLink->facet;
+ }
+ }
+ if (found && (ret != 1)) {
+ ret = XML_SCHEMAV_CVC_PATTERN_VALID;
+ if (fireErrors) {
+ xmlSchemaFacetErr(actxt, ret, node,
+ value, 0, type, facet, NULL, NULL, NULL);
+ } else
+ return (ret);
+ if (error == 0)
+ error = ret;
+ break;
+ }
+ tmpType = tmpType->baseType;
+ } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
return (error);
}
@@ -27802,7 +28006,7 @@ xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
* @warn: the warning function
* @ctx: the functions context
*
- * Set the error and warning callback informations
+ * Set the error and warning callback information
*/
void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
@@ -27847,7 +28051,7 @@ xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
* @warn: the warning function result
* @ctx: the functions context result
*
- * Get the error and warning callback informations
+ * Get the error and warning callback information
*
* Returns -1 in case of error and 0 otherwise
*/
@@ -28272,13 +28476,13 @@ struct _xmlSchemaSplitSAXData {
struct _xmlSchemaSAXPlug {
unsigned int magic;
- /* the original callbacks informations */
+ /* the original callbacks information */
xmlSAXHandlerPtr *user_sax_ptr;
xmlSAXHandlerPtr user_sax;
void **user_data_ptr;
void *user_data;
- /* the block plugged back and validation informations */
+ /* the block plugged back and validation information */
xmlSAXHandler schemas_sax;
xmlSchemaValidCtxtPtr ctxt;
};
diff --git a/contrib/libs/libxml/xmlschemastypes.c b/contrib/libs/libxml/xmlschemastypes.c
index e7764d9058..af31be5f78 100644
--- a/contrib/libs/libxml/xmlschemastypes.c
+++ b/contrib/libs/libxml/xmlschemastypes.c
@@ -199,7 +199,7 @@ static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
************************************************************************/
/**
* xmlSchemaTypeErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle an out of memory condition
*/
@@ -1160,9 +1160,12 @@ static const unsigned int daysInMonthLeap[12] =
#define VALID_DATETIME(dt) \
(VALID_DATE(dt) && VALID_TIME(dt))
-#define SECS_PER_MIN (60)
-#define SECS_PER_HOUR (60 * SECS_PER_MIN)
-#define SECS_PER_DAY (24 * SECS_PER_HOUR)
+#define SECS_PER_MIN 60
+#define MINS_PER_HOUR 60
+#define HOURS_PER_DAY 24
+#define SECS_PER_HOUR (MINS_PER_HOUR * SECS_PER_MIN)
+#define SECS_PER_DAY (HOURS_PER_DAY * SECS_PER_HOUR)
+#define MINS_PER_DAY (HOURS_PER_DAY * MINS_PER_HOUR)
static const long dayInYearByMonth[12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
@@ -1222,7 +1225,14 @@ _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
firstChar = cur;
while ((*cur >= '0') && (*cur <= '9')) {
- dt->year = dt->year * 10 + (*cur - '0');
+ int digit = *cur - '0';
+
+ if (dt->year > LONG_MAX / 10)
+ return 2;
+ dt->year *= 10;
+ if (dt->year > LONG_MAX - digit)
+ return 2;
+ dt->year += digit;
cur++;
digcnt++;
}
@@ -1791,10 +1801,8 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
xmlSchemaValPtr dur;
int isneg = 0;
unsigned int seq = 0;
- double num;
- int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */
- const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
- const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
+ long days, secs = 0;
+ double sec_frac = 0.0;
if (duration == NULL)
return -1;
@@ -1819,6 +1827,10 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
return -1;
while (*cur != 0) {
+ long num = 0;
+ size_t has_digits = 0;
+ int has_frac = 0;
+ const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
/* input string should be empty or invalid date/time item */
if (seq >= sizeof(desig))
@@ -1826,53 +1838,104 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
/* T designator must be present for time items */
if (*cur == 'T') {
- if (seq <= 3) {
- seq = 3;
- cur++;
- } else
- return 1;
+ if (seq > 3)
+ goto error;
+ cur++;
+ seq = 3;
} else if (seq == 3)
goto error;
- /* parse the number portion of the item */
- PARSE_NUM(num, cur, num_type);
-
- if ((num_type == -1) || (*cur == 0))
- goto error;
-
- /* update duration based on item type */
- while (seq < sizeof(desig)) {
- if (*cur == desig[seq]) {
+ /* Parse integral part. */
+ while (*cur >= '0' && *cur <= '9') {
+ long digit = *cur - '0';
- /* verify numeric type; only seconds can be float */
- if ((num_type != 0) && (seq < (sizeof(desig)-1)))
- goto error;
+ if (num > LONG_MAX / 10)
+ goto error;
+ num *= 10;
+ if (num > LONG_MAX - digit)
+ goto error;
+ num += digit;
- switch (seq) {
- case 0:
- dur->value.dur.mon = (long)num * 12;
- break;
- case 1:
- dur->value.dur.mon += (long)num;
- break;
- default:
- /* convert to seconds using multiplier */
- dur->value.dur.sec += num * multi[seq];
- seq++;
- break;
- }
+ has_digits = 1;
+ cur++;
+ }
- break; /* exit loop */
+ if (*cur == '.') {
+ /* Parse fractional part. */
+ double mult = 1.0;
+ cur++;
+ has_frac = 1;
+ while (*cur >= '0' && *cur <= '9') {
+ mult /= 10.0;
+ sec_frac += (*cur - '0') * mult;
+ has_digits = 1;
+ cur++;
}
- /* no date designators found? */
- if ((++seq == 3) || (seq == 6))
+ }
+
+ while (*cur != desig[seq]) {
+ seq++;
+ /* No T designator or invalid char. */
+ if (seq == 3 || seq == sizeof(desig))
goto error;
}
cur++;
- if (collapse)
- while IS_WSP_BLANK_CH(*cur) cur++;
+
+ if (!has_digits || (has_frac && (seq != 5)))
+ goto error;
+
+ switch (seq) {
+ case 0:
+ /* Year */
+ if (num > LONG_MAX / 12)
+ goto error;
+ dur->value.dur.mon = num * 12;
+ break;
+ case 1:
+ /* Month */
+ if (dur->value.dur.mon > LONG_MAX - num)
+ goto error;
+ dur->value.dur.mon += num;
+ break;
+ case 2:
+ /* Day */
+ dur->value.dur.day = num;
+ break;
+ case 3:
+ /* Hour */
+ days = num / HOURS_PER_DAY;
+ if (dur->value.dur.day > LONG_MAX - days)
+ goto error;
+ dur->value.dur.day += days;
+ secs = (num % HOURS_PER_DAY) * SECS_PER_HOUR;
+ break;
+ case 4:
+ /* Minute */
+ days = num / MINS_PER_DAY;
+ if (dur->value.dur.day > LONG_MAX - days)
+ goto error;
+ dur->value.dur.day += days;
+ secs += (num % MINS_PER_DAY) * SECS_PER_MIN;
+ break;
+ case 5:
+ /* Second */
+ days = num / SECS_PER_DAY;
+ if (dur->value.dur.day > LONG_MAX - days)
+ goto error;
+ dur->value.dur.day += days;
+ secs += num % SECS_PER_DAY;
+ break;
+ }
+
+ seq++;
}
+ days = secs / SECS_PER_DAY;
+ if (dur->value.dur.day > LONG_MAX - days)
+ goto error;
+ dur->value.dur.day += days;
+ dur->value.dur.sec = (secs % SECS_PER_DAY) + sec_frac;
+
if (isneg) {
dur->value.dur.mon = -dur->value.dur.mon;
dur->value.dur.day = -dur->value.dur.day;
@@ -2124,6 +2187,44 @@ xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
return(ret);
}
+/*
+ * xmlSchemaCheckLanguageType
+ * @value: the value to check
+ *
+ * Check that a value conforms to the lexical space of the language datatype.
+ * Must conform to [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
+ *
+ * Returns 1 if this validates, 0 otherwise.
+ */
+static int
+xmlSchemaCheckLanguageType(const xmlChar* value) {
+ int first = 1, len = 0;
+ const xmlChar* cur = value;
+
+ if (value == NULL)
+ return (0);
+
+ while (cur[0] != 0) {
+ if (!( ((cur[0] >= 'a') && (cur[0] <= 'z')) || ((cur[0] >= 'A') && (cur[0] <= 'Z'))
+ || (cur[0] == '-')
+ || ((first == 0) && (xmlIsDigit_ch(cur[0]))) ))
+ return (0);
+ if (cur[0] == '-') {
+ if ((len < 1) || (len > 8))
+ return (0);
+ len = 0;
+ first = 0;
+ }
+ else
+ len++;
+ cur++;
+ }
+ if ((len < 1) || (len > 8))
+ return (0);
+
+ return (1);
+}
+
/**
* xmlSchemaValAtomicType:
* @type: the predefined type
@@ -2636,12 +2737,13 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
goto return0;
}
case XML_SCHEMAS_LANGUAGE:
- if (normOnTheFly) {
+ if ((norm == NULL) && (normOnTheFly)) {
norm = xmlSchemaCollapseString(value);
if (norm != NULL)
value = norm;
}
- if (xmlCheckLanguageID(value) == 1) {
+
+ if (xmlSchemaCheckLanguageType(value) == 1) {
if (val != NULL) {
v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
if (v != NULL) {
@@ -3628,6 +3730,8 @@ xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
minday = 0;
maxday = 0;
} else {
+ if (myear > LONG_MAX / 366)
+ return -2;
/* FIXME: This doesn't take leap year exceptions every 100/400 years
into account. */
maxday = 365 * myear + (myear + 3) / 4;
@@ -4016,6 +4120,14 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
if ((x == NULL) || (y == NULL))
return -2;
+ if ((x->value.date.year > LONG_MAX / 366) ||
+ (x->value.date.year < LONG_MIN / 366) ||
+ (y->value.date.year > LONG_MAX / 366) ||
+ (y->value.date.year < LONG_MIN / 366)) {
+ /* Possible overflow when converting to days. */
+ return -2;
+ }
+
if (x->value.date.tz_flag) {
if (!y->value.date.tz_flag) {
@@ -5069,7 +5181,7 @@ xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
/*
* TODO: Check if this is a decimal.
*/
- if (facet == NULL)
+ if (facet == NULL || facet->val == NULL)
return 0;
return ((unsigned long) facet->val->value.decimal.lo);
}
@@ -5319,7 +5431,6 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
xmlSchemaWhitespaceValueType ws)
{
int ret;
- int stringType;
if (facet == NULL)
return(-1);
@@ -5337,10 +5448,16 @@ xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
* the datatype.
* See https://www.w3.org/TR/xmlschema-2/#rf-pattern
*/
- stringType = val && ((val->type >= XML_SCHEMAS_STRING && val->type <= XML_SCHEMAS_NORMSTRING)
- || (val->type >= XML_SCHEMAS_TOKEN && val->type <= XML_SCHEMAS_NCNAME));
- ret = xmlRegexpExec(facet->regexp,
- (stringType && val->value.str) ? val->value.str : value);
+ if (val &&
+ val->value.str &&
+ ((val->type >= XML_SCHEMAS_STRING &&
+ val->type <= XML_SCHEMAS_NORMSTRING) ||
+ (val->type >= XML_SCHEMAS_TOKEN &&
+ val->type <= XML_SCHEMAS_ENTITIES &&
+ val->type != XML_SCHEMAS_QNAME))) {
+ value = val->value.str;
+ }
+ ret = xmlRegexpExec(facet->regexp, value);
if (ret == 1)
return(0);
if (ret == 0)
@@ -6003,13 +6120,13 @@ xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
* recoverable timezone and not "Z".
*/
snprintf(buf, 30,
- "%04ld:%02u:%02uZ",
+ "%04ld-%02u-%02uZ",
norm->value.date.year, norm->value.date.mon,
norm->value.date.day);
xmlSchemaFreeValue(norm);
} else {
snprintf(buf, 30,
- "%04ld:%02u:%02u",
+ "%04ld-%02u-%02u",
val->value.date.year, val->value.date.mon,
val->value.date.day);
}
@@ -6030,14 +6147,14 @@ xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
* TODO: Check if "%.14g" is portable.
*/
snprintf(buf, 50,
- "%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
+ "%04ld-%02u-%02uT%02u:%02u:%02.14gZ",
norm->value.date.year, norm->value.date.mon,
norm->value.date.day, norm->value.date.hour,
norm->value.date.min, norm->value.date.sec);
xmlSchemaFreeValue(norm);
} else {
snprintf(buf, 50,
- "%04ld:%02u:%02uT%02u:%02u:%02.14g",
+ "%04ld-%02u-%02uT%02u:%02u:%02.14g",
val->value.date.year, val->value.date.mon,
val->value.date.day, val->value.date.hour,
val->value.date.min, val->value.date.sec);
diff --git a/contrib/libs/libxml/xmlstring.c b/contrib/libs/libxml/xmlstring.c
index 8d2e06f66c..5a6875f562 100644
--- a/contrib/libs/libxml/xmlstring.c
+++ b/contrib/libs/libxml/xmlstring.c
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <libxml/xmlmemory.h>
#include <libxml/parserInternals.h>
#include <libxml/xmlstring.h>
@@ -42,7 +43,7 @@ xmlStrndup(const xmlChar *cur, int len) {
xmlChar *ret;
if ((cur == NULL) || (len < 0)) return(NULL);
- ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
+ ret = (xmlChar *) xmlMallocAtomic(((size_t) len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlErrMemory(NULL, NULL);
return(NULL);
@@ -87,7 +88,7 @@ xmlCharStrndup(const char *cur, int len) {
xmlChar *ret;
if ((cur == NULL) || (len < 0)) return(NULL);
- ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
+ ret = (xmlChar *) xmlMallocAtomic(((size_t) len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlErrMemory(NULL, NULL);
return(NULL);
@@ -130,16 +131,18 @@ xmlCharStrdup(const char *cur) {
int
xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
- register int tmp;
-
if (str1 == str2) return(0);
if (str1 == NULL) return(-1);
if (str2 == NULL) return(1);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ return(strcmp((const char *)str1, (const char *)str2));
+#else
do {
- tmp = *str1++ - *str2;
+ int tmp = *str1++ - *str2;
if (tmp != 0) return(tmp);
} while (*str2++ != 0);
return 0;
+#endif
}
/**
@@ -158,10 +161,14 @@ xmlStrEqual(const xmlChar *str1, const xmlChar *str2) {
if (str1 == str2) return(1);
if (str1 == NULL) return(0);
if (str2 == NULL) return(0);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ return(strcmp((const char *)str1, (const char *)str2) == 0);
+#else
do {
if (*str1++ != *str2) return(0);
} while (*str2++);
return(1);
+#endif
}
/**
@@ -204,18 +211,15 @@ xmlStrQEqual(const xmlChar *pref, const xmlChar *name, const xmlChar *str) {
int
xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
- register int tmp;
-
if (len <= 0) return(0);
if (str1 == str2) return(0);
if (str1 == NULL) return(-1);
if (str2 == NULL) return(1);
-#ifdef __GNUC__
- tmp = strncmp((const char *)str1, (const char *)str2, len);
- return tmp;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ return(strncmp((const char *)str1, (const char *)str2, len));
#else
do {
- tmp = *str1++ - *str2;
+ int tmp = *str1++ - *str2;
if (tmp != 0 || --len == 0) return(tmp);
} while (*str2++ != 0);
return 0;
@@ -420,14 +424,14 @@ xmlStrsub(const xmlChar *str, int start, int len) {
int
xmlStrlen(const xmlChar *str) {
- int len = 0;
+ size_t len = 0;
if (str == NULL) return(0);
while (*str != 0) { /* non input consuming */
str++;
len++;
}
- return(len);
+ return(len > INT_MAX ? 0 : len);
}
/**
@@ -457,9 +461,9 @@ xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
return(xmlStrndup(add, len));
size = xmlStrlen(cur);
- if (size < 0)
+ if ((size < 0) || (size > INT_MAX - len))
return(NULL);
- ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
+ ret = (xmlChar *) xmlRealloc(cur, ((size_t) size + len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlErrMemory(NULL, NULL);
return(cur);
@@ -497,9 +501,9 @@ xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) {
return(xmlStrndup(str2, len));
size = xmlStrlen(str1);
- if (size < 0)
+ if ((size < 0) || (size > INT_MAX - len))
return(NULL);
- ret = (xmlChar *) xmlMalloc((size + len + 1) * sizeof(xmlChar));
+ ret = (xmlChar *) xmlMalloc(((size_t) size + len + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlErrMemory(NULL, NULL);
return(xmlStrndup(str1, size));
@@ -664,7 +668,7 @@ xmlUTF8Charcmp(const xmlChar *utf1, const xmlChar *utf2) {
*/
int
xmlUTF8Strlen(const xmlChar *utf) {
- int ret = 0;
+ size_t ret = 0;
if (utf == NULL)
return(-1);
@@ -691,7 +695,7 @@ xmlUTF8Strlen(const xmlChar *utf) {
}
ret++;
}
- return(ret);
+ return(ret > INT_MAX ? 0 : ret);
}
/**
@@ -793,26 +797,28 @@ xmlCheckUTF8(const unsigned char *utf)
* 1110xxxx 10xxxxxx 10xxxxxx valid 3-byte
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx valid 4-byte
*/
- for (ix = 0; (c = utf[ix]);) { /* string is 0-terminated */
+ while ((c = utf[0])) { /* string is 0-terminated */
+ ix = 0;
if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
- ix++;
+ ix = 1;
} else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
- if ((utf[ix+1] & 0xc0 ) != 0x80)
+ if ((utf[1] & 0xc0 ) != 0x80)
return 0;
- ix += 2;
+ ix = 2;
} else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
- if (((utf[ix+1] & 0xc0) != 0x80) ||
- ((utf[ix+2] & 0xc0) != 0x80))
+ if (((utf[1] & 0xc0) != 0x80) ||
+ ((utf[2] & 0xc0) != 0x80))
return 0;
- ix += 3;
+ ix = 3;
} else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
- if (((utf[ix+1] & 0xc0) != 0x80) ||
- ((utf[ix+2] & 0xc0) != 0x80) ||
- ((utf[ix+3] & 0xc0) != 0x80))
+ if (((utf[1] & 0xc0) != 0x80) ||
+ ((utf[2] & 0xc0) != 0x80) ||
+ ((utf[3] & 0xc0) != 0x80))
return 0;
- ix += 4;
+ ix = 4;
} else /* unknown encoding */
return 0;
+ utf += ix;
}
return(1);
}
@@ -831,8 +837,9 @@ xmlCheckUTF8(const unsigned char *utf)
int
xmlUTF8Strsize(const xmlChar *utf, int len) {
- const xmlChar *ptr=utf;
- xmlChar ch;
+ const xmlChar *ptr=utf;
+ int ch;
+ size_t ret;
if (utf == NULL)
return(0);
@@ -849,7 +856,8 @@ xmlUTF8Strsize(const xmlChar *utf, int len) {
ptr++;
}
}
- return (ptr - utf);
+ ret = ptr - utf;
+ return (ret > INT_MAX ? 0 : ret);
}
@@ -869,11 +877,8 @@ xmlUTF8Strndup(const xmlChar *utf, int len) {
if ((utf == NULL) || (len < 0)) return(NULL);
i = xmlUTF8Strsize(utf, len);
- ret = (xmlChar *) xmlMallocAtomic((i + 1) * sizeof(xmlChar));
+ ret = (xmlChar *) xmlMallocAtomic(((size_t) i + 1) * sizeof(xmlChar));
if (ret == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "malloc of %ld byte failed\n",
- (len + 1) * (long)sizeof(xmlChar));
return(NULL);
}
memcpy(ret, utf, i * sizeof(xmlChar));
@@ -893,7 +898,7 @@ xmlUTF8Strndup(const xmlChar *utf, int len) {
*/
const xmlChar *
xmlUTF8Strpos(const xmlChar *utf, int pos) {
- xmlChar ch;
+ int ch;
if (utf == NULL) return(NULL);
if (pos < 0)
@@ -925,14 +930,15 @@ xmlUTF8Strpos(const xmlChar *utf, int pos) {
*/
int
xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar) {
- int i, size;
- xmlChar ch;
+ size_t i;
+ int size;
+ int ch;
if (utf==NULL || utfchar==NULL) return -1;
size = xmlUTF8Strsize(utfchar, 1);
for(i=0; (ch=*utf) != 0; i++) {
if (xmlStrncmp(utf, utfchar, size)==0)
- return(i);
+ return(i > INT_MAX ? 0 : i);
utf++;
if ( ch & 0x80 ) {
/* if not simple ascii, verify proper format */
@@ -962,8 +968,8 @@ xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar) {
xmlChar *
xmlUTF8Strsub(const xmlChar *utf, int start, int len) {
- int i;
- xmlChar ch;
+ int i;
+ int ch;
if (utf == NULL) return(NULL);
if (start < 0) return(NULL);
@@ -1019,6 +1025,8 @@ xmlEscapeFormatString(xmlChar **msg)
if (count == 0)
return(*msg);
+ if ((count > INT_MAX) || (msgLen > INT_MAX - count))
+ return(NULL);
resultLen = msgLen + count + 1;
result = (xmlChar *) xmlMallocAtomic(resultLen * sizeof(xmlChar));
if (result == NULL) {
diff --git a/contrib/libs/libxml/xpath.c b/contrib/libs/libxml/xpath.c
index e1f2bd5522..2da591cee9 100644
--- a/contrib/libs/libxml/xpath.c
+++ b/contrib/libs/libxml/xpath.c
@@ -136,6 +136,17 @@
#define XPATH_MAX_NODESET_LENGTH 10000000
/*
+ * XPATH_MAX_RECRUSION_DEPTH:
+ * Maximum amount of nested functions calls when parsing or evaluating
+ * expressions
+ */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#define XPATH_MAX_RECURSION_DEPTH 500
+#else
+#define XPATH_MAX_RECURSION_DEPTH 5000
+#endif
+
+/*
* TODO:
* There are a few spots where some tests are done which depend upon ascii
* data. These should be enhanced for full UTF8 support (see particularly
@@ -477,27 +488,23 @@ int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
* *
************************************************************************/
-#ifndef NAN
-#define NAN (0.0 / 0.0)
-#endif
-
-#ifndef INFINITY
-#define INFINITY HUGE_VAL
-#endif
-
-double xmlXPathNAN = NAN;
-double xmlXPathPINF = INFINITY;
-double xmlXPathNINF = -INFINITY;
+double xmlXPathNAN;
+double xmlXPathPINF;
+double xmlXPathNINF;
/**
* xmlXPathInit:
*
* Initialize the XPath environment
- *
- * Does nothing but must be kept as public function.
*/
+ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
void
xmlXPathInit(void) {
+ /* MSVC doesn't allow division by zero in constant expressions. */
+ double zero = 0.0;
+ xmlXPathNAN = 0.0 / zero;
+ xmlXPathPINF = 1.0 / zero;
+ xmlXPathNINF = -xmlXPathPINF;
}
/**
@@ -526,9 +533,9 @@ xmlXPathIsInf(double val) {
#ifdef isinf
return isinf(val) ? (val > 0 ? 1 : -1) : 0;
#else
- if (val >= INFINITY)
+ if (val >= xmlXPathPINF)
return 1;
- if (val <= -INFINITY)
+ if (val <= -xmlXPathPINF)
return -1;
return 0;
#endif
@@ -618,7 +625,7 @@ static const char *xmlXPathErrorMessages[] = {
/**
* xmlXPathErrMemory:
* @ctxt: an XPath context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -661,7 +668,7 @@ xmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra)
/**
* xmlXPathPErrMemory:
* @ctxt: an XPath parser context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -1745,7 +1752,6 @@ static int xmlXPathDebugObjMaxUsers = 0;
static int xmlXPathDebugObjMaxXSLTTree = 0;
static int xmlXPathDebugObjMaxAll = 0;
-/* REVISIT TODO: Make this static when committing */
static void
xmlXPathDebugObjUsageReset(xmlXPathContextPtr ctxt)
{
@@ -2060,7 +2066,6 @@ xmlXPathDebugObjUsageReleased(xmlXPathContextPtr ctxt,
xmlXPathDebugObjCounterAll--;
}
-/* REVISIT TODO: Make this static when committing */
static void
xmlXPathDebugObjUsageDisplay(xmlXPathContextPtr ctxt)
{
@@ -5863,10 +5868,10 @@ xmlXPathCastNodeToNumber (xmlNodePtr node) {
double ret;
if (node == NULL)
- return(NAN);
+ return(xmlXPathNAN);
strval = xmlXPathCastNodeToString(node);
if (strval == NULL)
- return(NAN);
+ return(xmlXPathNAN);
ret = xmlXPathCastStringToNumber(strval);
xmlFree(strval);
@@ -5887,7 +5892,7 @@ xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
double ret;
if (ns == NULL)
- return(NAN);
+ return(xmlXPathNAN);
str = xmlXPathCastNodeSetToString(ns);
ret = xmlXPathCastStringToNumber(str);
xmlFree(str);
@@ -5907,13 +5912,13 @@ xmlXPathCastToNumber(xmlXPathObjectPtr val) {
double ret = 0.0;
if (val == NULL)
- return(NAN);
+ return(xmlXPathNAN);
switch (val->type) {
case XPATH_UNDEFINED:
#ifdef DEBUG_EXPR
xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
#endif
- ret = NAN;
+ ret = xmlXPathNAN;
break;
case XPATH_NODESET:
case XPATH_XSLT_TREE:
@@ -5933,7 +5938,7 @@ xmlXPathCastToNumber(xmlXPathObjectPtr val) {
case XPATH_RANGE:
case XPATH_LOCATIONSET:
TODO;
- ret = NAN;
+ ret = xmlXPathNAN;
break;
}
return(ret);
@@ -6119,9 +6124,6 @@ xmlXPathNewContext(xmlDocPtr doc) {
ret->contextSize = -1;
ret->proximityPosition = -1;
- ret->maxDepth = INT_MAX;
- ret->maxParserDepth = INT_MAX;
-
#ifdef XP_DEFAULT_CACHE_ON
if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
xmlXPathFreeContext(ret);
@@ -7563,7 +7565,7 @@ xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
CHECK_TYPE(XPATH_NUMBER);
arg1 = ctxt->value->floatval;
if (arg2 == 0)
- ctxt->value->floatval = NAN;
+ ctxt->value->floatval = xmlXPathNAN;
else {
ctxt->value->floatval = fmod(arg1, arg2);
}
@@ -9993,7 +9995,7 @@ xmlXPathStringEvalNumber(const xmlChar *str) {
if (cur == NULL) return(0);
while (IS_BLANK_CH(*cur)) cur++;
if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
- return(NAN);
+ return(xmlXPathNAN);
}
if (*cur == '-') {
isneg = 1;
@@ -10029,7 +10031,7 @@ xmlXPathStringEvalNumber(const xmlChar *str) {
cur++;
if (((*cur < '0') || (*cur > '9')) && (!ok)) {
- return(NAN);
+ return(xmlXPathNAN);
}
while (*cur == '0') {
frac = frac + 1;
@@ -10062,7 +10064,7 @@ xmlXPathStringEvalNumber(const xmlChar *str) {
}
}
while (IS_BLANK_CH(*cur)) cur++;
- if (*cur != 0) return(NAN);
+ if (*cur != 0) return(xmlXPathNAN);
if (isneg) ret = -ret;
if (is_exponent_negative) exponent = -exponent;
ret *= pow(10.0, (double)exponent);
@@ -10087,6 +10089,7 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
int ok = 0;
int exponent = 0;
int is_exponent_negative = 0;
+ xmlXPathObjectPtr num;
#ifdef __GNUC__
unsigned long tmp = 0;
double temp;
@@ -10159,8 +10162,13 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
exponent = -exponent;
ret *= pow(10.0, (double) exponent);
}
- PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0,
- xmlXPathCacheNewFloat(ctxt->context, ret), NULL);
+ num = xmlXPathCacheNewFloat(ctxt->context, ret);
+ if (num == NULL) {
+ ctxt->error = XPATH_MEMORY_ERROR;
+ } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num,
+ NULL) == -1) {
+ xmlXPathReleaseObject(ctxt->context, num);
+ }
}
/**
@@ -10222,6 +10230,7 @@ static void
xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
const xmlChar *q;
xmlChar *ret = NULL;
+ xmlXPathObjectPtr lit;
if (CUR == '"') {
NEXT;
@@ -10249,8 +10258,13 @@ xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
XP_ERROR(XPATH_START_LITERAL_ERROR);
}
if (ret == NULL) return;
- PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0,
- xmlXPathCacheNewString(ctxt->context, ret), NULL);
+ lit = xmlXPathCacheNewString(ctxt->context, ret);
+ if (lit == NULL) {
+ ctxt->error = XPATH_MEMORY_ERROR;
+ } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit,
+ NULL) == -1) {
+ xmlXPathReleaseObject(ctxt->context, lit);
+ }
xmlFree(ret);
}
@@ -10287,8 +10301,10 @@ xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
XP_ERROR(XPATH_VARIABLE_REF_ERROR);
}
ctxt->comp->last = -1;
- PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
- name, prefix);
+ if (PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, name, prefix) == -1) {
+ xmlFree(prefix);
+ xmlFree(name);
+ }
SKIP_BLANKS;
if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
@@ -10395,8 +10411,10 @@ xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
SKIP_BLANKS;
}
}
- PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
- name, prefix);
+ if (PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, name, prefix) == -1) {
+ xmlFree(prefix);
+ xmlFree(name);
+ }
NEXT;
SKIP_BLANKS;
}
@@ -10933,9 +10951,13 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
xmlXPathContextPtr xpctxt = ctxt->context;
if (xpctxt != NULL) {
- if (xpctxt->depth >= xpctxt->maxParserDepth)
+ if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
- xpctxt->depth += 1;
+ /*
+ * Parsing a single '(' pushes about 10 functions on the call stack
+ * before recursing!
+ */
+ xpctxt->depth += 10;
}
xmlXPathCompAndExpr(ctxt);
@@ -10961,7 +10983,7 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
}
if (xpctxt != NULL)
- xpctxt->depth -= 1;
+ xpctxt->depth -= 10;
}
/**
@@ -11037,7 +11059,7 @@ xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
*/
static xmlChar *
xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
- xmlXPathTypeVal *type, const xmlChar **prefix,
+ xmlXPathTypeVal *type, xmlChar **prefix,
xmlChar *name) {
int blanks;
@@ -11098,7 +11120,9 @@ xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
name = NULL;
if (CUR != ')') {
name = xmlXPathParseLiteral(ctxt);
- CHECK_ERROR NULL;
+ if (name == NULL) {
+ XP_ERRORNULL(XPATH_EXPR_ERROR);
+ }
*test = NODE_TEST_PI;
SKIP_BLANKS;
}
@@ -11268,7 +11292,7 @@ xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
SKIP_BLANKS;
} else {
xmlChar *name = NULL;
- const xmlChar *prefix = NULL;
+ xmlChar *prefix = NULL;
xmlXPathTestVal test = (xmlXPathTestVal) 0;
xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
xmlXPathTypeVal type = (xmlXPathTypeVal) 0;
@@ -11378,9 +11402,11 @@ eval_predicates:
PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
} else
#endif
- PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
- test, type, (void *)prefix, (void *)name);
-
+ if (PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
+ test, type, (void *)prefix, (void *)name) == -1) {
+ xmlFree(prefix);
+ xmlFree(name);
+ }
}
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext, "Step : ");
@@ -11648,11 +11674,11 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
if (ctxt->error != XPATH_EXPRESSION_OK)
- goto exit;
+ break;
if (res < 0) {
/* Shouldn't happen */
xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
- goto exit;
+ break;
}
if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
@@ -11671,15 +11697,7 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
if (res != 0) {
if (pos == maxPos) {
- /* Clear remaining nodes and exit loop. */
- if (hasNsNodes) {
- for (i++; i < set->nodeNr; i++) {
- node = set->nodeTab[i];
- if ((node != NULL) &&
- (node->type == XML_NAMESPACE_DECL))
- xmlXPathNodeSetFreeNs((xmlNsPtr) node);
- }
- }
+ i += 1;
break;
}
@@ -11687,6 +11705,15 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
}
}
+ /* Free remaining nodes. */
+ if (hasNsNodes) {
+ for (; i < set->nodeNr; i++) {
+ xmlNodePtr node = set->nodeTab[i];
+ if ((node != NULL) && (node->type == XML_NAMESPACE_DECL))
+ xmlXPathNodeSetFreeNs((xmlNsPtr) node);
+ }
+ }
+
set->nodeNr = j;
/* If too many elements were removed, shrink table to preserve memory. */
@@ -11707,7 +11734,6 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
}
}
-exit:
xpctxt->node = oldnode;
xpctxt->doc = olddoc;
xpctxt->contextSize = oldcs;
@@ -11772,11 +11798,11 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
if (ctxt->error != XPATH_EXPRESSION_OK)
- goto exit;
+ break;
if (res < 0) {
/* Shouldn't happen */
xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
- goto exit;
+ break;
}
if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
@@ -11794,10 +11820,7 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
if (res != 0) {
if (pos == maxPos) {
- /* Clear remaining nodes and exit loop. */
- for (i++; i < locset->locNr; i++) {
- xmlXPathFreeObject(locset->locTab[i]);
- }
+ i += 1;
break;
}
@@ -11805,6 +11828,10 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
}
}
+ /* Free remaining nodes. */
+ for (; i < locset->locNr; i++)
+ xmlXPathFreeObject(locset->locTab[i]);
+
locset->locNr = j;
/* If too many elements were removed, shrink table to preserve memory. */
@@ -11825,7 +11852,6 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
}
}
-exit:
xpctxt->node = oldnode;
xpctxt->doc = olddoc;
xpctxt->contextSize = oldcs;
@@ -11863,7 +11889,7 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
"xmlXPathCompOpEvalPredicate: Expected a predicate\n");
XP_ERROR(XPATH_INVALID_OPERAND);
}
- if (ctxt->context->depth >= ctxt->context->maxDepth)
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
ctxt->context->depth += 1;
xmlXPathCompOpEvalPredicate(ctxt, &comp->steps[op->ch1], set,
@@ -12579,7 +12605,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
CHECK_ERROR0;
if (OP_LIMIT_EXCEEDED(ctxt, 1))
return(0);
- if (ctxt->context->depth >= ctxt->context->maxDepth)
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
ctxt->context->depth += 1;
comp = ctxt->comp;
@@ -12720,7 +12746,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
CHECK_ERROR0;
if (OP_LIMIT_EXCEEDED(ctxt, 1))
return(0);
- if (ctxt->context->depth >= ctxt->context->maxDepth)
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
ctxt->context->depth += 1;
comp = ctxt->comp;
@@ -12938,7 +12964,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
CHECK_ERROR0;
if (OP_LIMIT_EXCEEDED(ctxt, 1))
return(0);
- if (ctxt->context->depth >= ctxt->context->maxDepth)
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
ctxt->context->depth += 1;
comp = ctxt->comp;
@@ -13814,7 +13840,8 @@ scan_children:
do {
cur = cur->parent;
depth--;
- if ((cur == NULL) || (cur == limit))
+ if ((cur == NULL) || (cur == limit) ||
+ (cur->type == XML_DOCUMENT_NODE))
goto done;
if (cur->type == XML_ELEMENT_NODE) {
ret = xmlStreamPop(patstream);
@@ -14085,8 +14112,7 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
}
}
- stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH,
- &namespaces[0]);
+ stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, namespaces);
if (namespaces != NULL) {
xmlFree((xmlChar **)namespaces);
}
@@ -14172,7 +14198,7 @@ xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,
/* Recurse */
ctxt = pctxt->context;
if (ctxt != NULL) {
- if (ctxt->depth >= ctxt->maxDepth)
+ if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
return;
ctxt->depth += 1;
}
@@ -14205,7 +14231,7 @@ xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
return(comp);
#endif
- xmlXPathInit();
+ xmlInitParser();
pctxt = xmlXPathNewParserContext(str, ctxt);
if (pctxt == NULL)
@@ -14294,7 +14320,7 @@ xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
if (comp == NULL)
return(-1);
- xmlXPathInit();
+ xmlInitParser();
#ifndef LIBXML_THREAD_ENABLED
reentance++;
@@ -14439,7 +14465,7 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
CHECK_CTXT(ctx)
- xmlXPathInit();
+ xmlInitParser();
ctxt = xmlXPathNewParserContext(str, ctx);
if (ctxt == NULL)
diff --git a/contrib/libs/libxml/xpointer.c b/contrib/libs/libxml/xpointer.c
index c1732a584a..afeaa2ecf9 100644
--- a/contrib/libs/libxml/xpointer.c
+++ b/contrib/libs/libxml/xpointer.c
@@ -70,7 +70,7 @@
/**
* xmlXPtrErrMemory:
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -86,7 +86,7 @@ xmlXPtrErrMemory(const char *extra)
/**
* xmlXPtrErr:
* @ctxt: an XPTR evaluation context
- * @extra: extra informations
+ * @extra: extra information
*
* Handle a redefinition of attribute error
*/
@@ -851,7 +851,6 @@ static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name);
*
* Dirty macros, i.e. one need to make assumption on the context to use them
*
- * CUR_PTR return the current pointer to the xmlChar to be parsed.
* CUR returns the current xmlChar value, i.e. a 8 bit value
* in ISO-Latin or UTF-8.
* This should be used internally by the parser
@@ -871,7 +870,6 @@ static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name);
#define CUR (*ctxt->cur)
#define SKIP(val) ctxt->cur += (val)
#define NXT(val) ctxt->cur[(val)]
-#define CUR_PTR ctxt->cur
#define SKIP_BLANKS \
while (IS_BLANK_CH(*(ctxt->cur))) NEXT
@@ -999,55 +997,63 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
}
if (xmlStrEqual(name, (xmlChar *) "xpointer")) {
- const xmlChar *left = CUR_PTR;
+ const xmlChar *oldBase = ctxt->base;
+ const xmlChar *oldCur = ctxt->cur;
- CUR_PTR = buffer;
+ ctxt->cur = ctxt->base = buffer;
/*
* To evaluate an xpointer scheme element (4.3) we need:
* context initialized to the root
- * context position initalized to 1
+ * context position initialized to 1
* context size initialized to 1
*/
ctxt->context->node = (xmlNodePtr)ctxt->context->doc;
ctxt->context->proximityPosition = 1;
ctxt->context->contextSize = 1;
xmlXPathEvalExpr(ctxt);
- CUR_PTR=left;
+ ctxt->base = oldBase;
+ ctxt->cur = oldCur;
} else if (xmlStrEqual(name, (xmlChar *) "element")) {
- const xmlChar *left = CUR_PTR;
+ const xmlChar *oldBase = ctxt->base;
+ const xmlChar *oldCur = ctxt->cur;
xmlChar *name2;
- CUR_PTR = buffer;
+ ctxt->cur = ctxt->base = buffer;
if (buffer[0] == '/') {
xmlXPathRoot(ctxt);
xmlXPtrEvalChildSeq(ctxt, NULL);
} else {
name2 = xmlXPathParseName(ctxt);
if (name2 == NULL) {
- CUR_PTR = left;
+ ctxt->base = oldBase;
+ ctxt->cur = oldCur;
xmlFree(buffer);
xmlFree(name);
XP_ERROR(XPATH_EXPR_ERROR);
}
xmlXPtrEvalChildSeq(ctxt, name2);
}
- CUR_PTR = left;
+ ctxt->base = oldBase;
+ ctxt->cur = oldCur;
#ifdef XPTR_XMLNS_SCHEME
} else if (xmlStrEqual(name, (xmlChar *) "xmlns")) {
- const xmlChar *left = CUR_PTR;
+ const xmlChar *oldBase = ctxt->base;
+ const xmlChar *oldCur = ctxt->cur;
xmlChar *prefix;
- xmlChar *URI;
- xmlURIPtr value;
- CUR_PTR = buffer;
+ ctxt->cur = ctxt->base = buffer;
prefix = xmlXPathParseNCName(ctxt);
if (prefix == NULL) {
+ ctxt->base = oldBase;
+ ctxt->cur = oldCur;
xmlFree(buffer);
xmlFree(name);
XP_ERROR(XPTR_SYNTAX_ERROR);
}
SKIP_BLANKS;
if (CUR != '=') {
+ ctxt->base = oldBase;
+ ctxt->cur = oldCur;
xmlFree(prefix);
xmlFree(buffer);
xmlFree(name);
@@ -1055,27 +1061,10 @@ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
}
NEXT;
SKIP_BLANKS;
- /* @@ check escaping in the XPointer WD */
- value = xmlParseURI((const char *)ctxt->cur);
- if (value == NULL) {
- xmlFree(prefix);
- xmlFree(buffer);
- xmlFree(name);
- XP_ERROR(XPTR_SYNTAX_ERROR);
- }
- URI = xmlSaveUri(value);
- xmlFreeURI(value);
- if (URI == NULL) {
- xmlFree(prefix);
- xmlFree(buffer);
- xmlFree(name);
- XP_ERROR(XPATH_MEMORY_ERROR);
- }
-
- xmlXPathRegisterNs(ctxt->context, prefix, URI);
- CUR_PTR = left;
- xmlFree(URI);
+ xmlXPathRegisterNs(ctxt->context, prefix, ctxt->cur);
+ ctxt->base = oldBase;
+ ctxt->cur = oldCur;
xmlFree(prefix);
#endif /* XPTR_XMLNS_SCHEME */
} else {
@@ -1352,7 +1341,7 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
xmlXPathObjectPtr init = NULL;
int stack = 0;
- xmlXPathInit();
+ xmlInitParser();
if ((ctx == NULL) || (str == NULL))
return(NULL);
@@ -1470,16 +1459,16 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
return(list);
} else {
tmp = xmlCopyNode(cur, 0);
- if (list == NULL)
+ if (list == NULL) {
list = tmp;
- else {
+ parent = tmp;
+ } else {
if (last != NULL)
- xmlAddNextSibling(last, tmp);
+ parent = xmlAddNextSibling(last, tmp);
else
- xmlAddChild(parent, tmp);
+ parent = xmlAddChild(parent, tmp);
}
last = NULL;
- parent = tmp;
if (index2 > 1) {
end = xmlXPtrGetNthChild(cur, index2 - 1);
@@ -1536,7 +1525,7 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_NODE:
- /* Do not copy DTD informations */
+ /* Do not copy DTD information */
break;
case XML_ENTITY_DECL:
TODO /* handle crossing entities -> stack needed */
@@ -1561,8 +1550,7 @@ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
if (last != NULL)
xmlAddNextSibling(last, tmp);
else {
- xmlAddChild(parent, tmp);
- last = tmp;
+ last = xmlAddChild(parent, tmp);
}
}
}
@@ -2200,7 +2188,6 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
XP_ERROR(XPATH_MEMORY_ERROR)
set = tmp;
}
- oldset = (xmlLocationSetPtr) set->user;
/*
* The loop is to compute the covering range for each item and add it
@@ -2210,9 +2197,12 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathFreeObject(set);
XP_ERROR(XPATH_MEMORY_ERROR);
}
- for (i = 0;i < oldset->locNr;i++) {
- xmlXPtrLocationSetAdd(newset,
- xmlXPtrInsideRange(ctxt, oldset->locTab[i]));
+ oldset = (xmlLocationSetPtr) set->user;
+ if (oldset != NULL) {
+ for (i = 0;i < oldset->locNr;i++) {
+ xmlXPtrLocationSetAdd(newset,
+ xmlXPtrInsideRange(ctxt, oldset->locTab[i]));
+ }
}
/*
@@ -2706,10 +2696,10 @@ static void
xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
int i, startindex, endindex = 0, fendindex;
xmlNodePtr start, end = 0, fend;
- xmlXPathObjectPtr set;
+ xmlXPathObjectPtr set = NULL;
xmlLocationSetPtr oldset;
- xmlLocationSetPtr newset;
- xmlXPathObjectPtr string;
+ xmlLocationSetPtr newset = NULL;
+ xmlXPathObjectPtr string = NULL;
xmlXPathObjectPtr position = NULL;
xmlXPathObjectPtr number = NULL;
int found, pos = 0, num = 0;
@@ -2721,29 +2711,39 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
XP_ERROR(XPATH_INVALID_ARITY);
if (nargs >= 4) {
- CHECK_TYPE(XPATH_NUMBER);
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
+ goto error;
+ }
number = valuePop(ctxt);
if (number != NULL)
num = (int) number->floatval;
}
if (nargs >= 3) {
- CHECK_TYPE(XPATH_NUMBER);
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
+ goto error;
+ }
position = valuePop(ctxt);
if (position != NULL)
pos = (int) position->floatval;
}
- CHECK_TYPE(XPATH_STRING);
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
+ goto error;
+ }
string = valuePop(ctxt);
if ((ctxt->value == NULL) ||
((ctxt->value->type != XPATH_LOCATIONSET) &&
- (ctxt->value->type != XPATH_NODESET)))
- XP_ERROR(XPATH_INVALID_TYPE)
-
+ (ctxt->value->type != XPATH_NODESET))) {
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
+ goto error;
+ }
set = valuePop(ctxt);
newset = xmlXPtrLocationSetCreate(NULL);
if (newset == NULL) {
- xmlXPathFreeObject(set);
- XP_ERROR(XPATH_MEMORY_ERROR);
+ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
+ goto error;
}
if (set->nodesetval == NULL) {
goto error;
@@ -2756,8 +2756,10 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
*/
tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
xmlXPathFreeObject(set);
- if (tmp == NULL)
- XP_ERROR(XPATH_MEMORY_ERROR)
+ if (tmp == NULL) {
+ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
+ goto error;
+ }
set = tmp;
}
oldset = (xmlLocationSetPtr) set->user;
@@ -2830,7 +2832,8 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
* Save the new value and cleanup
*/
error:
- valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
+ if (newset != NULL)
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
xmlXPathFreeObject(set);
xmlXPathFreeObject(string);
if (position) xmlXPathFreeObject(position);