1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-21 22:50:08 +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:
* @buf: the xmlBufPtr output
@ -479,33 +505,15 @@ int
htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc,
xmlNodePtr cur, const char *encoding, int format) {
xmlOutputBufferPtr buf;
xmlCharEncodingHandlerPtr handler = NULL;
xmlCharEncodingHandlerPtr handler;
int ret;
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.
*/
handler = htmlFindOutputEncoder(encoding);
buf = xmlOutputBufferCreateFile(out, handler);
if (buf == NULL) return(0);
@ -556,27 +564,7 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
}
encoding = (const char *) htmlGetMetaEncoding(cur);
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");
}
handler = htmlFindOutputEncoder(encoding);
buf = xmlAllocOutputBufferInternal(handler);
if (buf == NULL) {
*mem = NULL;
@ -712,14 +700,14 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
xmlBufWriteQuotedString(buf->buffer, escaped);
xmlFree(escaped);
} else {
xmlBufWriteQuotedString(buf->buffer, value);
buf->error = XML_ERR_NO_MEMORY;
}
} else {
xmlBufWriteQuotedString(buf->buffer, value);
}
xmlFree(value);
} else {
xmlOutputBufferWriteString(buf, "=\"\"");
buf->error = XML_ERR_NO_MEMORY;
}
}
}
@ -860,10 +848,12 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
xmlChar *buffer;
buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
if (buffer != NULL) {
xmlOutputBufferWriteString(buf, (const char *)buffer);
xmlFree(buffer);
if (buffer == NULL) {
buf->error = XML_ERR_NO_MEMORY;
return;
}
xmlOutputBufferWriteString(buf, (const char *)buffer);
xmlFree(buffer);
} else {
xmlOutputBufferWriteString(buf, (const char *)cur->content);
}
@ -1039,26 +1029,7 @@ htmlDocDump(FILE *f, xmlDocPtr cur) {
}
encoding = (const char *) htmlGetMetaEncoding(cur);
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");
}
handler = htmlFindOutputEncoder(encoding);
buf = xmlOutputBufferCreateFile(f, handler);
if (buf == NULL) return(-1);
htmlDocContentDumpOutput(buf, cur, NULL);
@ -1089,29 +1060,7 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) {
xmlInitParser();
encoding = (const char *) htmlGetMetaEncoding(cur);
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.
*/
handler = htmlFindOutputEncoder(encoding);
buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
if (buf == NULL) return(0);
@ -1144,28 +1093,12 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur,
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);
}
htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
} else {
handler = htmlFindOutputEncoder(encoding);
if (handler != NULL)
htmlSetMetaEncoding(cur, (const xmlChar *) handler->name);
else
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.
*/

46
error.c
View File

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

View File

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