From: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- dlls/msxml3/saxreader.c | 62 +++++++++++++++- dlls/msxml3/tests/saxreader.c | 135 ++++++++++++++++++++++++++++++++++ dlls/msxml6/tests/saxreader.c | 117 +++++++++++++++++++++++++++++ 3 files changed, 311 insertions(+), 3 deletions(-) diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c index 7846b512910..0321f18750f 100644 --- a/dlls/msxml3/saxreader.c +++ b/dlls/msxml3/saxreader.c @@ -455,6 +455,7 @@ struct saxreader BSTR xmldecl_version; BSTR xmldecl_standalone; BSTR xmldecl_encoding; + int max_xml_size; BSTR empty_bstr; MSXML_VERSION version; }; @@ -790,6 +791,7 @@ struct input_buffer UINT code_page; struct text_position position; size_t consumed; + size_t raw_size; bool last_cr; unsigned int chunk_size; @@ -1892,6 +1894,22 @@ static bool saxreader_reserve_buffer(struct saxlocator *locator, struct encoded_ buffer->written + size, sizeof(*buffer->data)); } +static bool saxreader_limit_xml_size(struct saxlocator *locator, ULONG read) +{ + if (locator->saxreader->max_xml_size > 0) + { + locator->buffer.raw_size += read; + if (locator->buffer.raw_size > locator->saxreader->max_xml_size * 1024) + { + saxreader_set_error(locator, E_FAIL); + locator->eos = true; + return false; + } + } + + return true; +} + static bool saxreader_stream_read(struct saxlocator *locator, void *buffer, ULONG size, ULONG *read) { HRESULT hr; @@ -1906,6 +1924,9 @@ static bool saxreader_stream_read(struct saxlocator *locator, void *buffer, ULON return false; } + if (!saxreader_limit_xml_size(locator, *read)) + return false; + locator->eos = *read == 0; return true; } @@ -5205,6 +5226,10 @@ static void saxreader_detect_encoding(struct saxlocator *locator) if (FAILED(hr = ISequentialStream_Read(locator->stream, raw->data, locator->buffer.chunk_size, &read))) return saxreader_set_error(locator, hr); + + if (!saxreader_limit_xml_size(locator, read)) + return; + if (!read) return saxreader_set_error(locator, E_SAX_MISSINGROOT); @@ -5562,6 +5587,18 @@ static HRESULT saxreader_put_handler_from_variant(struct saxreader *reader, enum return S_OK; } +static HRESULT saxreader_get_int_property(const VARIANT *v, int *ret) +{ + VARIANT dest; + + VariantInit(&dest); + if (FAILED(VariantChangeType(&dest, v, 0, VT_I4))) + return E_FAIL; + + *ret = V_I4(&dest); + return S_OK; +} + static HRESULT saxreader_put_property(struct saxreader *reader, const WCHAR *prop, VARIANT value, bool vbInterface) { VARIANT *v; @@ -5580,9 +5617,21 @@ static HRESULT saxreader_put_property(struct saxreader *reader, const WCHAR *pro if (!wcscmp(prop, L"max-xml-size")) { - if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK; - FIXME("(%p)->(%s): max-xml-size unsupported\n", reader, debugstr_variant(v)); - return E_NOTIMPL; + int size; + + if (FAILED(saxreader_get_int_property(&value, &size))) + return E_FAIL; + + if (size < 0) + return E_INVALIDARG; + + if (reader->version >= MSXML4 && size > 4194304) + return E_INVALIDARG; + if (reader->version < MSXML4 && size >= 4194304) + return E_INVALIDARG; + + reader->max_xml_size = size; + return S_OK; } if (!wcscmp(prop, L"max-element-depth")) @@ -5642,6 +5691,13 @@ static HRESULT saxreader_get_property(const struct saxreader *reader, const WCHA return return_bstr(reader->xmldecl_version, &V_BSTR(value)); } + if (!wcscmp(prop, L"max-xml-size")) + { + V_VT(value) = VT_I4; + V_I4(value) = reader->max_xml_size; + return S_OK; + } + FIXME("(%p)->(%s) unsupported property\n", reader, debugstr_w(prop)); return E_NOTIMPL; diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c index aca56a00de5..2bd439d0905 100644 --- a/dlls/msxml3/tests/saxreader.c +++ b/dlls/msxml3/tests/saxreader.c @@ -3256,6 +3256,140 @@ static void test_saxreader_properties(void) free_bstrs(); } +static void test_saxreader_max_xml_size(void) +{ + static const char test_text[] = + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa"; + const struct msxmlsupported_data_t *table = reader_support_data; + ISAXXMLReader *reader; + LARGE_INTEGER pos; + IStream *stream; + DWORD written; + VARIANT var; + HRESULT hr; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IStream_Write(stream, "<a>", 3, &written); + for (int i = 0; i < 20; ++i) + IStream_Write(stream, test_text, sizeof(test_text)-1, &written); + IStream_Write(stream, "</a>", 4, &written); + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + + while (table->clsid) + { + if (!is_clsid_supported(table->clsid, reader_support_data)) + { + table++; + continue; + } + + winetest_push_context("%s", table->name); + + hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_ISAXXMLReader, (void **)&reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + V_I4(&var) = 123; + hr = ISAXXMLReader_getProperty(reader, L"max-xml-size", &var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&var) == VT_I4, "Unexpected type %d.\n", V_VT(&var)); + ok(!V_I4(&var), "Unexpected value %ld.\n", V_I4(&var)); + + V_VT(&var) = VT_R4; + V_R4(&var) = 10.0; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + V_I4(&var) = 0; + hr = ISAXXMLReader_getProperty(reader, L"max-xml-size", &var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&var) == VT_I4, "Unexpected type %d.\n", V_VT(&var)); + ok(V_I4(&var) == 10, "Unexpected value %ld.\n", V_I4(&var)); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = _bstr_("abc"); + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(FAILED(hr), "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + V_I4(&var) = 0; + hr = ISAXXMLReader_getProperty(reader, L"max-xml-size", &var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&var) == VT_I4, "Unexpected type %d.\n", V_VT(&var)); + ok(V_I4(&var) == 10, "Unexpected value %ld.\n", V_I4(&var)); + + V_VT(&var) = VT_I4; + V_I4(&var) = -123; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 4194303; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 4194304; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + if (IsEqualGUID(table->clsid, &CLSID_SAXXMLReader40)) + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + else + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 4194305; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + /* Limit to 1K */ + V_VT(&var) = VT_I4; + V_I4(&var) = 1; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + + V_VT(&var) = VT_UNKNOWN; + V_UNKNOWN(&var) = (IUnknown *)stream; + hr = ISAXXMLReader_parse(reader, var); + ok(FAILED(hr), "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 3; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + + V_VT(&var) = VT_UNKNOWN; + V_UNKNOWN(&var) = (IUnknown *)stream; + hr = ISAXXMLReader_parse(reader, var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + ISAXXMLReader_Release(reader); + table++; + + winetest_pop_context(); + } + + free_bstrs(); + IStream_Release(stream); +} + struct feature_ns_entry_t { const GUID *guid; const char *clsid; @@ -6561,6 +6695,7 @@ START_TEST(saxreader) test_saxreader(); test_saxreader_properties(); + test_saxreader_max_xml_size(); test_saxreader_features(); test_saxreader_encoding(); test_saxreader_dispex(); diff --git a/dlls/msxml6/tests/saxreader.c b/dlls/msxml6/tests/saxreader.c index 52519cee939..56847bb8525 100644 --- a/dlls/msxml6/tests/saxreader.c +++ b/dlls/msxml6/tests/saxreader.c @@ -5172,6 +5172,122 @@ static void test_saxreader_pi(void) free_bstrs(); } +static void test_saxreader_max_xml_size(void) +{ + static const char test_text[] = + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa" + "aaaaaaaaaa"; + ISAXXMLReader *reader; + LARGE_INTEGER pos; + IStream *stream; + DWORD written; + VARIANT var; + HRESULT hr; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IStream_Write(stream, "<a>", 3, &written); + for (int i = 0; i < 20; ++i) + IStream_Write(stream, test_text, sizeof(test_text)-1, &written); + IStream_Write(stream, "</a>", 4, &written); + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + + hr = CoCreateInstance(&CLSID_SAXXMLReader60, NULL, CLSCTX_INPROC_SERVER, &IID_ISAXXMLReader, (void **)&reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + V_I4(&var) = 123; + hr = ISAXXMLReader_getProperty(reader, L"max-xml-size", &var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&var) == VT_I4, "Unexpected type %d.\n", V_VT(&var)); + ok(!V_I4(&var), "Unexpected value %ld.\n", V_I4(&var)); + + V_VT(&var) = VT_R4; + V_R4(&var) = 10.0; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + V_I4(&var) = 0; + hr = ISAXXMLReader_getProperty(reader, L"max-xml-size", &var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&var) == VT_I4, "Unexpected type %d.\n", V_VT(&var)); + ok(V_I4(&var) == 10, "Unexpected value %ld.\n", V_I4(&var)); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = _bstr_("abc"); + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(FAILED(hr), "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + V_I4(&var) = 0; + hr = ISAXXMLReader_getProperty(reader, L"max-xml-size", &var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&var) == VT_I4, "Unexpected type %d.\n", V_VT(&var)); + ok(V_I4(&var) == 10, "Unexpected value %ld.\n", V_I4(&var)); + + V_VT(&var) = VT_I4; + V_I4(&var) = -123; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 4194303; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 4194304; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 4194305; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + /* Limit to 1K */ + V_VT(&var) = VT_I4; + V_I4(&var) = 1; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + + V_VT(&var) = VT_UNKNOWN; + V_UNKNOWN(&var) = (IUnknown *)stream; + hr = ISAXXMLReader_parse(reader, var); + ok(FAILED(hr), "Unexpected hr %#lx.\n", hr); + + V_VT(&var) = VT_I4; + V_I4(&var) = 3; + hr = ISAXXMLReader_putProperty(reader, L"max-xml-size", var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + + V_VT(&var) = VT_UNKNOWN; + V_UNKNOWN(&var) = (IUnknown *)stream; + hr = ISAXXMLReader_parse(reader, var); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + ISAXXMLReader_Release(reader); + + free_bstrs(); + IStream_Release(stream); +} + START_TEST(saxreader) { HRESULT hr; @@ -5187,6 +5303,7 @@ START_TEST(saxreader) { test_saxreader(); test_saxreader_properties(); + test_saxreader_max_xml_size(); test_saxreader_features(); test_saxreader_encoding(); test_saxreader_dispex(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10172