diff options
author | Nick Wellnhofer <wellnhofer@aevum.de> | 2023-04-30 18:25:09 +0200 |
---|---|---|
committer | Nick Wellnhofer <wellnhofer@aevum.de> | 2023-04-30 21:31:54 +0200 |
commit | 320f5084cd26b98af69c21d8745577183e1034e0 (patch) | |
tree | fb0caf6677c4a47530ee992f130f49b1541c95c1 | |
parent | fc69cf568b247a76fe5498966024bfb84b0c974d (diff) | |
download | libxml2-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.c | 19 | ||||
-rw-r--r-- | encoding.c | 54 | ||||
-rw-r--r-- | parser.c | 44 | ||||
-rw-r--r-- | parserInternals.c | 5 | ||||
-rw-r--r-- | xmlIO.c | 31 | ||||
-rw-r--r-- | xmlreader.c | 2 |
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 @@ -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 @@ -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); } @@ -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) || |