mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-25 10:50:08 +03:00
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.
This commit is contained in:
parent
fc69cf568b
commit
320f5084cd
19
HTMLparser.c
19
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
|
||||
|
54
encoding.c
54
encoding.c
@ -2006,6 +2006,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
|
||||
@ -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
|
||||
|
||||
|
44
parser.c
44
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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
31
xmlIO.c
31
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))
|
||||
|
@ -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) ||
|
||||
|
Loading…
x
Reference in New Issue
Block a user