[PATCH 3/4] uxtheme: Protect CloseThemeData() from invalid input.

Zhiyi Zhang zzhang at codeweavers.com
Tue Nov 30 00:51:18 CST 2021


From: Dmitry Timoshkov <dmitry at baikal.ru>

With test case by Michael Müller <michael at fds-team.de>.

Some applications closes the same HTHEME more than once, causing use-after-free. HTHEME is a handle
rather than a pointer. Some testing shows that it's a handle starting from 0x10000 or 0x20000. Each
new handle increments from the first handle and closing handles decrements it. I prefer not to
implement this handle to data map for now because it will likely hurt performance.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=29974
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/uxtheme/msstyles.c     | 22 ++++++++++++++++++++++
 dlls/uxtheme/msstyles.h     |  1 +
 dlls/uxtheme/tests/system.c |  2 ++
 3 files changed, 25 insertions(+)

diff --git a/dlls/uxtheme/msstyles.c b/dlls/uxtheme/msstyles.c
index c0f626d54aa..d834c9604b9 100644
--- a/dlls/uxtheme/msstyles.c
+++ b/dlls/uxtheme/msstyles.c
@@ -32,6 +32,7 @@
 
 #include "msstyles.h"
 
+#include "wine/exception.h"
 #include "wine/debug.h"
 #include "wine/heap.h"
 
@@ -48,6 +49,8 @@ static HRESULT MSSTYLES_GetFont (LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPC
 
 #define MSSTYLES_VERSION 0x0003
 
+#define THEME_CLASS_SIGNATURE 0x12bc6d83
+
 static PTHEME_FILE tfActiveTheme;
 
 /***********************************************************************/
@@ -203,6 +206,7 @@ void MSSTYLES_CloseThemeFile(PTHEME_FILE tf)
                         pcls->partstate = ps->next;
                         heap_free(ps);
                     }
+                    pcls->signature = 0;
                     heap_free(pcls);
                 }
             }
@@ -441,6 +445,7 @@ static PTHEME_CLASS MSSTYLES_AddClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWST
     if(cur) return cur;
 
     cur = heap_alloc(sizeof(*cur));
+    cur->signature = THEME_CLASS_SIGNATURE;
     cur->hTheme = tf->hTheme;
     lstrcpyW(cur->szAppName, pszAppName);
     lstrcpyW(cur->szClassName, pszClassName);
@@ -1044,6 +1049,23 @@ PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszAppName, LPCWSTR pszClassList, U
  */
 HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc)
 {
+    __TRY
+    {
+        if (tc->signature != THEME_CLASS_SIGNATURE)
+            tc = NULL;
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        tc = NULL;
+    }
+    __ENDTRY
+
+    if (!tc)
+    {
+        WARN("Invalid theme class handle\n");
+        return E_HANDLE;
+    }
+
     MSSTYLES_CloseThemeFile (tc->tf);
     return S_OK;
 }
diff --git a/dlls/uxtheme/msstyles.h b/dlls/uxtheme/msstyles.h
index 12292cefae4..89937227ee2 100644
--- a/dlls/uxtheme/msstyles.h
+++ b/dlls/uxtheme/msstyles.h
@@ -49,6 +49,7 @@ typedef struct _THEME_PARTSTATE {
 struct _THEME_FILE;
 
 typedef struct _THEME_CLASS {
+    DWORD signature;
     HMODULE hTheme;
     struct _THEME_FILE* tf;
     WCHAR szAppName[MAX_THEME_APP_NAME];
diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c
index 10857115061..ebf66f6b5af 100644
--- a/dlls/uxtheme/tests/system.c
+++ b/dlls/uxtheme/tests/system.c
@@ -768,6 +768,8 @@ static void test_CloseThemeData(void)
     ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
     hRes = CloseThemeData(INVALID_HANDLE_VALUE);
     ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
+    hRes = CloseThemeData((HTHEME)0xdeadbeef);
+    ok(hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
 }
 
 static void test_buffer_dc_props(HDC hdc, const RECT *rect)
-- 
2.32.0




More information about the wine-devel mailing list