Jacek Caban : msxml3: Fix string length handling in I[VB]SAXContentHandler::characters.

Alexandre Julliard julliard at winehq.org
Mon Nov 25 09:12:27 CST 2019


Module: wine
Branch: stable
Commit: 04dce9bc0bd47d3cd120ee8128ceb160f28152bb
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=04dce9bc0bd47d3cd120ee8128ceb160f28152bb

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Jun 18 16:55:40 2019 +0200

msxml3: Fix string length handling in I[VB]SAXContentHandler::characters.

Windows crashes when -1 length is passed. Escaping should just copy
embedded null bytes.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 73af53c4bca6cc56b4fccc8139cc564715c08e99)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 dlls/msxml3/mxwriter.c        | 10 +++---
 dlls/msxml3/tests/saxreader.c | 72 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/dlls/msxml3/mxwriter.c b/dlls/msxml3/mxwriter.c
index 10be2508b2..a5bfdf1e99 100644
--- a/dlls/msxml3/mxwriter.c
+++ b/dlls/msxml3/mxwriter.c
@@ -498,10 +498,10 @@ static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
     WCHAR *ptr, *ret;
 
     /* default buffer size to something if length is unknown */
-    conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
+    conv_len = max(2**len, default_alloc);
     ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
 
-    while (*str && p)
+    while (p)
     {
         if (ptr - ret > conv_len - grow_thresh)
         {
@@ -539,10 +539,10 @@ static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
         }
 
         str++;
-        if (*len != -1) p--;
+        p--;
     }
 
-    if (*len != -1) *len = ptr-ret;
+    *len = ptr-ret;
     *++ptr = 0;
 
     return ret;
@@ -2206,7 +2206,7 @@ static HRESULT WINAPI VBSAXContentHandler_characters(IVBSAXContentHandler *iface
     if (!chars)
         return E_POINTER;
 
-    return ISAXContentHandler_characters(&This->ISAXContentHandler_iface, *chars, -1);
+    return ISAXContentHandler_characters(&This->ISAXContentHandler_iface, *chars, SysStringLen(*chars));
 }
 
 static HRESULT WINAPI VBSAXContentHandler_ignorableWhitespace(IVBSAXContentHandler *iface, BSTR *chars)
diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c
index eeef5b64c1..d1076f58ea 100644
--- a/dlls/msxml3/tests/saxreader.c
+++ b/dlls/msxml3/tests/saxreader.c
@@ -3950,10 +3950,13 @@ static const struct writer_characters_t writer_characters[] = {
 static void test_mxwriter_characters(void)
 {
     static const WCHAR chardataW[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
+    static const WCHAR embedded_nullbytes[] = {'a',0,'b',0,0,0,'c',0};
     const struct writer_characters_t *table = writer_characters;
+    IVBSAXContentHandler *vb_content;
     ISAXContentHandler *content;
     IMXWriter *writer;
     VARIANT dest;
+    BSTR str;
     HRESULT hr;
     int i = 0;
 
@@ -3964,6 +3967,9 @@ static void test_mxwriter_characters(void)
     hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content);
     EXPECT_HR(hr, S_OK);
 
+    hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXContentHandler, (void**)&vb_content);
+    EXPECT_HR(hr, S_OK);
+
     hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE);
     EXPECT_HR(hr, S_OK);
 
@@ -3976,6 +3982,10 @@ static void test_mxwriter_characters(void)
     hr = ISAXContentHandler_characters(content, chardataW, 0);
     EXPECT_HR(hr, S_OK);
 
+    str = _bstr_("VbChars");
+    hr = IVBSAXContentHandler_characters(vb_content, &str);
+    EXPECT_HR(hr, S_OK);
+
     hr = ISAXContentHandler_characters(content, chardataW, ARRAY_SIZE(chardataW) - 1);
     EXPECT_HR(hr, S_OK);
 
@@ -3983,13 +3993,14 @@ static void test_mxwriter_characters(void)
     hr = IMXWriter_get_output(writer, &dest);
     EXPECT_HR(hr, S_OK);
     ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest));
-    ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest)));
+    ok(!lstrcmpW(_bstr_("VbCharsTESTCHARDATA ."), V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest)));
     VariantClear(&dest);
 
     hr = ISAXContentHandler_endDocument(content);
     EXPECT_HR(hr, S_OK);
 
     ISAXContentHandler_Release(content);
+    IVBSAXContentHandler_Release(vb_content);
     IMXWriter_Release(writer);
 
     /* try empty characters data to see if element is closed */
@@ -4025,6 +4036,65 @@ static void test_mxwriter_characters(void)
     ISAXContentHandler_Release(content);
     IMXWriter_Release(writer);
 
+    /* test embedded null bytes */
+    hr = CoCreateInstance(&CLSID_MXXMLWriter, NULL, CLSCTX_INPROC_SERVER,
+            &IID_IMXWriter, (void**)&writer);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE);
+    EXPECT_HR(hr, S_OK);
+
+    hr = ISAXContentHandler_startDocument(content);
+    EXPECT_HR(hr, S_OK);
+
+    hr = ISAXContentHandler_characters(content, embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes));
+    EXPECT_HR(hr, S_OK);
+
+    V_VT(&dest) = VT_EMPTY;
+    hr = IMXWriter_get_output(writer, &dest);
+    EXPECT_HR(hr, S_OK);
+    ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest));
+    ok(SysStringLen(V_BSTR(&dest)) == ARRAY_SIZE(embedded_nullbytes), "unexpected len %d\n", SysStringLen(V_BSTR(&dest)));
+    ok(!memcmp(V_BSTR(&dest), embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes)),
+       "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest)));
+    VariantClear(&dest);
+
+    ISAXContentHandler_Release(content);
+    IMXWriter_Release(writer);
+
+    hr = CoCreateInstance(&CLSID_MXXMLWriter, NULL, CLSCTX_INPROC_SERVER,
+            &IID_IMXWriter, (void**)&writer);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXContentHandler, (void**)&vb_content);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IVBSAXContentHandler_startDocument(vb_content);
+    EXPECT_HR(hr, S_OK);
+
+    str = SysAllocStringLen(embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes));
+    hr = IVBSAXContentHandler_characters(vb_content, &str);
+    EXPECT_HR(hr, S_OK);
+    SysFreeString(str);
+
+    V_VT(&dest) = VT_EMPTY;
+    hr = IMXWriter_get_output(writer, &dest);
+    EXPECT_HR(hr, S_OK);
+    ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest));
+    ok(SysStringLen(V_BSTR(&dest)) == ARRAY_SIZE(embedded_nullbytes), "unexpected len %d\n", SysStringLen(V_BSTR(&dest)));
+    ok(!memcmp(V_BSTR(&dest), embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes)),
+       "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest)));
+    VariantClear(&dest);
+
+    IVBSAXContentHandler_Release(vb_content);
+    IMXWriter_Release(writer);
+
     /* batch tests */
     while (table->clsid)
     {




More information about the wine-cvs mailing list