1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-21 22:50:08 +03:00

save: Report malloc failures

Fix places where malloc failures aren't report.

Introduce a new API function xmlSaveFinish which returns an error code.
This commit is contained in:
Nick Wellnhofer 2023-12-10 17:14:57 +01:00
parent 1a354d5b30
commit 0d97e43993
2 changed files with 89 additions and 58 deletions

View File

@ -73,6 +73,8 @@ XMLPUBFUN int
xmlSaveFlush (xmlSaveCtxtPtr ctxt);
XMLPUBFUN int
xmlSaveClose (xmlSaveCtxtPtr ctxt);
XMLPUBFUN int
xmlSaveFinish (xmlSaveCtxtPtr ctxt);
XMLPUBFUN int
xmlSaveSetEscape (xmlSaveCtxtPtr ctxt,
xmlCharEncodingOutputFunc escape);

145
xmlsave.c
View File

@ -422,19 +422,17 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
* This will dump the content of the notation table as an XML DTD definition
*/
static void
xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
xmlBufDumpNotationTable(xmlOutputBufferPtr stream, xmlNotationTablePtr table) {
xmlBufferPtr buffer;
buffer = xmlBufferCreate();
if (buffer == NULL) {
/*
* TODO set the error in buf
*/
stream->error = XML_ERR_NO_MEMORY;
return;
}
xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
xmlDumpNotationTable(buffer, table);
xmlBufMergeBuffer(buf, buffer);
xmlBufMergeBuffer(stream->buffer, buffer);
}
/**
@ -446,19 +444,17 @@ xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
* DTD definition
*/
static void
xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) {
xmlBufDumpElementDecl(xmlOutputBufferPtr stream, xmlElementPtr elem) {
xmlBufferPtr buffer;
buffer = xmlBufferCreate();
if (buffer == NULL) {
/*
* TODO set the error in buf
*/
stream->error = XML_ERR_NO_MEMORY;
return;
}
xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
xmlDumpElementDecl(buffer, elem);
xmlBufMergeBuffer(buf, buffer);
xmlBufMergeBuffer(stream->buffer, buffer);
}
/**
@ -470,19 +466,17 @@ xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) {
* DTD definition
*/
static void
xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
xmlBufDumpAttributeDecl(xmlOutputBufferPtr stream, xmlAttributePtr attr) {
xmlBufferPtr buffer;
buffer = xmlBufferCreate();
if (buffer == NULL) {
/*
* TODO set the error in buf
*/
stream->error = XML_ERR_NO_MEMORY;
return;
}
xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
xmlDumpAttributeDecl(buffer, attr);
xmlBufMergeBuffer(buf, buffer);
xmlBufMergeBuffer(stream->buffer, buffer);
}
/**
@ -493,19 +487,17 @@ xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
* This will dump the content of the entity table as an XML DTD definition
*/
static void
xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent) {
xmlBufDumpEntityDecl(xmlOutputBufferPtr stream, xmlEntityPtr ent) {
xmlBufferPtr buffer;
buffer = xmlBufferCreate();
if (buffer == NULL) {
/*
* TODO set the error in buf
*/
stream->error = XML_ERR_NO_MEMORY;
return;
}
xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
xmlDumpEntityDecl(buffer, ent);
xmlBufMergeBuffer(buf, buffer);
xmlBufMergeBuffer(stream->buffer, buffer);
}
/************************************************************************
@ -518,18 +510,21 @@ static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
xmlOutputBufferPtr buf = ctxt->buf;
if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
if (buf->encoder == NULL) {
xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
(const char *)encoding);
return(-1);
}
xmlCharEncodingHandler *handler;
int res;
res = xmlOpenCharEncodingHandler((const char *) encoding, &handler);
if (res != 0) {
buf->error = res;
return(-1);
}
buf->conv = xmlBufCreate();
if (buf->conv == NULL) {
xmlCharEncCloseFunc(buf->encoder);
xmlSaveErrMemory("creating encoding buffer");
xmlCharEncCloseFunc(handler);
buf->error = XML_ERR_NO_MEMORY;
return(-1);
}
buf->encoder = handler;
/*
* initialize the state, e.g. if outputting a BOM
*/
@ -696,8 +691,7 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
*/
if ((dtd->notations != NULL) && ((dtd->doc == NULL) ||
(dtd->doc->intSubset == dtd))) {
xmlBufDumpNotationTable(buf->buffer,
(xmlNotationTablePtr) dtd->notations);
xmlBufDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
}
format = ctxt->format;
level = ctxt->level;
@ -735,7 +729,16 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
}
xmlOutputBufferWriteString(buf, (const char *)cur->name);
xmlOutputBufferWrite(buf, 2, "=\"");
xmlAttrSerializeContent(buf, cur);
if ((ctxt->options & XML_SAVE_XHTML) &&
(cur->ns == NULL) &&
((cur->children == NULL) ||
(cur->children->content == NULL) ||
(cur->children->content[0] == 0)) &&
(htmlIsBooleanAttr(cur->name))) {
xmlOutputBufferWriteString(buf, (const char *) cur->name);
} else {
xmlAttrSerializeContent(buf, cur);
}
xmlOutputBufferWrite(buf, 1, "\"");
}
@ -839,15 +842,15 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
break;
case XML_ELEMENT_DECL:
xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
xmlBufDumpElementDecl(buf, (xmlElementPtr) cur);
break;
case XML_ATTRIBUTE_DECL:
xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
xmlBufDumpAttributeDecl(buf, (xmlAttributePtr) cur);
break;
case XML_ENTITY_DECL:
xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
xmlBufDumpEntityDecl(buf, (xmlEntityPtr) cur);
break;
case XML_ELEMENT_NODE:
@ -1329,17 +1332,6 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
(xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
xml_lang = cur;
else if ((cur->ns == NULL) &&
((cur->children == NULL) ||
(cur->children->content == NULL) ||
(cur->children->content[0] == 0)) &&
(htmlIsBooleanAttr(cur->name))) {
if (cur->children != NULL)
xmlFreeNode(cur->children);
cur->children = xmlNewDocText(cur->doc, cur->name);
if (cur->children != NULL)
cur->children->parent = (xmlNodePtr) cur;
}
xmlAttrDumpOutput(ctxt, cur);
cur = cur->next;
}
@ -1390,13 +1382,16 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
*/
static void
xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
int format = ctxt->format, addmeta;
int format = ctxt->format, addmeta, oldoptions;
xmlNodePtr tmp, root, unformattedNode = NULL;
xmlChar *start, *end;
xmlOutputBufferPtr buf = ctxt->buf;
if (cur == NULL) return;
oldoptions = ctxt->options;
ctxt->options |= XML_SAVE_XHTML;
root = cur;
while (1) {
switch (cur->type) {
@ -1421,15 +1416,15 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
break;
case XML_ELEMENT_DECL:
xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
xmlBufDumpElementDecl(buf, (xmlElementPtr) cur);
break;
case XML_ATTRIBUTE_DECL:
xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
xmlBufDumpAttributeDecl(buf, (xmlAttributePtr) cur);
break;
case XML_ENTITY_DECL:
xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
xmlBufDumpEntityDecl(buf, (xmlEntityPtr) cur);
break;
case XML_ELEMENT_NODE:
@ -1697,6 +1692,8 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
}
}
}
ctxt->options = oldoptions;
}
#endif
@ -1915,6 +1912,28 @@ xmlSaveClose(xmlSaveCtxtPtr ctxt)
return(ret);
}
/**
* xmlSaveFinish:
* @ctxt: a document saving context
*
* Close a document saving context, i.e. make sure that all bytes have
* been output and free the associated data.
*
* Returns an xmlParserErrors code.
*/
int
xmlSaveFinish(xmlSaveCtxtPtr ctxt)
{
int ret;
if (ctxt == NULL)
return(XML_ERR_INTERNAL_ERROR);
xmlSaveFlush(ctxt);
ret = ctxt->buf->error;
xmlFreeSaveCtxt(ctxt);
return(ret);
}
/**
* xmlSaveSetEscape:
* @ctxt: a document saving context
@ -2311,6 +2330,8 @@ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
int dummy = 0;
xmlOutputBufferPtr out_buff = NULL;
xmlCharEncodingHandlerPtr conv_hdlr = NULL;
xmlChar *content;
int len;
if (doc_txt_len == NULL) {
doc_txt_len = &dummy; /* Continue, caller just won't get length */
@ -2361,19 +2382,27 @@ xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
xmlDocContentDumpOutput(&ctxt, out_doc);
xmlOutputBufferFlush(out_buff);
if (out_buff->conv != NULL) {
*doc_txt_len = xmlBufUse(out_buff->conv);
*doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->conv), *doc_txt_len);
if (xmlBufContent(out_buff->buffer) == NULL)
goto error;
content = xmlBufContent(out_buff->conv);
len = xmlBufUse(out_buff->conv);
} else {
*doc_txt_len = xmlBufUse(out_buff->buffer);
*doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->buffer),*doc_txt_len);
content = xmlBufContent(out_buff->buffer);
len = xmlBufUse(out_buff->buffer);
}
(void)xmlOutputBufferClose(out_buff);
if (content == NULL)
goto error;
*doc_txt_ptr = xmlStrndup(content, len);
if (*doc_txt_ptr == NULL)
goto error;
*doc_txt_len = len;
xmlOutputBufferClose(out_buff);
if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
*doc_txt_len = 0;
xmlSaveErrMemory("creating output");
}
return;
error:
xmlSaveErrMemory("creating output");
xmlOutputBufferClose(out_buff);
return;
}