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

save: Fix xmlSave with NULL encoding

Regressed with cc45f618.
This commit is contained in:
Nick Wellnhofer
2025-04-20 19:25:04 +02:00
parent b85d77d156
commit 936e3d529a
2 changed files with 71 additions and 22 deletions

View File

@@ -288,6 +288,50 @@ testNoBlanks(void) {
return err; return err;
} }
static int
testSaveNullEncDoc(const char *xml, const char *expect) {
xmlDocPtr doc;
xmlBufferPtr buffer;
xmlSaveCtxtPtr save;
const xmlChar *result;
int err = 0;
doc = xmlReadDoc(BAD_CAST xml, NULL, NULL, 0);
buffer = xmlBufferCreate();
save = xmlSaveToBuffer(buffer, NULL, 0);
xmlSaveDoc(save, doc);
xmlSaveClose(save);
result = xmlBufferContent(buffer);
if (strcmp((char *) result, expect) != 0) {
fprintf(stderr, "xmlSave with NULL encodíng failed\n");
err = 1;
}
xmlBufferFree(buffer);
xmlFreeDoc(doc);
return err;
}
static int
testSaveNullEnc(void) {
int err = 0;
err |= testSaveNullEncDoc(
"<?xml version=\"1.0\"?><doc>\xC3\x98</doc>",
"<?xml version=\"1.0\"?>\n<doc>&#xD8;</doc>\n");
err |= testSaveNullEncDoc(
"<?xml version=\"1.0\" encoding=\"utf-8\"?><doc>\xC3\x98</doc>",
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<doc>\xC3\x98</doc>\n");
err |= testSaveNullEncDoc(
"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><doc>\xD8</doc>",
"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<doc>\xD8</doc>\n");
return err;
}
#endif /* LIBXML_OUTPUT_ENABLED */ #endif /* LIBXML_OUTPUT_ENABLED */
#ifdef LIBXML_SAX1_ENABLED #ifdef LIBXML_SAX1_ENABLED
@@ -1157,6 +1201,7 @@ main(void) {
#ifdef LIBXML_OUTPUT_ENABLED #ifdef LIBXML_OUTPUT_ENABLED
err |= testCtxtParseContent(); err |= testCtxtParseContent();
err |= testNoBlanks(); err |= testNoBlanks();
err |= testSaveNullEnc();
#endif #endif
#ifdef LIBXML_SAX1_ENABLED #ifdef LIBXML_SAX1_ENABLED
err |= testBalancedChunk(); err |= testBalancedChunk();

View File

@@ -778,13 +778,19 @@ static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
xmlSaveErr(buf, res, NULL, encoding); xmlSaveErr(buf, res, NULL, encoding);
return(-1); return(-1);
} }
buf->conv = xmlBufCreate(4000 /* MINLEN */);
if (buf->conv == NULL) { if (handler != NULL) {
xmlCharEncCloseFunc(handler); buf->conv = xmlBufCreate(4000 /* MINLEN */);
xmlSaveErrMemory(buf); if (buf->conv == NULL) {
return(-1); xmlCharEncCloseFunc(handler);
} xmlSaveErrMemory(buf);
buf->encoder = handler; return(-1);
}
buf->encoder = handler;
}
ctxt->encoding = (const xmlChar *) encoding;
/* /*
* initialize the state, e.g. if outputting a BOM * initialize the state, e.g. if outputting a BOM
*/ */
@@ -795,11 +801,15 @@ static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) { static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
xmlOutputBufferPtr buf = ctxt->buf; xmlOutputBufferPtr buf = ctxt->buf;
xmlOutputBufferFlush(buf); xmlOutputBufferFlush(buf);
xmlCharEncCloseFunc(buf->encoder); xmlCharEncCloseFunc(buf->encoder);
xmlBufFree(buf->conv); xmlBufFree(buf->conv);
buf->encoder = NULL; buf->encoder = NULL;
buf->conv = NULL; buf->conv = NULL;
ctxt->encoding = NULL;
return(0); return(0);
} }
@@ -1342,7 +1352,6 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
const xmlChar *oldctxtenc = ctxt->encoding; const xmlChar *oldctxtenc = ctxt->encoding;
const xmlChar *encoding = ctxt->encoding; const xmlChar *encoding = ctxt->encoding;
xmlOutputBufferPtr buf = ctxt->buf; xmlOutputBufferPtr buf = ctxt->buf;
xmlCharEncoding enc;
int switched_encoding = 0; int switched_encoding = 0;
xmlInitParser(); xmlInitParser();
@@ -1370,6 +1379,7 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) { if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
return(-1); return(-1);
} }
switched_encoding = 1;
} }
if (ctxt->options & XML_SAVE_FORMAT) if (ctxt->options & XML_SAVE_FORMAT)
htmlDocContentDumpFormatOutput(buf, cur, htmlDocContentDumpFormatOutput(buf, cur,
@@ -1377,29 +1387,23 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
else else
htmlDocContentDumpFormatOutput(buf, cur, htmlDocContentDumpFormatOutput(buf, cur,
(const char *)encoding, 0); (const char *)encoding, 0);
return(0);
#else #else
return(-1); return(-1);
#endif #endif
} else if ((cur->type == XML_DOCUMENT_NODE) || } else if ((cur->type == XML_DOCUMENT_NODE) ||
(ctxt->options & XML_SAVE_AS_XML) || (ctxt->options & XML_SAVE_AS_XML) ||
(ctxt->options & XML_SAVE_XHTML)) { (ctxt->options & XML_SAVE_XHTML)) {
enc = xmlParseCharEncoding((const char*) encoding);
if ((encoding != NULL) && (oldctxtenc == NULL) && if ((encoding != NULL) && (oldctxtenc == NULL) &&
(buf->encoder == NULL) && (buf->conv == NULL) && (buf->encoder == NULL) && (buf->conv == NULL) &&
((ctxt->options & XML_SAVE_NO_DECL) == 0)) { ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
if ((enc != XML_CHAR_ENCODING_UTF8) && /*
(enc != XML_CHAR_ENCODING_NONE) && * we need to switch to this encoding but just for this
(enc != XML_CHAR_ENCODING_ASCII)) { * document since we output the XMLDecl the conversion
/* * must be done to not generate not well formed documents.
* we need to switch to this encoding but just for this */
* document since we output the XMLDecl the conversion if (xmlSaveSwitchEncoding(ctxt, (const char *) encoding) < 0)
* must be done to not generate not well formed documents. return(-1);
*/ switched_encoding = 1;
if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0)
return(-1);
switched_encoding = 1;
}
} }