Commit 69b2ed36 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

xmllite/writer: Validate local name and prefix in WriteElementString().

parent 5e5b7b49
...@@ -1524,7 +1524,7 @@ static inline BOOL is_namestartchar(WCHAR ch) ...@@ -1524,7 +1524,7 @@ static inline BOOL is_namestartchar(WCHAR ch)
} }
/* [4 NS] NCName ::= Name - (Char* ':' Char*) */ /* [4 NS] NCName ::= Name - (Char* ':' Char*) */
static inline BOOL is_ncnamechar(WCHAR ch) BOOL is_ncnamechar(WCHAR ch)
{ {
return (ch >= 'A' && ch <= 'Z') || return (ch >= 'A' && ch <= 'Z') ||
(ch == '_') || (ch >= 'a' && ch <= 'z') || (ch == '_') || (ch >= 'a' && ch <= 'z') ||
......
...@@ -865,6 +865,7 @@ static void test_WriteStartElement(void) ...@@ -865,6 +865,7 @@ static void test_WriteStartElement(void)
{ NULL, NULL, "uri", NULL, NULL, E_INVALIDARG }, { NULL, NULL, "uri", NULL, NULL, E_INVALIDARG },
{ NULL, NULL, NULL, NULL, NULL, E_INVALIDARG }, { NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
{ NULL, "prefix:local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 }, { 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 }, { NULL, ":local", "uri", NULL, NULL, WC_E_NAMECHARACTER, 1, 1 },
{ ":", "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 }, { NULL, "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSPREFIXDECLARATION },
...@@ -1062,7 +1063,7 @@ static void test_WriteElementString(void) ...@@ -1062,7 +1063,7 @@ static void test_WriteElementString(void)
valueW = strdupAtoW(element_string_tests[i].value); valueW = strdupAtoW(element_string_tests[i].value);
hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW); 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); ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
if (SUCCEEDED(element_string_tests[i].hr)) if (SUCCEEDED(element_string_tests[i].hr))
......
...@@ -293,15 +293,16 @@ static HRESULT write_output_buffer_quoted(xmlwriteroutput *output, const WCHAR * ...@@ -293,15 +293,16 @@ static HRESULT write_output_buffer_quoted(xmlwriteroutput *output, const WCHAR *
} }
/* TODO: test if we need to validate char range */ /* 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) { if (prefix) {
static const WCHAR colW[] = {':'}; 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, colW, ARRAY_SIZE(colW));
} }
write_output_buffer(output, local_name, -1); write_output_buffer(output, local_name, local_len);
return S_OK; return S_OK;
} }
...@@ -834,10 +835,33 @@ static HRESULT WINAPI xmlwriter_WriteDocType(IXmlWriter *iface, LPCWSTR pwszName ...@@ -834,10 +835,33 @@ static HRESULT WINAPI xmlwriter_WriteDocType(IXmlWriter *iface, LPCWSTR pwszName
return E_NOTIMPL; 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, static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR prefix,
LPCWSTR local_name, LPCWSTR uri, LPCWSTR value) LPCWSTR local_name, LPCWSTR uri, LPCWSTR value)
{ {
xmlwriter *This = impl_from_IXmlWriter(iface); 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), 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)); wine_dbgstr_w(uri), wine_dbgstr_w(value));
...@@ -860,17 +884,24 @@ static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR pr ...@@ -860,17 +884,24 @@ static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR pr
if (!local_name) if (!local_name)
return E_INVALIDARG; 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_encoding_bom(This);
write_node_indent(This); write_node_indent(This);
write_output_buffer(This->output, ltW, ARRAY_SIZE(ltW)); 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) if (value)
{ {
write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW)); write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW));
write_output_buffer(This->output, value, -1); write_output_buffer(This->output, value, -1);
write_output_buffer(This->output, closeelementW, ARRAY_SIZE(closeelementW)); 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)); write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW));
} }
else else
...@@ -1258,7 +1289,7 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre ...@@ -1258,7 +1289,7 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre
push_element(This, element); push_element(This, element);
write_output_buffer(This->output, ltW, ARRAY_SIZE(ltW)); 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); writer_inc_indent(This);
return S_OK; return S_OK;
......
...@@ -60,4 +60,6 @@ HRESULT get_code_page(xml_encoding,UINT*) DECLSPEC_HIDDEN; ...@@ -60,4 +60,6 @@ HRESULT get_code_page(xml_encoding,UINT*) DECLSPEC_HIDDEN;
const WCHAR *get_encoding_name(xml_encoding) DECLSPEC_HIDDEN; const WCHAR *get_encoding_name(xml_encoding) DECLSPEC_HIDDEN;
xml_encoding get_encoding_from_codepage(UINT) DECLSPEC_HIDDEN; xml_encoding get_encoding_from_codepage(UINT) DECLSPEC_HIDDEN;
BOOL is_ncnamechar(WCHAR ch) DECLSPEC_HIDDEN;
#endif /* __XMLLITE_PRIVATE__ */ #endif /* __XMLLITE_PRIVATE__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment