[PATCH 2/3] xmllite/writer: Validate local name and prefix in WriteElementString().

Nikolay Sivov nsivov at codeweavers.com
Mon Sep 10 07:27:31 CDT 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/xmllite/reader.c          |  2 +-
 dlls/xmllite/tests/writer.c    |  3 ++-
 dlls/xmllite/writer.c          | 43 +++++++++++++++++++++++++++++-----
 dlls/xmllite/xmllite_private.h |  2 ++
 4 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index f10c718d80..97c269ceda 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -1524,7 +1524,7 @@ static inline BOOL is_namestartchar(WCHAR ch)
 }
 
 /* [4 NS] NCName ::= Name - (Char* ':' Char*) */
-static inline BOOL is_ncnamechar(WCHAR ch)
+BOOL is_ncnamechar(WCHAR ch)
 {
     return (ch >= 'A' && ch <= 'Z') ||
            (ch == '_') || (ch >= 'a' && ch <= 'z') ||
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c
index 67fe55bb44..7be885427b 100644
--- a/dlls/xmllite/tests/writer.c
+++ b/dlls/xmllite/tests/writer.c
@@ -865,6 +865,7 @@ static void test_WriteStartElement(void)
         { NULL, NULL, "uri", NULL, NULL, E_INVALIDARG },
         { NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
         { NULL, "prefix:local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
+        { "pre:fix", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
         { NULL, ":local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
         { ":", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
         { NULL, "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSPREFIXDECLARATION },
@@ -1062,7 +1063,7 @@ static void test_WriteElementString(void)
         valueW = strdupAtoW(element_string_tests[i].value);
 
         hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW);
-    todo_wine_if(i >= 10)
+    todo_wine_if(i >= 13)
         ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
 
         if (SUCCEEDED(element_string_tests[i].hr))
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index c0260ae473..a6cd1aa200 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -293,15 +293,16 @@ static HRESULT write_output_buffer_quoted(xmlwriteroutput *output, const WCHAR *
 }
 
 /* TODO: test if we need to validate char range */
-static HRESULT write_output_qname(xmlwriteroutput *output, const WCHAR *prefix, const WCHAR *local_name)
+static HRESULT write_output_qname(xmlwriteroutput *output, const WCHAR *prefix, int prefix_len,
+        const WCHAR *local_name, int local_len)
 {
     if (prefix) {
         static const WCHAR colW[] = {':'};
-        write_output_buffer(output, prefix, -1);
+        write_output_buffer(output, prefix, prefix_len);
         write_output_buffer(output, colW, ARRAY_SIZE(colW));
     }
 
-    write_output_buffer(output, local_name, -1);
+    write_output_buffer(output, local_name, local_len);
 
     return S_OK;
 }
@@ -834,10 +835,33 @@ static HRESULT WINAPI xmlwriter_WriteDocType(IXmlWriter *iface, LPCWSTR pwszName
     return E_NOTIMPL;
 }
 
+static HRESULT is_valid_ncname(const WCHAR *str, int *out)
+{
+    int len = 0;
+
+    *out = 0;
+
+    if (!str || !*str)
+        return S_OK;
+
+    while (*str)
+    {
+        if (!is_ncnamechar(*str))
+            return WC_E_NAMECHARACTER;
+        len++;
+        str++;
+    }
+
+    *out = len;
+    return S_OK;
+}
+
 static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR prefix,
                                      LPCWSTR local_name, LPCWSTR uri, LPCWSTR value)
 {
     xmlwriter *This = impl_from_IXmlWriter(iface);
+    int prefix_len, local_len;
+    HRESULT hr;
 
     TRACE("(%p)->(%s %s %s %s)\n", This, wine_dbgstr_w(prefix), wine_dbgstr_w(local_name),
                         wine_dbgstr_w(uri), wine_dbgstr_w(value));
@@ -860,17 +884,24 @@ static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR pr
     if (!local_name)
         return E_INVALIDARG;
 
+    /* Validate prefix and local name */
+    if (FAILED(hr = is_valid_ncname(prefix, &prefix_len)))
+        return hr;
+
+    if (FAILED(hr = is_valid_ncname(local_name, &local_len)))
+        return hr;
+
     write_encoding_bom(This);
     write_node_indent(This);
     write_output_buffer(This->output, ltW, ARRAY_SIZE(ltW));
-    write_output_qname(This->output, prefix, local_name);
+    write_output_qname(This->output, prefix, prefix_len, local_name, local_len);
 
     if (value)
     {
         write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW));
         write_output_buffer(This->output, value, -1);
         write_output_buffer(This->output, closeelementW, ARRAY_SIZE(closeelementW));
-        write_output_qname(This->output, prefix, local_name);
+        write_output_qname(This->output, prefix, prefix_len, local_name, local_len);
         write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW));
     }
     else
@@ -1258,7 +1289,7 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre
     push_element(This, element);
 
     write_output_buffer(This->output, ltW, ARRAY_SIZE(ltW));
-    write_output_qname(This->output, prefix, local_name);
+    write_output_qname(This->output, prefix, -1, local_name, -1);
     writer_inc_indent(This);
 
     return S_OK;
diff --git a/dlls/xmllite/xmllite_private.h b/dlls/xmllite/xmllite_private.h
index 7884e27453..9fb9e82d33 100644
--- a/dlls/xmllite/xmllite_private.h
+++ b/dlls/xmllite/xmllite_private.h
@@ -60,4 +60,6 @@ HRESULT get_code_page(xml_encoding,UINT*) DECLSPEC_HIDDEN;
 const WCHAR *get_encoding_name(xml_encoding) DECLSPEC_HIDDEN;
 xml_encoding get_encoding_from_codepage(UINT) DECLSPEC_HIDDEN;
 
+BOOL is_ncnamechar(WCHAR ch) DECLSPEC_HIDDEN;
+
 #endif /* __XMLLITE_PRIVATE__ */
-- 
2.18.0




More information about the wine-devel mailing list