[PATCH 1/2] xmllite/writer: Improve handling of the output with invalid encoding

Nikolay Sivov nsivov at codeweavers.com
Thu Aug 3 03:00:31 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/xmllite/reader.c       |   4 +-
 dlls/xmllite/tests/writer.c | 117 +++++++++++++++++++++++++++++++++++++++++++-
 dlls/xmllite/writer.c       |  85 +++++++++++++++++++++++---------
 3 files changed, 181 insertions(+), 25 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index ac0fe33f9f..495d4e3cb4 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -156,7 +156,7 @@ struct xml_encoding_data
 
 static const struct xml_encoding_data xml_encoding_map[] = {
     { usasciiW, XmlEncoding_USASCII, 20127 },
-    { utf16W, XmlEncoding_UTF16, ~0 },
+    { utf16W, XmlEncoding_UTF16, 1200 },
     { utf8W,  XmlEncoding_UTF8,  CP_UTF8 },
 };
 
@@ -1084,7 +1084,7 @@ static HRESULT reader_more(xmlreader *reader)
     prev_len = dest->written / sizeof(WCHAR);
 
     /* just copy for UTF-16 case */
-    if (cp == ~0)
+    if (cp == 1200)
     {
         readerinput_grow(readerinput, len);
         memcpy(dest->data + dest->written, src->data + src->cur, len);
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c
index 8ef2e70979..1add717b8e 100644
--- a/dlls/xmllite/tests/writer.c
+++ b/dlls/xmllite/tests/writer.c
@@ -31,6 +31,8 @@
 #include "initguid.h"
 DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
 
+static const WCHAR aW[] = {'a',0};
+
 #define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
 static void _expect_ref(IUnknown *obj, ULONG ref, int line)
 {
@@ -292,11 +294,92 @@ static void test_writer_create(void)
     IXmlWriter_Release(writer);
 }
 
+static void test_invalid_output_encoding(IXmlWriter *writer, IUnknown *output)
+{
+    HRESULT hr;
+
+    hr = IXmlWriter_SetOutput(writer, output);
+    ok(hr == S_OK, "Failed to set output, hr %#x.\n", hr);
+
+    /* TODO: WriteAttributes */
+
+    hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteCData(writer, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteCharEntity(writer, 0x100);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteChars(writer, aW, 1);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteComment(writer, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    /* TODO: WriteDocType */
+
+    hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteEndDocument(writer);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteEndElement(writer);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteEntityRef(writer, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteFullEndElement(writer);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteName(writer, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteNmToken(writer, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    /* TODO: WriteNode */
+    /* TODO: WriteNodeShallow */
+
+    hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteQualifiedName(writer, aW, NULL);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteRaw(writer, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteRawChars(writer, aW, 1);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    hr = IXmlWriter_WriteString(writer, aW);
+    ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
+
+    /* TODO: WriteSurrogateCharEntity */
+    /* ًُُTODO: WriteWhitespace */
+
+    hr = IXmlWriter_Flush(writer);
+    ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+}
+
 static void test_writeroutput(void)
 {
     static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
     static const WCHAR usasciiW[] = {'u','s','-','a','s','c','i','i',0};
+    static const WCHAR dummyW[] = {'d','u','m','m','y',0};
     IXmlWriterOutput *output;
+    IXmlWriter *writer;
+    IStream *stream;
     IUnknown *unk;
     HRESULT hr;
 
@@ -339,6 +422,39 @@ todo_wine
     hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, usasciiW, &output);
     ok(hr == S_OK, "got %08x\n", hr);
     IUnknown_Release(output);
+
+    /* Create output with meaningless code page value. */
+    hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
+    ok(hr == S_OK, "Failed to create writer, hr %#x.\n", hr);
+
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    output = NULL;
+    hr = CreateXmlWriterOutputWithEncodingCodePage((IUnknown *)stream, NULL, ~0u, &output);
+    ok(hr == S_OK, "Failed to create writer output, hr %#x.\n", hr);
+
+    test_invalid_output_encoding(writer, output);
+    CHECK_OUTPUT(stream, "");
+
+    IStream_Release(stream);
+    IUnknown_Release(output);
+
+    /* Same, with invalid encoding name. */
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    output = NULL;
+    hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, dummyW, &output);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    test_invalid_output_encoding(writer, output);
+    CHECK_OUTPUT(stream, "");
+
+    IStream_Release(stream);
+    IUnknown_Release(output);
+
+    IXmlWriter_Release(writer);
 }
 
 static void test_writestartdocument(void)
@@ -547,7 +663,6 @@ static void test_bom(void)
     static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
     static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
     static const WCHAR xmlW[] = {'x','m','l',0};
-    static const WCHAR aW[] = {'a',0};
     IXmlWriterOutput *output;
     unsigned char *ptr;
     IXmlWriter *writer;
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index 9e99338798..9bf7e63211 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -57,13 +57,14 @@ struct output_buffer
 
 typedef enum
 {
-    XmlWriterState_Initial,      /* output is not set yet */
-    XmlWriterState_Ready,        /* SetOutput() was called, ready to start */
-    XmlWriterState_PIDocStarted, /* document was started with manually added 'xml' PI */
-    XmlWriterState_DocStarted,   /* document was started with WriteStartDocument() */
-    XmlWriterState_ElemStarted,  /* writing element */
-    XmlWriterState_Content,      /* content is accepted at this point */
-    XmlWriterState_DocClosed     /* WriteEndDocument was called */
+    XmlWriterState_Initial,         /* output is not set yet */
+    XmlWriterState_Ready,           /* SetOutput() was called, ready to start */
+    XmlWriterState_InvalidEncoding, /* SetOutput() was called, but output had invalid encoding */
+    XmlWriterState_PIDocStarted,    /* document was started with manually added 'xml' PI */
+    XmlWriterState_DocStarted,      /* document was started with WriteStartDocument() */
+    XmlWriterState_ElemStarted,     /* writing element */
+    XmlWriterState_Content,         /* content is accepted at this point */
+    XmlWriterState_DocClosed        /* WriteEndDocument was called */
 } XmlWriterState;
 
 typedef struct
@@ -208,11 +209,11 @@ static HRESULT init_output_buffer(xmlwriteroutput *output)
 {
     struct output_buffer *buffer = &output->buffer;
     const int initial_len = 0x2000;
+    UINT cp = ~0u;
     HRESULT hr;
-    UINT cp;
 
-    hr = get_code_page(output->encoding, &cp);
-    if (FAILED(hr)) return hr;
+    if (FAILED(hr = get_code_page(output->encoding, &cp)))
+        WARN("Failed to get code page for specified encoding.\n");
 
     buffer->data = writeroutput_alloc(output, initial_len);
     if (!buffer->data) return E_OUTOFMEMORY;
@@ -256,16 +257,8 @@ static HRESULT write_output_buffer(xmlwriteroutput *output, const WCHAR *data, i
     HRESULT hr;
     char *ptr;
 
-    if (buffer->codepage != ~0) {
-        length = WideCharToMultiByte(buffer->codepage, 0, data, len, NULL, 0, NULL, NULL);
-        hr = grow_output_buffer(output, length);
-        if (FAILED(hr)) return hr;
-        ptr = buffer->data + buffer->written;
-        length = WideCharToMultiByte(buffer->codepage, 0, data, len, ptr, length, NULL, NULL);
-        buffer->written += len == -1 ? length-1 : length;
-    }
-    else {
-        /* WCHAR data just copied */
+    if (buffer->codepage == 1200) {
+        /* For UTF-16 encoding just copy. */
         length = len == -1 ? strlenW(data) : len;
         if (length) {
             length *= sizeof(WCHAR);
@@ -281,6 +274,14 @@ static HRESULT write_output_buffer(xmlwriteroutput *output, const WCHAR *data, i
             *(WCHAR*)ptr = 0;
         }
     }
+    else {
+        length = WideCharToMultiByte(buffer->codepage, 0, data, len, NULL, 0, NULL, NULL);
+        hr = grow_output_buffer(output, length);
+        if (FAILED(hr)) return hr;
+        ptr = buffer->data + buffer->written;
+        length = WideCharToMultiByte(buffer->codepage, 0, data, len, ptr, length, NULL, NULL);
+        buffer->written += len == -1 ? length-1 : length;
+    }
 
     return S_OK;
 }
@@ -546,7 +547,6 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
                 writeroutput, writeroutput->lpVtbl);
             IUnknown_Release(writeroutput);
             return E_FAIL;
-
         }
     }
 
@@ -557,7 +557,10 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
         This->output = impl_from_IXmlWriterOutput(writeroutput);
     }
 
-    This->state = XmlWriterState_Ready;
+    if (This->output->encoding == XmlEncoding_Unknown)
+        This->state = XmlWriterState_InvalidEncoding;
+    else
+        This->state = XmlWriterState_Ready;
     return writeroutput_query_for_stream(This->output);
 }
 
@@ -643,6 +646,8 @@ static HRESULT WINAPI xmlwriter_WriteAttributeString(IXmlWriter *iface, LPCWSTR
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
@@ -690,6 +695,8 @@ static HRESULT WINAPI xmlwriter_WriteCData(IXmlWriter *iface, LPCWSTR data)
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
@@ -731,6 +738,8 @@ static HRESULT WINAPI xmlwriter_WriteCharEntity(IXmlWriter *iface, WCHAR ch)
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_ElemStarted:
         writer_close_starttag(This);
         break;
@@ -756,6 +765,8 @@ static HRESULT WINAPI xmlwriter_WriteChars(IXmlWriter *iface, const WCHAR *pwch,
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_DocClosed:
         return WR_E_INVALIDACTION;
     default:
@@ -778,6 +789,8 @@ static HRESULT WINAPI xmlwriter_WriteComment(IXmlWriter *iface, LPCWSTR comment)
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_ElemStarted:
         writer_close_starttag(This);
         break;
@@ -835,6 +848,8 @@ static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR pr
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_ElemStarted:
         writer_close_starttag(This);
         break;
@@ -879,6 +894,8 @@ static HRESULT WINAPI xmlwriter_WriteEndDocument(IXmlWriter *iface)
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
@@ -906,6 +923,8 @@ static HRESULT WINAPI xmlwriter_WriteEndElement(IXmlWriter *iface)
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
@@ -942,6 +961,8 @@ static HRESULT WINAPI xmlwriter_WriteEntityRef(IXmlWriter *iface, LPCWSTR pwszNa
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_DocClosed:
         return WR_E_INVALIDACTION;
     default:
@@ -966,6 +987,8 @@ static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface)
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
@@ -1005,6 +1028,8 @@ static HRESULT WINAPI xmlwriter_WriteName(IXmlWriter *iface, LPCWSTR pwszName)
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
@@ -1026,6 +1051,8 @@ static HRESULT WINAPI xmlwriter_WriteNmToken(IXmlWriter *iface, LPCWSTR pwszNmTo
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
@@ -1066,6 +1093,8 @@ static HRESULT WINAPI xmlwriter_WriteProcessingInstruction(IXmlWriter *iface, LP
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_DocStarted:
         if (!strcmpW(name, xmlW))
             return WR_E_INVALIDACTION;
@@ -1102,6 +1131,8 @@ static HRESULT WINAPI xmlwriter_WriteQualifiedName(IXmlWriter *iface, LPCWSTR pw
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_DocClosed:
         return WR_E_INVALIDACTION;
     default:
@@ -1130,6 +1161,8 @@ static HRESULT WINAPI xmlwriter_WriteRaw(IXmlWriter *iface, LPCWSTR data)
     case XmlWriterState_DocStarted:
     case XmlWriterState_PIDocStarted:
         break;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
@@ -1149,6 +1182,8 @@ static HRESULT WINAPI xmlwriter_WriteRawChars(IXmlWriter *iface,  const WCHAR *p
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_DocClosed:
         return WR_E_INVALIDACTION;
     default:
@@ -1173,6 +1208,8 @@ static HRESULT WINAPI xmlwriter_WriteStartDocument(IXmlWriter *iface, XmlStandal
         return S_OK;
     case XmlWriterState_Ready:
         break;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
@@ -1195,6 +1232,8 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre
     {
     case XmlWriterState_Initial:
         return E_UNEXPECTED;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     case XmlWriterState_DocClosed:
         return WR_E_INVALIDACTION;
     default:
@@ -1271,6 +1310,8 @@ static HRESULT WINAPI xmlwriter_WriteString(IXmlWriter *iface, const WCHAR *stri
     case XmlWriterState_DocClosed:
         This->state = XmlWriterState_DocClosed;
         return WR_E_INVALIDACTION;
+    case XmlWriterState_InvalidEncoding:
+        return MX_E_ENCODING;
     default:
         ;
     }
-- 
2.13.2




More information about the wine-patches mailing list