summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Wellnhofer <wellnhofer@aevum.de>2023-04-30 18:25:09 +0200
committerNick Wellnhofer <wellnhofer@aevum.de>2023-04-30 21:31:54 +0200
commit320f5084cd26b98af69c21d8745577183e1034e0 (patch)
treefb0caf6677c4a47530ee992f130f49b1541c95c1
parentfc69cf568b247a76fe5498966024bfb84b0c974d (diff)
downloadlibxml2-320f5084cd26b98af69c21d8745577183e1034e0.tar.gz
parser: Improve handling of encoding and IO errors
Make sure that xmlCharEncInput, xmlParserInputBufferPush and xmlParserInputBufferGrow set the correct error code in the xmlParserInputBuffer. Handle errors when calling these functions.
-rw-r--r--HTMLparser.c19
-rw-r--r--encoding.c54
-rw-r--r--parser.c44
-rw-r--r--parserInternals.c5
-rw-r--r--xmlIO.c31
-rw-r--r--xmlreader.c2
6 files changed, 116 insertions, 39 deletions
diff --git a/HTMLparser.c b/HTMLparser.c
index abcdfe24..ca2da8fa 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -3858,9 +3858,10 @@ htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) {
nbchars = xmlCharEncInput(ctxt->input->buf, 1);
xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
if (nbchars < 0) {
- htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
+ htmlParseErr(ctxt, ctxt->input->buf->error,
"htmlCheckEncoding: encoder error\n",
NULL, NULL);
+ xmlHaltParser(ctxt);
}
}
}
@@ -6279,7 +6280,9 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
if (res < 0) {
- htmlErrMemory(ctxt, NULL);
+ htmlParseErr(ctxt, ctxt->input->buf->error,
+ "xmlParserInputBufferPush failed", NULL, NULL);
+ xmlHaltParser(ctxt);
return (ctxt->errNo);
}
#ifdef DEBUG_PUSH
@@ -6302,8 +6305,9 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
nbchars = xmlCharEncInput(in, terminate);
xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
if (nbchars < 0) {
- htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
+ htmlParseErr(ctxt, in->error,
"encoder error\n", NULL, NULL);
+ xmlHaltParser(ctxt);
return(XML_ERR_INVALID_ENCODING);
}
}
@@ -6394,10 +6398,15 @@ htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data,
(ctxt->input->buf != NULL)) {
size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
size_t cur = ctxt->input->cur - ctxt->input->base;
+ int res;
- xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-
+ res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+ if (res < 0) {
+ htmlParseErr(ctxt, ctxt->input->buf->error,
+ "xmlParserInputBufferPush failed\n", NULL, NULL);
+ xmlHaltParser(ctxt);
+ }
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
#endif
diff --git a/encoding.c b/encoding.c
index 6c2aa32e..e395f264 100644
--- a/encoding.c
+++ b/encoding.c
@@ -2007,6 +2007,34 @@ xmlUconvWrapper(uconv_t *cd, int toUnicode, unsigned char *out, int *outlen,
************************************************************************/
/**
+ * xmlEncConvertError:
+ * @code: XML_ENC_ERR code
+ *
+ * Convert XML_ENC_ERR to libxml2 error codes.
+ */
+static int
+xmlEncConvertError(int code) {
+ int ret;
+
+ switch (code) {
+ case XML_ENC_ERR_SUCCESS:
+ ret = XML_ERR_OK;
+ break;
+ case XML_ENC_ERR_INPUT:
+ ret = XML_ERR_INVALID_ENCODING;
+ break;
+ case XML_ENC_ERR_MEMORY:
+ ret = XML_ERR_NO_MEMORY;
+ break;
+ default:
+ ret = XML_ERR_INTERNAL_ERROR;
+ break;
+ }
+
+ return(ret);
+}
+
+/**
* xmlEncInputChunk:
* @handler: encoding handler
* @out: a pointer to an array of bytes to store the result
@@ -2165,7 +2193,13 @@ xmlCharEncInput(xmlParserInputBufferPtr input, int flush)
xmlBufShrink(in, c_in);
xmlBufAddLen(out, c_out);
- return (c_out? c_out : ret);
+ if ((c_out == 0) && (ret != 0)) {
+ if (input->error == 0)
+ input->error = xmlEncConvertError(ret);
+ return(ret);
+ }
+
+ return (c_out);
}
/**
@@ -2301,7 +2335,7 @@ retry:
cur = xmlGetUTF8Char(content, &len);
if (cur <= 0)
- return(ret);
+ goto error;
#ifdef DEBUG_ENCODING
xmlGenericError(xmlGenericErrorContext,
@@ -2324,14 +2358,24 @@ retry:
c_in = charrefLen;
ret = xmlEncOutputChunk(output->encoder, xmlBufEnd(out), &c_out,
charref, &c_in);
- if ((ret < 0) || (c_in != charrefLen))
- return(XML_ENC_ERR_INTERNAL);
+ if ((ret < 0) || (c_in != charrefLen)) {
+ ret = XML_ENC_ERR_INTERNAL;
+ goto error;
+ }
xmlBufAddLen(out, c_out);
writtentot += c_out;
goto retry;
}
- return(writtentot ? writtentot : ret);
+
+error:
+ if ((writtentot <= 0) && (ret != 0)) {
+ if (output->error == 0)
+ output->error = xmlEncConvertError(ret);
+ return(ret);
+ }
+
+ return(writtentot);
}
#endif
diff --git a/parser.c b/parser.c
index 100189ca..bb05791d 100644
--- a/parser.c
+++ b/parser.c
@@ -11144,10 +11144,16 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
ctxt->input);
size_t current = ctxt->input->cur - ctxt->input->base;
+ int res;
- xmlParserInputBufferPush(ctxt->input->buf, 0, "");
+ res = xmlParserInputBufferPush(ctxt->input->buf, 0, "");
xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
base, current);
+ if (res < 0) {
+ xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
+ xmlHaltParser(ctxt);
+ return(0);
+ }
}
}
avail = ctxt->input->end - ctxt->input->cur;
@@ -11822,9 +11828,9 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
if (res < 0) {
- ctxt->errNo = XML_PARSER_EOF;
+ xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
xmlHaltParser(ctxt);
- return (XML_PARSER_EOF);
+ return(ctxt->errNo);
}
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
@@ -11842,11 +11848,9 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
nbchars = xmlCharEncInput(in, terminate);
xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
if (nbchars < 0) {
- /* TODO 2.6.0 */
- xmlGenericError(xmlGenericErrorContext,
- "xmlParseChunk: encoder error\n");
+ xmlFatalErr(ctxt, in->error, NULL);
xmlHaltParser(ctxt);
- return(XML_ERR_INVALID_ENCODING);
+ return(ctxt->errNo);
}
}
}
@@ -11871,11 +11875,16 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
ctxt->input);
size_t current = ctxt->input->cur - ctxt->input->base;
+ int res;
- xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
-
+ res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
base, current);
+ if (res < 0) {
+ xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
+ xmlHaltParser(ctxt);
+ return(ctxt->errNo);
+ }
}
if (terminate) {
/*
@@ -11983,10 +11992,14 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
(ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
size_t cur = ctxt->input->cur - ctxt->input->base;
+ int res;
- xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-
+ res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+ if (res < 0) {
+ xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
+ xmlHaltParser(ctxt);
+ }
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
#endif
@@ -14351,10 +14364,15 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
(ctxt->input->buf != NULL)) {
size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
size_t cur = ctxt->input->cur - ctxt->input->base;
+ int res;
- xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
-
+ res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
+ if (res < 0) {
+ xmlFatalErr(ctxt, ctxt->input->buf->error, NULL);
+ xmlHaltParser(ctxt);
+ return(1);
+ }
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
#endif
diff --git a/parserInternals.c b/parserInternals.c
index 4fa24c0c..6612ea74 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -553,7 +553,7 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) {
if (((curEnd > XML_MAX_LOOKUP_LIMIT) ||
(curBase > XML_MAX_LOOKUP_LIMIT)) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) {
- xmlErrInternal(ctxt, "Huge input lookup", NULL);
+ xmlErrMemory(ctxt, "Huge input lookup");
xmlHaltParser(ctxt);
return(-1);
}
@@ -564,9 +564,8 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) {
ret = xmlParserInputBufferGrow(buf, INPUT_CHUNK);
xmlBufSetInputBaseCur(buf->buffer, in, 0, curBase);
- /* TODO: Get error code from xmlParserInputBufferGrow */
if (ret < 0) {
- xmlErrInternal(ctxt, "Growing input buffer", NULL);
+ xmlFatalErr(ctxt, buf->error, NULL);
xmlHaltParser(ctxt);
}
diff --git a/xmlIO.c b/xmlIO.c
index 5cab16f4..658d608f 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -3119,21 +3119,24 @@ xmlParserInputBufferPush(xmlParserInputBufferPtr in,
*/
if (in->raw == NULL) {
in->raw = xmlBufCreate();
+ if (in->raw == NULL) {
+ in->error = XML_ERR_NO_MEMORY;
+ return(-1);
+ }
}
ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
- if (ret != 0)
+ if (ret != 0) {
+ in->error = XML_ERR_NO_MEMORY;
return(-1);
+ }
/*
* convert as much as possible to the parser reading buffer.
*/
use = xmlBufUse(in->raw);
nbchars = xmlCharEncInput(in, 1);
- if (nbchars < 0) {
- xmlIOErr(XML_IO_ENCODER, NULL);
- in->error = XML_IO_ENCODER;
+ if (nbchars < 0)
return(-1);
- }
consumed = use - xmlBufUse(in->raw);
if ((consumed > ULONG_MAX) ||
(in->rawconsumed > ULONG_MAX - (unsigned long)consumed))
@@ -3143,8 +3146,10 @@ xmlParserInputBufferPush(xmlParserInputBufferPtr in,
} else {
nbchars = len;
ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
- if (ret != 0)
+ if (ret != 0) {
+ in->error = XML_ERR_NO_MEMORY;
return(-1);
+ }
}
#ifdef DEBUG_INPUT
xmlGenericError(xmlGenericErrorContext,
@@ -3207,7 +3212,6 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
*/
if (in->readcallback != NULL) {
if (xmlBufGrow(buf, len + 1) < 0) {
- xmlIOErrMemory("growing input buffer");
in->error = XML_ERR_NO_MEMORY;
return(-1);
}
@@ -3215,11 +3219,15 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
res = in->readcallback(in->context, (char *)xmlBufEnd(buf), len);
if (res <= 0)
in->readcallback = endOfInput;
- if (res < 0)
+ if (res < 0) {
+ in->error = XML_IO_UNKNOWN;
return(-1);
+ }
- if (xmlBufAddLen(buf, res) < 0)
+ if (xmlBufAddLen(buf, res) < 0) {
+ in->error = XML_ERR_NO_MEMORY;
return(-1);
+ }
}
/*
@@ -3240,11 +3248,8 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
*/
use = xmlBufUse(buf);
res = xmlCharEncInput(in, 1);
- if (res < 0) {
- xmlIOErr(XML_IO_ENCODER, NULL);
- in->error = XML_IO_ENCODER;
+ if (res < 0)
return(-1);
- }
consumed = use - xmlBufUse(buf);
if ((consumed > ULONG_MAX) ||
(in->rawconsumed > ULONG_MAX - (unsigned long)consumed))
diff --git a/xmlreader.c b/xmlreader.c
index 979385a1..71f2f933 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -788,6 +788,8 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
reader->state = oldstate;
}
} else if (val < 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParserInputBufferRead failed\n");
reader->mode = XML_TEXTREADER_MODE_EOF;
reader->state = oldstate;
if ((oldstate != XML_TEXTREADER_START) ||