Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/tests/writer.c | 306 +++++++++++++++++++++++++++++++----- dlls/xmllite/writer.c | 3 + 2 files changed, 273 insertions(+), 36 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 33c2f8f7d1..67fe55bb44 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -26,6 +26,8 @@ #include "winbase.h" #include "ole2.h" #include "xmllite.h" + +#include "wine/heap.h" #include "wine/test.h"
#include "initguid.h" @@ -89,6 +91,19 @@ static void check_output(IStream *stream, const char *expected, BOOL todo, int l #define CHECK_OUTPUT_TODO(stream, expected) check_output(stream, expected, TRUE, __LINE__) #define CHECK_OUTPUT_RAW(stream, expected, size) check_output_raw(stream, expected, size, __LINE__)
+static WCHAR *strdupAtoW(const char *str) +{ + WCHAR *ret = NULL; + DWORD len; + + if (!str) return ret; + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = heap_alloc(len * sizeof(WCHAR)); + if (ret) + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + return ret; +} + static void writer_set_property(IXmlWriter *writer, XmlWriterProperty property) { HRESULT hr; @@ -826,13 +841,41 @@ static void test_bom(void) IXmlWriter_Release(writer); }
-static void test_writestartelement(void) +static void test_WriteStartElement(void) { + static const struct + { + const char *prefix; + const char *local; + const char *uri; + const char *output; + const char *output_partial; + HRESULT hr; + int todo; + int todo_partial; + } + start_element_tests[] = + { + { "prefix", "local", "uri", "<prefix:local xmlns:prefix="uri" />", "<prefix:local", S_OK, 1 }, + { NULL, "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1 }, + { "", "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1, 1 }, + { "", "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1, 1}, + + { "prefix", NULL, NULL, NULL, NULL, E_INVALIDARG }, + { 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 }, + { 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 }, + { "prefix", "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSURIDECLARATION }, + }; static const WCHAR valueW[] = {'v','a','l','u','e',0}; static const WCHAR aW[] = {'a',0}; static const WCHAR bW[] = {'b',0}; IXmlWriter *writer; IStream *stream; + unsigned int i; HRESULT hr;
hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); @@ -843,15 +886,6 @@ static void test_writestartelement(void)
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, aW, NULL, NULL); - ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); - - hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL); - ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); - - hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, aW); - ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); - hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL); ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -900,6 +934,161 @@ static void test_writestartelement(void) "<a><b>value</b><b />");
IStream_Release(stream); + + /* WriteStartElement */ + for (i = 0; i < ARRAY_SIZE(start_element_tests); ++i) + { + WCHAR *prefixW, *localW, *uriW; + + stream = writer_set_output(writer); + + writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit); + ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr); + + prefixW = strdupAtoW(start_element_tests[i].prefix); + localW = strdupAtoW(start_element_tests[i].local); + uriW = strdupAtoW(start_element_tests[i].uri); + + hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW); + todo_wine_if(i >= 7) + ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr); + + if (SUCCEEDED(start_element_tests[i].hr)) + { + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + check_output(stream, start_element_tests[i].output_partial, start_element_tests[i].todo_partial, __LINE__); + + hr = IXmlWriter_WriteEndDocument(writer); + ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + check_output(stream, start_element_tests[i].output, start_element_tests[i].todo, __LINE__); + } + + heap_free(prefixW); + heap_free(localW); + heap_free(uriW); + + IStream_Release(stream); + } + + IXmlWriter_Release(writer); +} + +static void test_WriteElementString(void) +{ + static const struct + { + const char *prefix; + const char *local; + const char *uri; + const char *value; + const char *output; + HRESULT hr; + int todo; + } + element_string_tests[] = + { + { "prefix", "local", "uri", "value", "<prefix:local xmlns:prefix="uri">value</prefix:local>", S_OK, 1 }, + { NULL, "local", "uri", "value", "<local xmlns="uri">value</local>", S_OK, 1 }, + { "", "local", "uri", "value", "<local xmlns="uri">value</local>", S_OK, 1 }, + { "prefix", "local", "uri", NULL, "<prefix:local xmlns:prefix="uri" />", S_OK, 1 }, + { NULL, "local", "uri", NULL, "<local xmlns="uri" />", S_OK, 1 }, + { "", "local", "uri", NULL, "<local xmlns="uri" />", S_OK, 1 }, + { NULL, "local", NULL, NULL, "<local />" }, + + { "prefix", NULL, NULL, "value", NULL, E_INVALIDARG }, + { NULL, NULL, "uri", "value", NULL, E_INVALIDARG }, + { NULL, NULL, NULL, "value", NULL, E_INVALIDARG }, + { NULL, "prefix:local", "uri", "value", NULL, WC_E_NAMECHARACTER }, + { NULL, ":local", "uri", "value", NULL, WC_E_NAMECHARACTER }, + { ":", "local", "uri", "value", NULL, WC_E_NAMECHARACTER }, + { NULL, "local", "http://www.w3.org/2000/xmlns/", "value", NULL, WR_E_XMLNSPREFIXDECLARATION }, + { "prefix", "local", "http://www.w3.org/2000/xmlns/", "value", NULL, WR_E_XMLNSURIDECLARATION }, + }; + static const WCHAR valueW[] = {'v','a','l','u','e',0}; + static const WCHAR aW[] = {'a',0}; + static const WCHAR bW[] = {'b',0}; + IXmlWriter *writer; + IStream *stream; + unsigned int i; + HRESULT hr; + + hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + stream = writer_set_output(writer); + + hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, + "<a><b>value</b><b />"); + + IStream_Release(stream); + + for (i = 0; i < ARRAY_SIZE(element_string_tests); ++i) + { + WCHAR *prefixW, *localW, *uriW, *valueW; + + stream = writer_set_output(writer); + + writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit); + ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr); + + prefixW = strdupAtoW(element_string_tests[i].prefix); + localW = strdupAtoW(element_string_tests[i].local); + uriW = strdupAtoW(element_string_tests[i].uri); + valueW = strdupAtoW(element_string_tests[i].value); + + hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW); + todo_wine_if(i >= 10) + ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr); + + if (SUCCEEDED(element_string_tests[i].hr)) + { + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__); + + hr = IXmlWriter_WriteEndDocument(writer); + ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__); + } + + heap_free(prefixW); + heap_free(localW); + heap_free(uriW); + heap_free(valueW); + + IStream_Release(stream); + } + IXmlWriter_Release(writer); }
@@ -1313,42 +1502,94 @@ static void test_indentation(void)
static void test_WriteAttributeString(void) { + static const struct + { + const char *prefix; + const char *local; + const char *uri; + const char *value; + const char *output; + const char *output_partial; + HRESULT hr; + } + attribute_tests[] = + { + { NULL, "a", NULL, "b", "<e a="b" />", "<e a="b"" }, + { "prefix", "local", "uri", "b", "<e prefix:local="b" xmlns:prefix="uri" />", "<e prefix:local="b"" }, + { NULL, "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e xmlns:a="defuri" />", "<e xmlns:a="defuri"" }, + + /* Autogenerated prefix names. */ + { NULL, "a", "defuri", NULL, "<e p1:a="" xmlns:p1="defuri" />", "<e p1:a=""" }, + { NULL, "a", "defuri", "b", "<e p1:a="b" xmlns:p1="defuri" />", "<e p1:a="b"" }, + + /* Failing cases. */ + { NULL, NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG }, + { "prefix", NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG }, + { "prefix", NULL, NULL, "b", "<e />", "<e", E_INVALIDARG }, + { "prefix", NULL, "uri", NULL, "<e />", "<e", E_INVALIDARG }, + { "xmlns", NULL, NULL, "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED }, + { "xmlns", "a", "defuri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION }, + { NULL, "xmlns", "uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION }, + { "xmlns", NULL, "uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION }, + { "prefix", "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", WR_E_XMLNSURIDECLARATION }, + }; + static const WCHAR prefixW[] = {'p','r','e','f','i','x',0}; static const WCHAR localW[] = {'l','o','c','a','l',0}; static const WCHAR uriW[] = {'u','r','i',0}; - static const WCHAR uri2W[] = {'u','r','i','2',0}; - static const WCHAR xmlnsW[] = {'x','m','l','n','s',0}; + static const WCHAR elementW[] = {'e',0}; static const WCHAR aW[] = {'a',0}; static const WCHAR bW[] = {'b',0}; IXmlWriter *writer; IStream *stream; + unsigned int i; HRESULT hr;
hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- stream = writer_set_output(writer); - writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
- hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit); - ok(hr == S_OK, "got 0x%08x\n", hr); + for (i = 0; i < ARRAY_SIZE(attribute_tests); ++i) + { + WCHAR *prefixW, *localW, *uriW, *valueW;
- hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL); - ok(hr == S_OK, "got 0x%08x\n", hr); + stream = writer_set_output(writer);
- hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, bW); - ok(hr == S_OK, "got 0x%08x\n", hr); + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit); + ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
- hr = IXmlWriter_WriteEndDocument(writer); - ok(hr == S_OK, "got 0x%08x\n", hr); + hr = IXmlWriter_WriteStartElement(writer, NULL, elementW, NULL); + ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
- hr = IXmlWriter_Flush(writer); - ok(hr == S_OK, "got 0x%08x\n", hr); + prefixW = strdupAtoW(attribute_tests[i].prefix); + localW = strdupAtoW(attribute_tests[i].local); + uriW = strdupAtoW(attribute_tests[i].uri); + valueW = strdupAtoW(attribute_tests[i].value);
- CHECK_OUTPUT(stream, - "<a a="b" />"); - IStream_Release(stream); + hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, uriW, valueW); + todo_wine_if(i != 0) + ok(hr == attribute_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + check_output(stream, attribute_tests[i].output_partial, i == 1 || i == 2 || i == 3 || i == 4, __LINE__); + + hr = IXmlWriter_WriteEndDocument(writer); + ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + heap_free(prefixW); + heap_free(localW); + heap_free(uriW); + heap_free(valueW); + + check_output(stream, attribute_tests[i].output, i == 1 || i == 2 || i == 3 || i == 4, __LINE__); + IStream_Release(stream); + }
/* with namespaces */ stream = writer_set_output(writer); @@ -1370,14 +1611,6 @@ todo_wine hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, bW); ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteAttributeString(writer, NULL, xmlnsW, uri2W, NULL); -todo_wine - ok(hr == WR_E_XMLNSPREFIXDECLARATION, "got 0x%08x\n", hr); - - hr = IXmlWriter_WriteAttributeString(writer, NULL, xmlnsW, NULL, uri2W); -todo_wine - ok(hr == WR_E_NSPREFIXDECLARED, "got 0x%08x\n", hr); - hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, NULL, bW); todo_wine ok(hr == WR_E_DUPLICATEATTRIBUTE, "got 0x%08x\n", hr); @@ -1585,7 +1818,8 @@ START_TEST(writer) test_writer_state(); test_writeroutput(); test_writestartdocument(); - test_writestartelement(); + test_WriteStartElement(); + test_WriteElementString(); test_writeendelement(); test_flush(); test_omitxmldeclaration(); diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index 88f75b6e20..c0260ae473 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -857,6 +857,9 @@ static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR pr ; }
+ if (!local_name) + return E_INVALIDARG; + write_encoding_bom(This); write_node_indent(This); write_output_buffer(This->output, ltW, ARRAY_SIZE(ltW));
Signed-off-by: Nikolay Sivov nsivov@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__ */
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/tests/writer.c | 6 +++--- dlls/xmllite/writer.c | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 7be885427b..cf43f30f6b 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -858,8 +858,8 @@ static void test_WriteStartElement(void) { { "prefix", "local", "uri", "<prefix:local xmlns:prefix="uri" />", "<prefix:local", S_OK, 1 }, { NULL, "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1 }, - { "", "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1, 1 }, - { "", "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1, 1}, + { "", "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1 }, + { "", "local", "uri", "<local xmlns="uri" />", "<local", S_OK, 1 },
{ "prefix", NULL, NULL, NULL, NULL, E_INVALIDARG }, { NULL, NULL, "uri", NULL, NULL, E_INVALIDARG }, @@ -953,7 +953,7 @@ static void test_WriteStartElement(void) uriW = strdupAtoW(start_element_tests[i].uri);
hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW); - todo_wine_if(i >= 7) + todo_wine_if(i >= 11) ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
if (SUCCEEDED(start_element_tests[i].hr)) diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index a6cd1aa200..f9e8c666b2 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -20,7 +20,9 @@ */ #define COBJMACROS
+#include <assert.h> #include <stdarg.h> + #include "windef.h" #include "winbase.h" #include "objbase.h" @@ -296,7 +298,9 @@ static HRESULT write_output_buffer_quoted(xmlwriteroutput *output, const WCHAR * static HRESULT write_output_qname(xmlwriteroutput *output, const WCHAR *prefix, int prefix_len, const WCHAR *local_name, int local_len) { - if (prefix) { + assert(prefix_len >= 0 && local_len >= 0); + + if (prefix_len) { static const WCHAR colW[] = {':'}; write_output_buffer(output, prefix, prefix_len); write_output_buffer(output, colW, ARRAY_SIZE(colW)); @@ -1253,7 +1257,9 @@ static HRESULT WINAPI xmlwriter_WriteStartDocument(IXmlWriter *iface, XmlStandal static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR prefix, LPCWSTR local_name, LPCWSTR uri) { xmlwriter *This = impl_from_IXmlWriter(iface); + int prefix_len, local_len; struct element *element; + HRESULT hr;
TRACE("(%p)->(%s %s %s)\n", This, wine_dbgstr_w(prefix), wine_dbgstr_w(local_name), wine_dbgstr_w(uri));
@@ -1272,6 +1278,13 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre ; }
+ /* 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; + /* close pending element */ if (This->starttagopen) write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW)); @@ -1289,7 +1302,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, -1, local_name, -1); + write_output_qname(This->output, prefix, prefix_len, local_name, local_len); writer_inc_indent(This);
return S_OK;