1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-24 13:33:01 +03:00

html: Report malloc failures

Fix many places where malloc failures aren't reported.

Stop checking for ctxt->instate.
This commit is contained in:
Nick Wellnhofer
2023-12-10 19:07:32 +01:00
parent e115194e6f
commit abd74186f9
4 changed files with 273 additions and 483 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -384,6 +384,32 @@ htmlSaveErr(int code, xmlNodePtr node, const char *extra)
* * * *
************************************************************************/ ************************************************************************/
static xmlCharEncodingHandler *
htmlFindOutputEncoder(const char *encoding) {
xmlCharEncodingHandler *handler = NULL;
if (encoding != NULL) {
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
} else {
/*
* Fallback to HTML or ASCII when the encoding is unspecified
*/
if (handler == NULL)
handler = xmlFindCharEncodingHandler("HTML");
if (handler == NULL)
handler = xmlFindCharEncodingHandler("ascii");
}
return(handler);
}
/** /**
* htmlBufNodeDumpFormat: * htmlBufNodeDumpFormat:
* @buf: the xmlBufPtr output * @buf: the xmlBufPtr output
@@ -479,33 +505,15 @@ int
htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc, htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc,
xmlNodePtr cur, const char *encoding, int format) { xmlNodePtr cur, const char *encoding, int format) {
xmlOutputBufferPtr buf; xmlOutputBufferPtr buf;
xmlCharEncodingHandlerPtr handler = NULL; xmlCharEncodingHandlerPtr handler;
int ret; int ret;
xmlInitParser(); xmlInitParser();
if (encoding != NULL) {
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
} else {
/*
* Fallback to HTML or ASCII when the encoding is unspecified
*/
if (handler == NULL)
handler = xmlFindCharEncodingHandler("HTML");
if (handler == NULL)
handler = xmlFindCharEncodingHandler("ascii");
}
/* /*
* save the content to a temp buffer. * save the content to a temp buffer.
*/ */
handler = htmlFindOutputEncoder(encoding);
buf = xmlOutputBufferCreateFile(out, handler); buf = xmlOutputBufferCreateFile(out, handler);
if (buf == NULL) return(0); if (buf == NULL) return(0);
@@ -556,27 +564,7 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
} }
encoding = (const char *) htmlGetMetaEncoding(cur); encoding = (const char *) htmlGetMetaEncoding(cur);
handler = htmlFindOutputEncoder(encoding);
if (encoding != NULL) {
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
} else {
/*
* Fallback to HTML or ASCII when the encoding is unspecified
*/
if (handler == NULL)
handler = xmlFindCharEncodingHandler("HTML");
if (handler == NULL)
handler = xmlFindCharEncodingHandler("ascii");
}
buf = xmlAllocOutputBufferInternal(handler); buf = xmlAllocOutputBufferInternal(handler);
if (buf == NULL) { if (buf == NULL) {
*mem = NULL; *mem = NULL;
@@ -712,14 +700,14 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
xmlBufWriteQuotedString(buf->buffer, escaped); xmlBufWriteQuotedString(buf->buffer, escaped);
xmlFree(escaped); xmlFree(escaped);
} else { } else {
xmlBufWriteQuotedString(buf->buffer, value); buf->error = XML_ERR_NO_MEMORY;
} }
} else { } else {
xmlBufWriteQuotedString(buf->buffer, value); xmlBufWriteQuotedString(buf->buffer, value);
} }
xmlFree(value); xmlFree(value);
} else { } else {
xmlOutputBufferWriteString(buf, "=\"\""); buf->error = XML_ERR_NO_MEMORY;
} }
} }
} }
@@ -860,10 +848,12 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
xmlChar *buffer; xmlChar *buffer;
buffer = xmlEncodeEntitiesReentrant(doc, cur->content); buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
if (buffer != NULL) { if (buffer == NULL) {
xmlOutputBufferWriteString(buf, (const char *)buffer); buf->error = XML_ERR_NO_MEMORY;
xmlFree(buffer); return;
} }
xmlOutputBufferWriteString(buf, (const char *)buffer);
xmlFree(buffer);
} else { } else {
xmlOutputBufferWriteString(buf, (const char *)cur->content); xmlOutputBufferWriteString(buf, (const char *)cur->content);
} }
@@ -1039,26 +1029,7 @@ htmlDocDump(FILE *f, xmlDocPtr cur) {
} }
encoding = (const char *) htmlGetMetaEncoding(cur); encoding = (const char *) htmlGetMetaEncoding(cur);
handler = htmlFindOutputEncoder(encoding);
if (encoding != NULL) {
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
} else {
/*
* Fallback to HTML or ASCII when the encoding is unspecified
*/
if (handler == NULL)
handler = xmlFindCharEncodingHandler("HTML");
if (handler == NULL)
handler = xmlFindCharEncodingHandler("ascii");
}
buf = xmlOutputBufferCreateFile(f, handler); buf = xmlOutputBufferCreateFile(f, handler);
if (buf == NULL) return(-1); if (buf == NULL) return(-1);
htmlDocContentDumpOutput(buf, cur, NULL); htmlDocContentDumpOutput(buf, cur, NULL);
@@ -1089,29 +1060,7 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) {
xmlInitParser(); xmlInitParser();
encoding = (const char *) htmlGetMetaEncoding(cur); encoding = (const char *) htmlGetMetaEncoding(cur);
handler = htmlFindOutputEncoder(encoding);
if (encoding != NULL) {
xmlCharEncoding enc;
enc = xmlParseCharEncoding(encoding);
if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
} else {
/*
* Fallback to HTML or ASCII when the encoding is unspecified
*/
if (handler == NULL)
handler = xmlFindCharEncodingHandler("HTML");
if (handler == NULL)
handler = xmlFindCharEncodingHandler("ascii");
}
/*
* save the content to a temp buffer.
*/
buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression); buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
if (buf == NULL) return(0); if (buf == NULL) return(0);
@@ -1144,28 +1093,12 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur,
xmlInitParser(); xmlInitParser();
if (encoding != NULL) { handler = htmlFindOutputEncoder(encoding);
xmlCharEncoding enc; if (handler != NULL)
htmlSetMetaEncoding(cur, (const xmlChar *) handler->name);
enc = xmlParseCharEncoding(encoding); else
if (enc != XML_CHAR_ENCODING_UTF8) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
} else {
htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8"); htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8");
/*
* Fallback to HTML or ASCII when the encoding is unspecified
*/
if (handler == NULL)
handler = xmlFindCharEncodingHandler("HTML");
if (handler == NULL)
handler = xmlFindCharEncodingHandler("ascii");
}
/* /*
* save the content to a temp buffer. * save the content to a temp buffer.
*/ */

46
error.c
View File

@@ -25,8 +25,6 @@
#endif #endif
#endif #endif
#define XML_MAX_ERRORS 100
#define XML_GET_VAR_STR(msg, str) \ #define XML_GET_VAR_STR(msg, str) \
do { \ do { \
va_list ap; \ va_list ap; \
@@ -500,8 +498,6 @@ xmlVRaiseError(xmlStructuredErrorFunc schannel,
xmlParserCtxtPtr ctxt = NULL; xmlParserCtxtPtr ctxt = NULL;
xmlNodePtr node = (xmlNodePtr) nod; xmlNodePtr node = (xmlNodePtr) nod;
char *str = NULL; char *str = NULL;
xmlParserInputPtr input = NULL;
/* xmlLastError is a macro retrieving the per-thread global. */ /* xmlLastError is a macro retrieving the per-thread global. */
xmlErrorPtr lastError = &xmlLastError; xmlErrorPtr lastError = &xmlLastError;
xmlErrorPtr to = lastError; xmlErrorPtr to = lastError;
@@ -515,25 +511,6 @@ xmlVRaiseError(xmlStructuredErrorFunc schannel,
(domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
ctxt = (xmlParserCtxtPtr) ctx; ctxt = (xmlParserCtxtPtr) ctx;
if (ctxt != NULL) {
if (level == XML_ERR_WARNING) {
if (ctxt->nbWarnings >= XML_MAX_ERRORS)
return(0);
ctxt->nbWarnings += 1;
} else {
if (ctxt->nbErrors >= XML_MAX_ERRORS)
return(0);
ctxt->nbErrors += 1;
}
if ((schannel == NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->initialized == XML_SAX2_MAGIC) &&
(ctxt->sax->serror != NULL)) {
schannel = ctxt->sax->serror;
data = ctxt->userData;
}
}
} }
/* /*
* Check if structured error handler set * Check if structured error handler set
@@ -560,18 +537,10 @@ xmlVRaiseError(xmlStructuredErrorFunc schannel,
/* /*
* specific processing if a parser context is provided * specific processing if a parser context is provided
*/ */
if ((ctxt != NULL) && (ctxt->input != NULL)) { if (ctxt != NULL)
if (file == NULL) {
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;
}
to = &ctxt->lastError; to = &ctxt->lastError;
} else if ((node != NULL) && (file == NULL)) {
if ((node != NULL) && (file == NULL)) {
int i; int i;
if ((node->doc != NULL) && (node->doc->URL != NULL)) { if ((node->doc != NULL) && (node->doc->URL != NULL)) {
@@ -678,14 +647,7 @@ xmlVRaiseError(xmlStructuredErrorFunc schannel,
/* /*
* Find the callback channel if channel param is NULL * Find the callback channel if channel param is NULL
*/ */
if ((ctxt != NULL) && (channel == NULL) && if ((ctxt == NULL) && (channel == NULL)) {
(xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
if (level == XML_ERR_WARNING)
channel = ctxt->sax->warning;
else
channel = ctxt->sax->error;
data = ctxt->userData;
} else if (channel == NULL) {
channel = xmlGenericError; channel = xmlGenericError;
data = xmlGenericErrorContext; data = xmlGenericErrorContext;
} }

View File

@@ -24,6 +24,7 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
int int
LLVMFuzzerTestOneInput(const char *data, size_t size) { LLVMFuzzerTestOneInput(const char *data, size_t size) {
xmlParserCtxtPtr ctxt;
htmlDocPtr doc; htmlDocPtr doc;
const char *docBuffer; const char *docBuffer;
size_t maxAlloc, docSize; size_t maxAlloc, docSize;
@@ -31,7 +32,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
xmlFuzzDataInit(data, size); xmlFuzzDataInit(data, size);
opts = (int) xmlFuzzReadInt(4); opts = (int) xmlFuzzReadInt(4);
maxAlloc = xmlFuzzReadInt(4) % (size + 1); maxAlloc = xmlFuzzReadInt(4) % (size + 100);
docBuffer = xmlFuzzReadRemaining(&docSize); docBuffer = xmlFuzzReadRemaining(&docSize);
if (docBuffer == NULL) { if (docBuffer == NULL) {
@@ -42,31 +43,50 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
/* Pull parser */ /* Pull parser */
xmlFuzzMemSetLimit(maxAlloc); xmlFuzzMemSetLimit(maxAlloc);
doc = htmlReadMemory(docBuffer, docSize, NULL, NULL, opts); ctxt = htmlNewParserCtxt();
if (ctxt != NULL) {
doc = htmlCtxtReadMemory(ctxt, docBuffer, docSize, NULL, NULL, opts);
xmlFuzzCheckMallocFailure("htmlCtxtReadMemory",
ctxt->errNo == XML_ERR_NO_MEMORY);
if (doc != NULL) {
xmlDocPtr copy;
#ifdef LIBXML_OUTPUT_ENABLED #ifdef LIBXML_OUTPUT_ENABLED
{ xmlOutputBufferPtr out;
xmlOutputBufferPtr out; const xmlChar *content;
/* /*
* Also test the serializer. Call htmlDocContentDumpOutput with our * Also test the serializer. Call htmlDocContentDumpOutput with our
* own buffer to avoid encoding the output. The HTML encoding is * own buffer to avoid encoding the output. The HTML encoding is
* excruciatingly slow (see htmlEntityValueLookup). * excruciatingly slow (see htmlEntityValueLookup).
*/ */
out = xmlAllocOutputBuffer(NULL); xmlFuzzResetMallocFailed();
htmlDocContentDumpOutput(out, doc, NULL); out = xmlAllocOutputBuffer(NULL);
xmlOutputBufferClose(out); htmlDocContentDumpOutput(out, doc, NULL);
} content = xmlOutputBufferGetContent(out);
xmlFuzzCheckMallocFailure("htmlDocContentDumpOutput",
content == NULL);
xmlOutputBufferClose(out);
#endif #endif
xmlFreeDoc(doc); xmlFuzzResetMallocFailed();
copy = xmlCopyDoc(doc, 1);
xmlFuzzCheckMallocFailure("xmlCopyNode", copy == NULL);
xmlFreeDoc(copy);
xmlFreeDoc(doc);
}
htmlFreeParserCtxt(ctxt);
}
/* Push parser */ /* Push parser */
#ifdef LIBXML_PUSH_ENABLED #ifdef LIBXML_PUSH_ENABLED
{ {
static const size_t maxChunkSize = 128; static const size_t maxChunkSize = 128;
xmlParserCtxtPtr ctxt;
size_t consumed, chunkSize; size_t consumed, chunkSize;
xmlFuzzMemSetLimit(maxAlloc); xmlFuzzMemSetLimit(maxAlloc);
@@ -84,6 +104,8 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
} }
htmlParseChunk(ctxt, NULL, 0, 1); htmlParseChunk(ctxt, NULL, 0, 1);
xmlFuzzCheckMallocFailure("htmlParseChunk",
ctxt->errNo == XML_ERR_NO_MEMORY);
xmlFreeDoc(ctxt->myDoc); xmlFreeDoc(ctxt->myDoc);
htmlFreeParserCtxt(ctxt); htmlFreeParserCtxt(ctxt);
} }