From: Damjan Jovanovic Subject: [PATCH v2] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped Message-Id: Date: Thu, 5 Dec 2019 21:02:02 +0200 msxml3 allows URL escape sequences even for C:\ style paths. eg. C:\Program%20Files\... Try 2 determines URL length dynamically, suppresses some compiler const warnings, and cleans up tests. Signed-off-by: Damjan Jovanovic --- dlls/msxml3/bsc.c | 33 ++++++++++++++++++++++++++++----- dlls/msxml3/tests/domdoc.c | 17 +++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/dlls/msxml3/bsc.c b/dlls/msxml3/bsc.c index df4cf37346..cc1c2a8685 100644 --- a/dlls/msxml3/bsc.c +++ b/dlls/msxml3/bsc.c @@ -244,30 +244,53 @@ static const struct IBindStatusCallbackVtbl bsc_vtbl = HRESULT create_uri(const WCHAR *url, IUri **uri) { + WCHAR *unescapedUrl = NULL; WCHAR fileUrl[INTERNET_MAX_URL_LENGTH]; + DWORD size; + HRESULT hr; TRACE("%s\n", debugstr_w(url)); - if (!PathIsURLW(url)) + size = 0; + hr = UrlUnescapeW((WCHAR*)url, (WCHAR*)url, &size, 0); + if (FAILED(hr) && hr != E_POINTER) + goto end; + unescapedUrl = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR)); + if (unescapedUrl == NULL) + { + hr = E_OUTOFMEMORY; + goto end; + } + hr = UrlUnescapeW((WCHAR*)url, unescapedUrl, &size, 0); + if (FAILED(hr)) + goto end; + + if (!PathIsURLW(unescapedUrl)) { WCHAR fullpath[MAX_PATH]; DWORD needed = ARRAY_SIZE(fileUrl); - if (!PathSearchAndQualifyW(url, fullpath, ARRAY_SIZE(fullpath))) + if (!PathSearchAndQualifyW(unescapedUrl, fullpath, ARRAY_SIZE(fullpath))) { WARN("can't find path\n"); - return E_FAIL; + hr = E_FAIL; + goto end; } if (FAILED(UrlCreateFromPathW(fullpath, fileUrl, &needed, 0))) { ERR("can't create url from path\n"); - return E_FAIL; + hr = E_FAIL; + goto end; } url = fileUrl; } - return CreateUri(url, Uri_CREATE_ALLOW_RELATIVE | Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, uri); + hr = CreateUri(url, Uri_CREATE_ALLOW_RELATIVE | Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, uri); + +end: + HeapFree(GetProcessHeap(), 0, unescapedUrl); + return hr; } HRESULT create_moniker_from_url(LPCWSTR url, IMoniker **mon) diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index c4337ab191..aa4c7a2832 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -10219,6 +10219,7 @@ static void test_load(void) VARIANT src; HRESULT hr; void* ptr; + int n; GetTempPathA(MAX_PATH, path); strcat(path, "winetest.xml"); @@ -10268,6 +10269,22 @@ static void test_load(void) ok(hr == S_OK, "got 0x%08x\n", hr); SysFreeString(bstr1); + /* Regular local path with some URL encoded characters. */ + strcpy(path2, path); + n = strlen(path2); + strcpy(&path2[n-1], "%6C"); /* C:\path\to\winetest.xm%6C */ + test_doc_load_from_path(doc, path2); + + /* Both spaces and %20s work. */ + GetTempPathA(MAX_PATH, path2); + strcat(path2, "wine test.xml"); + write_to_file(path2, win1252xml); + test_doc_load_from_path(doc, path2); + GetTempPathA(MAX_PATH, path2); + strcat(path2, "wine%20test.xml"); + test_doc_load_from_path(doc, path2); + DeleteFileA(path2); + DeleteFileA(path); /* load from existing path, no xml content */