[PATCH v2] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped

Damjan Jovanovic damjan.jov at gmail.com
Thu Dec 5 13:02:02 CST 2019


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 <damjan.jov at gmail.com>
---
 dlls/msxml3/bsc.c          | 33 ++++++++++++++++++++++++++++-----
 dlls/msxml3/tests/domdoc.c | 17 +++++++++++++++++
 2 files changed, 45 insertions(+), 5 deletions(-)
-------------- next part --------------
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 */


More information about the wine-devel mailing list