[PATCH 0/4] MR9076: xmllite/tests: Add more tests for name validation when writing.
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9076
From: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> --- dlls/xmllite/tests/writer.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 92aa90d3984..021ac35da18 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -986,6 +986,26 @@ static void test_WriteStartElement(void) stream = writer_set_output(writer); + hr = IXmlWriter_WriteStartElement(writer, NULL, L".a", NULL); + todo_wine + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, NULL, L":a", NULL); + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, NULL, L"a:b", NULL); + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, L".prefix", L"a", L"uri"); + todo_wine + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, L":prefix", L"a", L"uri"); + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, L"prefix:b", L"a", L"uri"); + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_WriteStartElement(writer, NULL, L"a", NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -995,7 +1015,7 @@ static void test_WriteStartElement(void) hr = IXmlWriter_Flush(writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - CHECK_OUTPUT(stream, "<a"); + CHECK_OUTPUT_TODO(stream, "<a"); hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr); @@ -1714,8 +1734,10 @@ static void test_WriteAttributeString(void) { NULL, L"xmlns", L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 }, { L"xmlns", NULL, L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 }, { L"pre:fix", L"local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER }, + { L".prefix", L"local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER, 1, 1, 1 }, { L"pre:fix", NULL, L"uri", L"b", "<e />", "<e", E_INVALIDARG }, { L"prefix", L"lo:cal", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER }, + { L"prefix", L".local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER, 1, 1, 1 }, { L"xmlns", NULL, NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED }, { L"xmlns", NULL, L"", L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED }, { L"xmlns", L"", NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED }, @@ -3330,10 +3352,18 @@ static void test_WriteQualifiedName(void) hr = IXmlWriter_WriteQualifiedName(writer, L"a(a)b", L"cd"); ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + /* Wrong start char */ + hr = IXmlWriter_WriteQualifiedName(writer, L".a", L"cd"); + todo_wine + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteQualifiedName(writer, L":a", L"cd"); + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_Flush(writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - CHECK_OUTPUT(stream, + CHECK_OUTPUT_TODO(stream, "<ab:a"); IStream_Release(stream); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9076
From: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> --- dlls/xmllite/reader.c | 11 +++++++---- dlls/xmllite/tests/writer.c | 11 ++++------- dlls/xmllite/writer.c | 5 ++++- dlls/xmllite/xmllite_private.h | 1 + 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c index 1e146493aa6..27d4fd014c1 100644 --- a/dlls/xmllite/reader.c +++ b/dlls/xmllite/reader.c @@ -83,8 +83,6 @@ typedef enum StringValue_Last } XmlReaderStringValue; -BOOL is_namestartchar(WCHAR ch); - static const char *debugstr_nodetype(XmlNodeType nodetype) { static const char * const type_names[] = @@ -1480,9 +1478,9 @@ BOOL is_pubchar(WCHAR ch) (ch == '_') || (ch == '\r') || (ch == '\n'); } -BOOL is_namestartchar(WCHAR ch) +BOOL is_ncnamestartchar(WCHAR ch) { - return (ch == ':') || (ch >= 'A' && ch <= 'Z') || + return (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch >= 'a' && ch <= 'z') || (ch >= 0xc0 && ch <= 0xd6) || (ch >= 0xd8 && ch <= 0xf6) || @@ -1499,6 +1497,11 @@ BOOL is_namestartchar(WCHAR ch) (ch >= 0xfdf0 && ch <= 0xfffd); } +BOOL is_namestartchar(WCHAR ch) +{ + return is_ncnamestartchar(ch) || ch == ':'; +} + /* [4 NS] NCName ::= Name - (Char* ':' Char*) */ BOOL is_ncnamechar(WCHAR ch) { diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 021ac35da18..0fae2bbca88 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -987,7 +987,6 @@ static void test_WriteStartElement(void) stream = writer_set_output(writer); hr = IXmlWriter_WriteStartElement(writer, NULL, L".a", NULL); - todo_wine ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteStartElement(writer, NULL, L":a", NULL); @@ -997,7 +996,6 @@ static void test_WriteStartElement(void) ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteStartElement(writer, L".prefix", L"a", L"uri"); - todo_wine ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteStartElement(writer, L":prefix", L"a", L"uri"); @@ -1015,7 +1013,7 @@ static void test_WriteStartElement(void) hr = IXmlWriter_Flush(writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - CHECK_OUTPUT_TODO(stream, "<a"); + CHECK_OUTPUT(stream, "<a"); hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr); @@ -1734,10 +1732,10 @@ static void test_WriteAttributeString(void) { NULL, L"xmlns", L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 }, { L"xmlns", NULL, L"uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 }, { L"pre:fix", L"local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER }, - { L".prefix", L"local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER, 1, 1, 1 }, + { L".prefix", L"local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER }, { L"pre:fix", NULL, L"uri", L"b", "<e />", "<e", E_INVALIDARG }, { L"prefix", L"lo:cal", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER }, - { L"prefix", L".local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER, 1, 1, 1 }, + { L"prefix", L".local", L"uri", L"b", "<e />", "<e", WC_E_NAMECHARACTER }, { L"xmlns", NULL, NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED }, { L"xmlns", NULL, L"", L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED }, { L"xmlns", L"", NULL, L"uri", "<e />", "<e", WR_E_NSPREFIXDECLARED }, @@ -3354,7 +3352,6 @@ static void test_WriteQualifiedName(void) /* Wrong start char */ hr = IXmlWriter_WriteQualifiedName(writer, L".a", L"cd"); - todo_wine ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteQualifiedName(writer, L":a", L"cd"); @@ -3363,7 +3360,7 @@ static void test_WriteQualifiedName(void) hr = IXmlWriter_Flush(writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - CHECK_OUTPUT_TODO(stream, + CHECK_OUTPUT(stream, "<ab:a"); IStream_Release(stream); diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index c7dcafda875..6e343d0ade6 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -347,13 +347,16 @@ static struct ns *writer_find_ns(const xmlwriter *writer, const WCHAR *prefix, c static HRESULT is_valid_ncname(const WCHAR *str, int *out) { - int len = 0; + int len = 1; *out = 0; if (!str || !*str) return S_OK; + if (!is_ncnamestartchar(*str++)) + return WC_E_NAMECHARACTER; + while (*str) { if (!is_ncnamechar(*str)) diff --git a/dlls/xmllite/xmllite_private.h b/dlls/xmllite/xmllite_private.h index fc3e6d264e1..16336ff7eb9 100644 --- a/dlls/xmllite/xmllite_private.h +++ b/dlls/xmllite/xmllite_private.h @@ -61,6 +61,7 @@ xml_encoding get_encoding_from_codepage(UINT); BOOL is_ncnamechar(WCHAR ch); BOOL is_pubchar(WCHAR ch); BOOL is_namestartchar(WCHAR ch); +BOOL is_ncnamestartchar(WCHAR ch); BOOL is_namechar(WCHAR ch); /* [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9076
From: David Kahurani <k.kahurani(a)gmail.com> Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> --- dlls/xmllite/tests/writer.c | 8 +------- dlls/xmllite/writer.c | 27 ++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 0fae2bbca88..c109fedb072 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -3140,11 +3140,9 @@ static void test_WriteEntityRef(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEntityRef(writer, L""); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEntityRef(writer, NULL); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEntityRef(writer, L"name"); @@ -3155,7 +3153,6 @@ static void test_WriteEntityRef(void) writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration); hr = IXmlWriter_WriteEntityRef(writer, L"name"); - todo_wine ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#lx.\n", hr); IStream_Release(stream); @@ -3168,7 +3165,6 @@ static void test_WriteEntityRef(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEntityRef(writer, L"na:me"); - todo_wine ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_Flush(writer); @@ -3187,11 +3183,9 @@ static void test_WriteEntityRef(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEntityRef(writer, L"name"); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEntityRef(writer, L".name"); - todo_wine ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEndDocument(writer); @@ -3203,7 +3197,7 @@ static void test_WriteEntityRef(void) hr = IXmlWriter_Flush(writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - CHECK_OUTPUT_TODO(stream, + CHECK_OUTPUT(stream, "<a>&name;</a>"); IStream_Release(stream); diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index 6e343d0ade6..be9666d6fd3 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -1567,25 +1567,42 @@ static HRESULT WINAPI xmlwriter_WriteEndElement(IXmlWriter *iface) return hr; } -static HRESULT WINAPI xmlwriter_WriteEntityRef(IXmlWriter *iface, LPCWSTR pwszName) +static HRESULT WINAPI xmlwriter_WriteEntityRef(IXmlWriter *iface, const WCHAR *name) { - xmlwriter *This = impl_from_IXmlWriter(iface); + xmlwriter *writer = impl_from_IXmlWriter(iface); + int name_len; + HRESULT hr; - FIXME("%p %s\n", This, wine_dbgstr_w(pwszName)); + TRACE("%p, %s.\n", iface, wine_dbgstr_w(name)); - switch (This->state) + if (is_empty_string(name)) + return E_INVALIDARG; + + if (FAILED(hr = is_valid_ncname(name, &name_len))) + return hr; + + switch (writer->state) { case XmlWriterState_Initial: return E_UNEXPECTED; case XmlWriterState_InvalidEncoding: return MX_E_ENCODING; + case XmlWriterState_Ready: case XmlWriterState_DocClosed: + writer->state = XmlWriterState_DocClosed; return WR_E_INVALIDACTION; + case XmlWriterState_ElemStarted: + hr = writer_close_starttag(writer); + break; default: ; } - return E_NOTIMPL; + write_output(writer, L"&", 1, &hr); + write_output(writer, name, name_len, &hr); + write_output(writer, L";", 1, &hr); + + return hr; } static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9076
From: David Kahurani <k.kahurani(a)gmail.com> Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> --- dlls/xmllite/tests/writer.c | 14 ++++----- dlls/xmllite/writer.c | 62 +++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index c109fedb072..760029ee670 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -3037,11 +3037,9 @@ static void test_WriteName(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteName(writer, L""); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteName(writer, NULL); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteName(writer, L"name"); @@ -3063,7 +3061,12 @@ static void test_WriteName(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteName(writer, L"a:a:a"); - todo_wine + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteName(writer, L".a"); + ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); + + hr = IXmlWriter_WriteName(writer, L":a"); ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_Flush(writer); @@ -3085,7 +3088,6 @@ static void test_WriteName(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteName(writer, L"name"); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteFullEndElement(writer); @@ -3095,7 +3097,6 @@ static void test_WriteName(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteName(writer, L"ab:name"); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteEndDocument(writer); @@ -3104,7 +3105,7 @@ static void test_WriteName(void) hr = IXmlWriter_Flush(writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - CHECK_OUTPUT_TODO(stream, + CHECK_OUTPUT(stream, "<root><a>name</a><b>ab:name</b></root>"); IStream_Release(stream); @@ -3117,7 +3118,6 @@ static void test_WriteName(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_WriteName(writer, L""); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); hr = IXmlWriter_Flush(writer); diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index be9666d6fd3..e39255b99d7 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -433,6 +433,45 @@ static HRESULT is_valid_name(const WCHAR *str, unsigned int *out) return S_OK; } +static HRESULT is_valid_qname(const WCHAR *str, unsigned int *out) +{ + int len = 1; + + *out = 0; + + if (!is_ncnamestartchar(*str++)) + return WC_E_NAMECHARACTER; + + while (*str && is_ncnamechar(*str)) + { + len++; + str++; + } + + if (!*str) + { + *out = len; + return S_OK; + } + + if (*str && *str != ':') + return WC_E_NAMECHARACTER; + str++; + len++; + + while (*str && is_ncnamechar(*str)) + { + len++; + str++; + } + + if (*str) + return WC_E_NAMECHARACTER; + + *out = len; + return S_OK; +} + static HRESULT is_valid_pubid(const WCHAR *str, unsigned int *out) { unsigned int len = 0; @@ -1655,27 +1694,38 @@ static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface) return hr; } -static HRESULT WINAPI xmlwriter_WriteName(IXmlWriter *iface, LPCWSTR pwszName) +static HRESULT WINAPI xmlwriter_WriteName(IXmlWriter *iface, const WCHAR *name) { - xmlwriter *This = impl_from_IXmlWriter(iface); + xmlwriter *writer = impl_from_IXmlWriter(iface); + unsigned int name_len; + HRESULT hr; - FIXME("%p %s\n", This, wine_dbgstr_w(pwszName)); + TRACE("%p, %s.\n", iface, wine_dbgstr_w(name)); + + if (is_empty_string(name)) + return E_INVALIDARG; + + if (FAILED(hr = is_valid_qname(name, &name_len))) + return hr; - switch (This->state) + switch (writer->state) { case XmlWriterState_Initial: return E_UNEXPECTED; case XmlWriterState_Ready: case XmlWriterState_DocClosed: - This->state = XmlWriterState_DocClosed; + writer->state = XmlWriterState_DocClosed; return WR_E_INVALIDACTION; case XmlWriterState_InvalidEncoding: return MX_E_ENCODING; + case XmlWriterState_ElemStarted: + hr = writer_close_starttag(writer); + break; default: ; } - return E_NOTIMPL; + return write_output(writer, name, name_len, &hr); } static HRESULT WINAPI xmlwriter_WriteNmToken(IXmlWriter *iface, const WCHAR *nmtoken) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9076
This merge request was approved by Nikolay Sivov. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9076
participants (3)
-
David Kahurani -
Nikolay Sivov -
Nikolay Sivov (@nsivov)