Module: wine Branch: master Commit: 69b2ed368d5966ca16654a5a151741f53928c312 URL: https://source.winehq.org/git/wine.git/?a=commit;h=69b2ed368d5966ca16654a5a1...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Mon Sep 10 15:27:31 2018 +0300
xmllite/writer: Validate local name and prefix in WriteElementString().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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 f10c718..97c269c 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 67fe55b..7be8854 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 c0260ae..a6cd1aa 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 7884e27..9fb9e82 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__ */