mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-24 13:33:01 +03:00
parser: Report malloc failures
Fix many places where malloc failures aren't reported. Make xmlErrMemory public. This is useful for custom external entity loaders. Introduce new API function xmlSwitchEncodingName. Change the way how we store whether the the parser is stopped. This used to be signaled by setting ctxt->instate to XML_PARSER_EOF which was misdesigned and error-prone. Set ctxt->disableSAX to 2 instead and introduce a macro PARSER_STOPPED. Also stop to remove parser inputs in xmlHaltParser. This allows to remove many checks of ctxt->instate. Introduce xmlErrParser to handle errors if a parser context is available.
This commit is contained in:
@@ -45,6 +45,8 @@
|
||||
#include "private/io.h"
|
||||
#include "private/parser.h"
|
||||
|
||||
#define XML_MAX_ERRORS 100
|
||||
|
||||
/*
|
||||
* XML_MAX_AMPLIFICATION_DEFAULT is the default maximum allowed amplification
|
||||
* factor of serialized output after entity expansion.
|
||||
@@ -99,25 +101,138 @@ xmlCheckVersion(int version) {
|
||||
* Handle a redefinition of attribute error
|
||||
*/
|
||||
void
|
||||
xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra)
|
||||
xmlErrMemory(xmlParserCtxtPtr ctxt, const char *extra ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
|
||||
(ctxt->instate == XML_PARSER_EOF))
|
||||
return;
|
||||
if (ctxt != NULL) {
|
||||
ctxt->errNo = XML_ERR_NO_MEMORY;
|
||||
ctxt->instate = XML_PARSER_EOF;
|
||||
ctxt->disableSAX = 1;
|
||||
xmlError *lastError = &xmlLastError;
|
||||
|
||||
xmlResetLastError();
|
||||
lastError->domain = XML_FROM_PARSER;
|
||||
lastError->code = XML_ERR_NO_MEMORY;
|
||||
lastError->level = XML_ERR_FATAL;
|
||||
|
||||
ctxt->errNo = XML_ERR_NO_MEMORY;
|
||||
ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */
|
||||
ctxt->wellFormed = 0;
|
||||
ctxt->disableSAX = 2;
|
||||
|
||||
xmlResetError(&ctxt->lastError);
|
||||
ctxt->lastError.domain = XML_FROM_PARSER;
|
||||
ctxt->lastError.code = XML_ERR_NO_MEMORY;
|
||||
ctxt->lastError.level = XML_ERR_FATAL;
|
||||
|
||||
if ((ctxt->sax->initialized == XML_SAX2_MAGIC) &&
|
||||
(ctxt->sax->serror != NULL)) {
|
||||
ctxt->sax->serror(ctxt->userData, &ctxt->lastError);
|
||||
} else if (xmlStructuredError != NULL) {
|
||||
xmlStructuredError(ctxt->userData, &ctxt->lastError);
|
||||
} else {
|
||||
xmlGenericErrorFunc channel = ctxt->sax->error;
|
||||
|
||||
if ((channel == xmlParserError) ||
|
||||
(channel == xmlParserWarning) ||
|
||||
(channel == xmlParserValidityError) ||
|
||||
(channel == xmlParserValidityWarning))
|
||||
channel = xmlGenericError;
|
||||
|
||||
if (channel != NULL)
|
||||
channel(ctxt->userData, "parser error : out of memory\n");
|
||||
}
|
||||
if (extra)
|
||||
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
|
||||
XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
|
||||
NULL, NULL, 0, 0,
|
||||
"Memory allocation failed : %s\n", extra);
|
||||
else
|
||||
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
|
||||
XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
|
||||
NULL, NULL, 0, 0, "Memory allocation failed\n");
|
||||
}
|
||||
|
||||
void
|
||||
xmlVErrParser(xmlParserCtxtPtr ctxt, xmlNodePtr node,
|
||||
int domain, int code, xmlErrorLevel level,
|
||||
const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
|
||||
int int1, const char *msg, va_list ap)
|
||||
{
|
||||
xmlStructuredErrorFunc schannel = NULL;
|
||||
xmlGenericErrorFunc channel;
|
||||
void *data;
|
||||
const char *file = NULL;
|
||||
int line = 0;
|
||||
int col = 0;
|
||||
int res;
|
||||
|
||||
if (PARSER_STOPPED(ctxt))
|
||||
return;
|
||||
|
||||
if (code == XML_ERR_NO_MEMORY) {
|
||||
xmlErrMemory(ctxt, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (level == XML_ERR_WARNING) {
|
||||
if (ctxt->nbWarnings >= XML_MAX_ERRORS)
|
||||
return;
|
||||
ctxt->nbWarnings += 1;
|
||||
} else {
|
||||
if (ctxt->nbErrors >= XML_MAX_ERRORS)
|
||||
return;
|
||||
ctxt->nbErrors += 1;
|
||||
}
|
||||
|
||||
if (ctxt->sax->initialized == XML_SAX2_MAGIC)
|
||||
schannel = ctxt->sax->serror;
|
||||
|
||||
if ((domain == XML_FROM_VALID) || (domain == XML_FROM_DTD)) {
|
||||
if (level == XML_ERR_WARNING)
|
||||
channel = ctxt->vctxt.warning;
|
||||
else
|
||||
channel = ctxt->vctxt.error;
|
||||
data = ctxt->vctxt.userData;
|
||||
} else {
|
||||
if (level == XML_ERR_WARNING)
|
||||
channel = ctxt->sax->warning;
|
||||
else
|
||||
channel = ctxt->sax->error;
|
||||
data = ctxt->userData;
|
||||
}
|
||||
|
||||
if (ctxt->input != NULL) {
|
||||
xmlParserInputPtr input = ctxt->input;
|
||||
|
||||
if ((input->filename == NULL) &&
|
||||
(ctxt->inputNr > 1)) {
|
||||
input = ctxt->inputTab[ctxt->inputNr - 2];
|
||||
}
|
||||
file = input->filename;
|
||||
line = input->line;
|
||||
col = input->col;
|
||||
}
|
||||
|
||||
res = xmlVRaiseError(schannel, channel, data, ctxt, node, domain, code,
|
||||
level, file, line, (const char *) str1,
|
||||
(const char *) str2, (const char *) str3, int1, col,
|
||||
msg, ap);
|
||||
|
||||
if (res < 0) {
|
||||
xmlErrMemory(ctxt, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (level >= XML_ERR_ERROR)
|
||||
ctxt->errNo = code;
|
||||
if (level == XML_ERR_FATAL) {
|
||||
ctxt->wellFormed = 0;
|
||||
if (ctxt->recovery == 0)
|
||||
ctxt->disableSAX = 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
xmlErrParser(xmlParserCtxtPtr ctxt, xmlNodePtr node,
|
||||
int domain, int code, xmlErrorLevel level,
|
||||
const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
|
||||
int int1, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
xmlVErrParser(ctxt, node, domain, code, level,
|
||||
str1, str2, str3, int1, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,20 +249,8 @@ void
|
||||
__xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr,
|
||||
const char *msg, const xmlChar * str1, const xmlChar * str2)
|
||||
{
|
||||
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
|
||||
(ctxt->instate == XML_PARSER_EOF))
|
||||
return;
|
||||
if (ctxt != NULL)
|
||||
ctxt->errNo = xmlerr;
|
||||
__xmlRaiseError(NULL, NULL, NULL,
|
||||
ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL,
|
||||
NULL, 0, (const char *) str1, (const char *) str2,
|
||||
NULL, 0, 0, msg, str1, str2);
|
||||
if (ctxt != NULL) {
|
||||
ctxt->wellFormed = 0;
|
||||
if (ctxt->recovery == 0)
|
||||
ctxt->disableSAX = 1;
|
||||
}
|
||||
xmlErrParser(ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL,
|
||||
str1, str2, NULL, 0, msg, str1, str2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,20 +264,10 @@ __xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr,
|
||||
static void LIBXML_ATTR_FORMAT(2,0)
|
||||
xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str)
|
||||
{
|
||||
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
|
||||
(ctxt->instate == XML_PARSER_EOF))
|
||||
return;
|
||||
if (ctxt != NULL)
|
||||
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
|
||||
__xmlRaiseError(NULL, NULL, NULL,
|
||||
ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR,
|
||||
XML_ERR_FATAL, NULL, 0, (const char *) str, NULL, NULL,
|
||||
0, 0, msg, str);
|
||||
if (ctxt != NULL) {
|
||||
ctxt->wellFormed = 0;
|
||||
if (ctxt->recovery == 0)
|
||||
ctxt->disableSAX = 1;
|
||||
}
|
||||
if (ctxt == NULL)
|
||||
return;
|
||||
xmlErrParser(ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR,
|
||||
XML_ERR_FATAL, str, NULL, NULL, 0, msg, str);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,9 +283,6 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
|
||||
{
|
||||
const char *errmsg;
|
||||
|
||||
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
|
||||
(ctxt->instate == XML_PARSER_EOF))
|
||||
return;
|
||||
switch (error) {
|
||||
case XML_ERR_INVALID_HEX_CHARREF:
|
||||
errmsg = "CharRef: invalid hexadecimal value";
|
||||
@@ -393,21 +483,14 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
|
||||
default:
|
||||
errmsg = "Unregistered error message";
|
||||
}
|
||||
if (ctxt != NULL)
|
||||
ctxt->errNo = error;
|
||||
|
||||
if (info == NULL) {
|
||||
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
|
||||
XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
|
||||
errmsg);
|
||||
xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
|
||||
NULL, NULL, NULL, 0, "%s\n", errmsg);
|
||||
} else {
|
||||
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
|
||||
XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
|
||||
errmsg, info);
|
||||
}
|
||||
if (ctxt != NULL) {
|
||||
ctxt->wellFormed = 0;
|
||||
if (ctxt->recovery == 0)
|
||||
ctxt->disableSAX = 1;
|
||||
xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
|
||||
(const xmlChar *) info, NULL, NULL, 0,
|
||||
"%s: %s\n", errmsg, info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,19 +507,8 @@ static void LIBXML_ATTR_FORMAT(3,0)
|
||||
xmlErrEncodingInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
|
||||
const char *msg, int val)
|
||||
{
|
||||
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
|
||||
(ctxt->instate == XML_PARSER_EOF))
|
||||
return;
|
||||
if (ctxt != NULL)
|
||||
ctxt->errNo = error;
|
||||
__xmlRaiseError(NULL, NULL, NULL,
|
||||
ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
|
||||
NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
|
||||
if (ctxt != NULL) {
|
||||
ctxt->wellFormed = 0;
|
||||
if (ctxt->recovery == 0)
|
||||
ctxt->disableSAX = 1;
|
||||
}
|
||||
xmlErrParser(ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
|
||||
NULL, NULL, NULL, val, msg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -473,28 +545,8 @@ void
|
||||
xmlHaltParser(xmlParserCtxtPtr ctxt) {
|
||||
if (ctxt == NULL)
|
||||
return;
|
||||
ctxt->instate = XML_PARSER_EOF;
|
||||
ctxt->disableSAX = 1;
|
||||
while (ctxt->inputNr > 1)
|
||||
xmlFreeInputStream(inputPop(ctxt));
|
||||
if (ctxt->input != NULL) {
|
||||
/*
|
||||
* in case there was a specific allocation deallocate before
|
||||
* overriding base
|
||||
*/
|
||||
if (ctxt->input->free != NULL) {
|
||||
ctxt->input->free((xmlChar *) ctxt->input->base);
|
||||
ctxt->input->free = NULL;
|
||||
}
|
||||
if (ctxt->input->buf != NULL) {
|
||||
xmlFreeParserInputBuffer(ctxt->input->buf);
|
||||
ctxt->input->buf = NULL;
|
||||
}
|
||||
ctxt->input->cur = BAD_CAST"";
|
||||
ctxt->input->length = 0;
|
||||
ctxt->input->base = ctxt->input->cur;
|
||||
ctxt->input->end = ctxt->input->cur;
|
||||
}
|
||||
ctxt->instate = XML_PARSER_EOF; /* TODO: Remove after refactoring */
|
||||
ctxt->disableSAX = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,7 +590,8 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) {
|
||||
if (((curEnd > XML_MAX_LOOKUP_LIMIT) ||
|
||||
(curBase > XML_MAX_LOOKUP_LIMIT)) &&
|
||||
((ctxt->options & XML_PARSE_HUGE) == 0)) {
|
||||
xmlErrMemory(ctxt, "Huge input lookup");
|
||||
xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
|
||||
"Buffer size limit exceeded, try XML_PARSE_HUGE\n");
|
||||
xmlHaltParser(ctxt);
|
||||
return(-1);
|
||||
}
|
||||
@@ -551,9 +604,6 @@ xmlParserGrow(xmlParserCtxtPtr ctxt) {
|
||||
|
||||
if (ret < 0) {
|
||||
xmlFatalErr(ctxt, buf->error, NULL);
|
||||
/* Buffer contents may be lost in case of memory errors. */
|
||||
if (buf->error == XML_ERR_NO_MEMORY)
|
||||
xmlHaltParser(ctxt);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
@@ -712,16 +762,14 @@ xmlNextChar(xmlParserCtxtPtr ctxt)
|
||||
size_t avail;
|
||||
int c;
|
||||
|
||||
if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) ||
|
||||
(ctxt->input == NULL))
|
||||
if ((ctxt == NULL) || (ctxt->input == NULL))
|
||||
return;
|
||||
|
||||
avail = ctxt->input->end - ctxt->input->cur;
|
||||
|
||||
if (avail < INPUT_CHUNK) {
|
||||
xmlParserGrow(ctxt);
|
||||
if ((ctxt->instate == XML_PARSER_EOF) ||
|
||||
(ctxt->input->cur >= ctxt->input->end))
|
||||
if (ctxt->input->cur >= ctxt->input->end)
|
||||
return;
|
||||
avail = ctxt->input->end - ctxt->input->cur;
|
||||
}
|
||||
@@ -836,15 +884,11 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
|
||||
int c;
|
||||
|
||||
if ((ctxt == NULL) || (len == NULL) || (ctxt->input == NULL)) return(0);
|
||||
if (ctxt->instate == XML_PARSER_EOF)
|
||||
return(0);
|
||||
|
||||
avail = ctxt->input->end - ctxt->input->cur;
|
||||
|
||||
if (avail < INPUT_CHUNK) {
|
||||
xmlParserGrow(ctxt);
|
||||
if (ctxt->instate == XML_PARSER_EOF)
|
||||
return(0);
|
||||
avail = ctxt->input->end - ctxt->input->cur;
|
||||
}
|
||||
|
||||
@@ -1070,24 +1114,30 @@ xmlCopyChar(int len ATTRIBUTE_UNUSED, xmlChar *out, int val) {
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
static xmlCharEncodingHandlerPtr
|
||||
xmlDetectEBCDIC(xmlParserInputPtr input) {
|
||||
static int
|
||||
xmlDetectEBCDIC(xmlParserInputPtr input, xmlCharEncodingHandlerPtr *hout) {
|
||||
xmlChar out[200];
|
||||
xmlCharEncodingHandlerPtr handler;
|
||||
int inlen, outlen, res, i;
|
||||
|
||||
*hout = NULL;
|
||||
|
||||
/*
|
||||
* To detect the EBCDIC code page, we convert the first 200 bytes
|
||||
* to EBCDIC-US and try to find the encoding declaration.
|
||||
*/
|
||||
handler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC);
|
||||
if (handler == NULL)
|
||||
return(NULL);
|
||||
res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler);
|
||||
if (res != 0)
|
||||
return(res);
|
||||
outlen = sizeof(out) - 1;
|
||||
inlen = input->end - input->cur;
|
||||
res = xmlEncInputChunk(handler, out, &outlen, input->cur, &inlen);
|
||||
/*
|
||||
* Return the EBCDIC handler if decoding failed. The error will
|
||||
* be reported later.
|
||||
*/
|
||||
if (res < 0)
|
||||
return(handler);
|
||||
goto done;
|
||||
out[outlen] = 0;
|
||||
|
||||
for (i = 0; i < outlen; i++) {
|
||||
@@ -1119,15 +1169,24 @@ xmlDetectEBCDIC(xmlParserInputPtr input) {
|
||||
break;
|
||||
out[i] = 0;
|
||||
xmlCharEncCloseFunc(handler);
|
||||
return(xmlFindCharEncodingHandler((char *) out + start));
|
||||
res = xmlOpenCharEncodingHandler((char *) out + start, &handler);
|
||||
if (res != 0)
|
||||
return(res);
|
||||
*hout = handler;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
/*
|
||||
* ICU handlers are stateful, so we have to recreate them.
|
||||
* Encoding handlers are stateful, so we have to recreate them.
|
||||
*/
|
||||
xmlCharEncCloseFunc(handler);
|
||||
return(xmlGetCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC));
|
||||
res = xmlLookupCharEncodingHandler(XML_CHAR_ENCODING_EBCDIC, &handler);
|
||||
if (res != 0)
|
||||
return(res);
|
||||
*hout = handler;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1135,10 +1194,11 @@ xmlDetectEBCDIC(xmlParserInputPtr input) {
|
||||
* @ctxt: the parser context
|
||||
* @enc: the encoding value (number)
|
||||
*
|
||||
* Use encoding specified by enum to decode input data.
|
||||
* Use encoding specified by enum to decode input data. This overrides
|
||||
* the encoding found in the XML declaration.
|
||||
*
|
||||
* This function can be used to enforce the encoding of chunks passed
|
||||
* to xmlParseChunk.
|
||||
* This function can also be used to override the encoding of chunks
|
||||
* passed to xmlParseChunk.
|
||||
*
|
||||
* Returns 0 in case of success, -1 otherwise
|
||||
*/
|
||||
@@ -1146,8 +1206,8 @@ int
|
||||
xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
|
||||
{
|
||||
xmlCharEncodingHandlerPtr handler = NULL;
|
||||
int check = 1;
|
||||
int ret;
|
||||
int res;
|
||||
|
||||
if ((ctxt == NULL) || (ctxt->input == NULL))
|
||||
return(-1);
|
||||
@@ -1156,28 +1216,25 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
|
||||
case XML_CHAR_ENCODING_NONE:
|
||||
case XML_CHAR_ENCODING_UTF8:
|
||||
case XML_CHAR_ENCODING_ASCII:
|
||||
check = 0;
|
||||
res = 0;
|
||||
break;
|
||||
case XML_CHAR_ENCODING_EBCDIC:
|
||||
handler = xmlDetectEBCDIC(ctxt->input);
|
||||
res = xmlDetectEBCDIC(ctxt->input, &handler);
|
||||
break;
|
||||
default:
|
||||
handler = xmlGetCharEncodingHandler(enc);
|
||||
res = xmlLookupCharEncodingHandler(enc, &handler);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((check) && (handler == NULL)) {
|
||||
const char *name = xmlGetCharEncodingName(enc);
|
||||
if (res != 0) {
|
||||
if (res == XML_ERR_UNSUPPORTED_ENCODING) {
|
||||
const char *name = xmlGetCharEncodingName(enc);
|
||||
|
||||
__xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
|
||||
"encoding not supported: %s\n",
|
||||
BAD_CAST (name ? name : "<null>"), NULL);
|
||||
/*
|
||||
* TODO: We could recover from errors in external entities
|
||||
* if we didn't stop the parser. But most callers of this
|
||||
* function don't check the return value.
|
||||
*/
|
||||
xmlStopParser(ctxt);
|
||||
__xmlErrEncoding(ctxt, res, "encoding not supported: %s\n",
|
||||
BAD_CAST (name ? name : "<null>"), NULL);
|
||||
} else {
|
||||
xmlFatalErr(ctxt, res, NULL);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
@@ -1190,6 +1247,39 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSwitchEncodingName:
|
||||
* @ctxt: the parser context
|
||||
* @encoding: the encoding name
|
||||
*
|
||||
* Use specified encoding to decode input data. This overrides the
|
||||
* encoding found in the XML declaration.
|
||||
*
|
||||
* This function can also be used to override the encoding of chunks
|
||||
* passed to xmlParseChunk.
|
||||
*
|
||||
* Available since 2.13.0.
|
||||
*
|
||||
* Returns 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int
|
||||
xmlSwitchEncodingName(xmlParserCtxtPtr ctxt, const char *encoding) {
|
||||
xmlCharEncodingHandlerPtr handler;
|
||||
int res;
|
||||
|
||||
res = xmlOpenCharEncodingHandler(encoding, &handler);
|
||||
if (res != 0) {
|
||||
if (res == XML_ERR_UNSUPPORTED_ENCODING)
|
||||
__xmlErrEncoding(ctxt, res, "Unsupported encoding: %s\n",
|
||||
(const xmlChar *) encoding, NULL);
|
||||
else
|
||||
xmlFatalErr(ctxt, res, NULL);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(xmlSwitchInputEncoding(ctxt, ctxt->input, handler));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSwitchInputEncoding:
|
||||
* @ctxt: the parser context
|
||||
@@ -1261,12 +1351,17 @@ xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
|
||||
input->consumed += processed;
|
||||
in->raw = in->buffer;
|
||||
in->buffer = xmlBufCreate();
|
||||
if (in->buffer == NULL) {
|
||||
xmlErrMemory(ctxt, NULL);
|
||||
return(-1);
|
||||
}
|
||||
in->rawconsumed = processed;
|
||||
|
||||
nbchars = xmlCharEncInput(in);
|
||||
xmlBufResetInput(in->buffer, input);
|
||||
if (nbchars < 0) {
|
||||
/* TODO: This could be an out of memory or an encoding error. */
|
||||
if (nbchars == XML_ENC_ERR_MEMORY) {
|
||||
xmlErrMemory(ctxt, NULL);
|
||||
} else if (nbchars < 0) {
|
||||
xmlErrInternal(ctxt,
|
||||
"switching encoding: encoder error\n",
|
||||
NULL);
|
||||
@@ -1412,23 +1507,9 @@ xmlDetectEncoding(xmlParserCtxtPtr ctxt) {
|
||||
*/
|
||||
void
|
||||
xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) {
|
||||
if (ctxt->encoding != NULL)
|
||||
xmlFree((xmlChar *) ctxt->encoding);
|
||||
ctxt->encoding = encoding;
|
||||
|
||||
if (((ctxt->input->flags & XML_INPUT_HAS_ENCODING) == 0) &&
|
||||
((ctxt->options & XML_PARSE_IGNORE_ENC) == 0)) {
|
||||
xmlCharEncodingHandlerPtr handler;
|
||||
|
||||
handler = xmlFindCharEncodingHandler((const char *) encoding);
|
||||
if (handler == NULL) {
|
||||
__xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
|
||||
"Unsupported encoding: %s\n",
|
||||
encoding, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
xmlSwitchToEncoding(ctxt, handler);
|
||||
xmlSwitchEncodingName(ctxt, (const char *) encoding);
|
||||
ctxt->input->flags |= XML_INPUT_USES_ENC_DECL;
|
||||
} else if (ctxt->input->flags & XML_INPUT_AUTO_ENCODING) {
|
||||
static const char *allowedUTF8[] = {
|
||||
@@ -1474,9 +1555,17 @@ xmlSetDeclaredEncoding(xmlParserCtxtPtr ctxt, xmlChar *encoding) {
|
||||
"Encoding '%s' doesn't match "
|
||||
"auto-detected '%s'\n",
|
||||
encoding, BAD_CAST autoEnc);
|
||||
xmlFree(encoding);
|
||||
encoding = xmlStrdup(BAD_CAST autoEnc);
|
||||
if (encoding == NULL)
|
||||
xmlErrMemory(ctxt, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxt->encoding != NULL)
|
||||
xmlFree((xmlChar *) ctxt->encoding);
|
||||
ctxt->encoding = encoding;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@@ -1706,12 +1795,12 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
|
||||
buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
|
||||
if (buf == NULL) {
|
||||
if (filename == NULL)
|
||||
__xmlLoaderErr(ctxt,
|
||||
"failed to load external entity: NULL filename \n",
|
||||
NULL);
|
||||
xmlLoaderErr(ctxt,
|
||||
"failed to load external entity: NULL filename\n",
|
||||
NULL);
|
||||
else
|
||||
__xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
|
||||
(const char *) filename);
|
||||
xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
|
||||
(const char *) filename);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@@ -1765,27 +1854,21 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax,
|
||||
{
|
||||
xmlParserInputPtr input;
|
||||
|
||||
if(ctxt==NULL) {
|
||||
xmlErrInternal(NULL, "Got NULL parser context\n", NULL);
|
||||
if (ctxt == NULL)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
xmlInitParser();
|
||||
|
||||
if (ctxt->dict == NULL)
|
||||
ctxt->dict = xmlDictCreate();
|
||||
if (ctxt->dict == NULL) {
|
||||
xmlErrMemory(NULL, "cannot initialize parser context\n");
|
||||
if (ctxt->dict == NULL)
|
||||
return(-1);
|
||||
}
|
||||
xmlDictSetLimit(ctxt->dict, XML_MAX_DICTIONARY_LIMIT);
|
||||
|
||||
if (ctxt->sax == NULL)
|
||||
ctxt->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
|
||||
if (ctxt->sax == NULL) {
|
||||
xmlErrMemory(NULL, "cannot initialize parser context\n");
|
||||
if (ctxt->sax == NULL)
|
||||
return(-1);
|
||||
}
|
||||
if (sax == NULL) {
|
||||
memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
|
||||
xmlSAXVersion(ctxt->sax, 2);
|
||||
@@ -1808,13 +1891,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax,
|
||||
xmlMalloc(5 * sizeof(xmlParserInputPtr));
|
||||
ctxt->inputMax = 5;
|
||||
}
|
||||
if (ctxt->inputTab == NULL) {
|
||||
xmlErrMemory(NULL, "cannot initialize parser context\n");
|
||||
ctxt->inputNr = 0;
|
||||
ctxt->inputMax = 0;
|
||||
ctxt->input = NULL;
|
||||
if (ctxt->inputTab == NULL)
|
||||
return(-1);
|
||||
}
|
||||
while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
|
||||
xmlFreeInputStream(input);
|
||||
}
|
||||
@@ -1837,16 +1915,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax,
|
||||
ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
|
||||
ctxt->nodeMax = 10;
|
||||
}
|
||||
if (ctxt->nodeTab == NULL) {
|
||||
xmlErrMemory(NULL, "cannot initialize parser context\n");
|
||||
ctxt->nodeNr = 0;
|
||||
ctxt->nodeMax = 0;
|
||||
ctxt->node = NULL;
|
||||
ctxt->inputNr = 0;
|
||||
ctxt->inputMax = 0;
|
||||
ctxt->input = NULL;
|
||||
if (ctxt->nodeTab == NULL)
|
||||
return(-1);
|
||||
}
|
||||
ctxt->nodeNr = 0;
|
||||
ctxt->node = NULL;
|
||||
|
||||
@@ -1855,19 +1925,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax,
|
||||
ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
|
||||
ctxt->nameMax = 10;
|
||||
}
|
||||
if (ctxt->nameTab == NULL) {
|
||||
xmlErrMemory(NULL, "cannot initialize parser context\n");
|
||||
ctxt->nodeNr = 0;
|
||||
ctxt->nodeMax = 0;
|
||||
ctxt->node = NULL;
|
||||
ctxt->inputNr = 0;
|
||||
ctxt->inputMax = 0;
|
||||
ctxt->input = NULL;
|
||||
ctxt->nameNr = 0;
|
||||
ctxt->nameMax = 0;
|
||||
ctxt->name = NULL;
|
||||
if (ctxt->nameTab == NULL)
|
||||
return(-1);
|
||||
}
|
||||
ctxt->nameNr = 0;
|
||||
ctxt->name = NULL;
|
||||
|
||||
@@ -1876,22 +1935,8 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax,
|
||||
ctxt->spaceTab = (int *) xmlMalloc(10 * sizeof(int));
|
||||
ctxt->spaceMax = 10;
|
||||
}
|
||||
if (ctxt->spaceTab == NULL) {
|
||||
xmlErrMemory(NULL, "cannot initialize parser context\n");
|
||||
ctxt->nodeNr = 0;
|
||||
ctxt->nodeMax = 0;
|
||||
ctxt->node = NULL;
|
||||
ctxt->inputNr = 0;
|
||||
ctxt->inputMax = 0;
|
||||
ctxt->input = NULL;
|
||||
ctxt->nameNr = 0;
|
||||
ctxt->nameMax = 0;
|
||||
ctxt->name = NULL;
|
||||
ctxt->spaceNr = 0;
|
||||
ctxt->spaceMax = 0;
|
||||
ctxt->space = NULL;
|
||||
if (ctxt->spaceTab == NULL)
|
||||
return(-1);
|
||||
}
|
||||
ctxt->spaceNr = 1;
|
||||
ctxt->spaceMax = 10;
|
||||
ctxt->spaceTab[0] = -1;
|
||||
@@ -2092,10 +2137,8 @@ xmlNewSAXParserCtxt(const xmlSAXHandler *sax, void *userData)
|
||||
xmlParserCtxtPtr ctxt;
|
||||
|
||||
ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
|
||||
if (ctxt == NULL) {
|
||||
xmlErrMemory(NULL, "cannot allocate parser context\n");
|
||||
if (ctxt == NULL)
|
||||
return(NULL);
|
||||
}
|
||||
memset(ctxt, 0, sizeof(xmlParserCtxt));
|
||||
if (xmlInitSAXParserCtxt(ctxt, sax, userData) < 0) {
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
Reference in New Issue
Block a user