From 23345a1cb1ab344620810de316b6992c812b2905 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 19 Dec 2023 19:52:28 +0100 Subject: [PATCH] io: Report IO errors through xmlCtxtErrIO This is also a new public API function to be used in external entity loaders. --- include/libxml/parserInternals.h | 4 ++ include/private/io.h | 2 - parser.c | 10 ++--- parserInternals.c | 4 +- xmlIO.c | 67 +++++++++++++++++++++++--------- xmlreader.c | 2 +- 6 files changed, 61 insertions(+), 28 deletions(-) diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h index 88d84acb..3f0c243e 100644 --- a/include/libxml/parserInternals.h +++ b/include/libxml/parserInternals.h @@ -315,6 +315,10 @@ XMLPUBFUN xmlParserCtxtPtr const xmlChar *base); XMLPUBFUN void xmlCtxtErrMemory (xmlParserCtxtPtr ctxt); +XMLPUBFUN void + xmlCtxtErrIO (xmlParserCtxtPtr ctxt, + int code, + const char *uri); XMLPUBFUN int xmlSwitchEncoding (xmlParserCtxtPtr ctxt, xmlCharEncoding enc); diff --git a/include/private/io.h b/include/private/io.h index 41cf560a..ca2c8e7e 100644 --- a/include/private/io.h +++ b/include/private/io.h @@ -7,8 +7,6 @@ XML_HIDDEN int __xmlIOErr(int domain, int code, const char *extra); -XML_HIDDEN void -xmlLoaderErr(xmlParserCtxtPtr ctxt, int code, const char *filename); XML_HIDDEN int xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc, diff --git a/parser.c b/parser.c index de510458..9fc29edc 100644 --- a/parser.c +++ b/parser.c @@ -8118,7 +8118,7 @@ xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { xmlBufResetInput(input->buf->buffer, input); if (res < 0) { - xmlFatalErr(ctxt, input->buf->error, NULL); + xmlCtxtErrIO(ctxt, input->buf->error, NULL); goto error; } @@ -11934,7 +11934,7 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); xmlHaltParser(ctxt); return(ctxt->errNo); } @@ -11961,7 +11961,7 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, res = xmlParserInputBufferPush(ctxt->input->buf, 1, "\r"); xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); xmlHaltParser(ctxt); return(ctxt->errNo); } @@ -12085,7 +12085,7 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); xmlHaltParser(ctxt); } } @@ -14348,7 +14348,7 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); if (res < 0) { - xmlFatalErr(ctxt, ctxt->input->buf->error, NULL); + xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); xmlHaltParser(ctxt); return(1); } diff --git a/parserInternals.c b/parserInternals.c index 35e6734b..6b487a3b 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -616,7 +616,7 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) { xmlBufUpdateInput(buf->buffer, in, curBase); if (ret < 0) { - xmlFatalErr(ctxt, buf->error, NULL); + xmlCtxtErrIO(ctxt, buf->error, NULL); } return(ret); @@ -1812,7 +1812,7 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) { code = xmlParserInputBufferCreateFilenameSafe(filename, XML_CHAR_ENCODING_NONE, &buf); if (buf == NULL) { - xmlLoaderErr(ctxt, code, filename); + xmlCtxtErrIO(ctxt, code, filename); return(NULL); } diff --git a/xmlIO.c b/xmlIO.c index 8acb9d5d..2d9ff109 100644 --- a/xmlIO.c +++ b/xmlIO.c @@ -425,33 +425,59 @@ xmlIOErr(int code, const char *extra) } /** - * xmlLoaderErr: - * @ctx: parser context - * @code: error code - * @filename: file name + * xmlCtxtErrIO: + * @ctxt: parser context + * @code: xmlParserErrors code + * @uri: filename or URI (optional) * - * Handle a resource access error + * If filename is empty, use the one from context input if available. + * + * Report an IO error to the parser context. */ void -xmlLoaderErr(xmlParserCtxtPtr ctxt, int code, const char *filename) +xmlCtxtErrIO(xmlParserCtxtPtr ctxt, int code, const char *uri) { + const char *errstr, *msg, *str1, *str2; xmlErrorLevel level; unsigned idx = 0; - if (ctxt->validate) - level = XML_ERR_ERROR; - else - level = XML_ERR_WARNING; + if (ctxt == NULL) + return; + + if ((code == XML_IO_ENOENT) || + (code == XML_IO_NETWORK_ATTEMPT) || + (code == XML_IO_UNKNOWN)) { + if (ctxt->validate == 0) + level = XML_ERR_WARNING; + else + level = XML_ERR_ERROR; + } else { + level = XML_ERR_FATAL; + } if (code >= XML_IO_UNKNOWN) { idx = code - XML_IO_UNKNOWN; if (idx >= (sizeof(IOerr) / sizeof(IOerr[0]))) idx = 0; } + errstr = IOerr[idx]; + if (uri == NULL) { + msg = "%s\n"; + str1 = errstr; + str2 = NULL; + } else { + msg = "failed to load \"%s\": %s\n"; + str1 = uri; + str2 = errstr; + } + + /* + * TODO: Set filename in error + */ xmlErrParser(ctxt, NULL, XML_FROM_IO, code, level, - (const xmlChar *) filename, NULL, NULL, 0, - "failed to load \"%s\": %s\n", filename, IOerr[idx]); + (const xmlChar *) uri, NULL, NULL, 0, + msg, str1, str2); } /************************************************************************ @@ -787,7 +813,8 @@ xmlFdRead (void * context, char * buffer, int len) { int ret; ret = read((int) (ptrdiff_t) context, &buffer[0], len); - if (ret < 0) xmlIOErr(0, "read()"); + if (ret < 0) + return(-xmlIOErr(0, "fread()")); return(ret); } @@ -1028,7 +1055,8 @@ xmlFileRead (void * context, char * buffer, int len) { if ((context == NULL) || (buffer == NULL)) return(-1); ret = fread(&buffer[0], 1, len, (FILE *) context); - if (ret < 0) xmlIOErr(0, "fread()"); + if (ret < 0) + return(-xmlIOErr(0, "fread()")); return(ret); } @@ -3410,7 +3438,10 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) { if (res <= 0) in->readcallback = endOfInput; if (res < 0) { - in->error = XML_IO_UNKNOWN; + if (res == -1) + in->error = XML_IO_UNKNOWN; + else + in->error = -res; return(-1); } @@ -3926,9 +3957,9 @@ xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { if (code >= 400) { /* fatal error */ if (ret->filename != NULL) - xmlLoaderErr(ctxt, XML_IO_LOAD_ERROR, ret->filename); + xmlCtxtErrIO(ctxt, XML_IO_LOAD_ERROR, ret->filename); else - xmlLoaderErr(ctxt, XML_IO_LOAD_ERROR, ""); + xmlCtxtErrIO(ctxt, XML_IO_LOAD_ERROR, ""); xmlFreeInputStream(ret); ret = NULL; } else { @@ -4193,7 +4224,7 @@ xmlNoNetExternalEntityLoader(const char *URL, const char *ID, if (resource != NULL) { if ((!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "ftp://", 6)) || (!xmlStrncasecmp(BAD_CAST resource, BAD_CAST "http://", 7))) { - xmlLoaderErr(ctxt, XML_IO_NETWORK_ATTEMPT, + xmlCtxtErrIO(ctxt, XML_IO_NETWORK_ATTEMPT, (const char *) resource); if (resource != (xmlChar *) URL) xmlFree(resource); diff --git a/xmlreader.c b/xmlreader.c index c86af0b5..fbc7296a 100644 --- a/xmlreader.c +++ b/xmlreader.c @@ -742,7 +742,7 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) { break; } } else if (val < 0) { - xmlFatalErr(reader->ctxt, reader->input->error, NULL); + xmlCtxtErrIO(reader->ctxt, reader->input->error, NULL); reader->mode = XML_TEXTREADER_MODE_ERROR; reader->state = XML_TEXTREADER_ERROR; return(-1);