Dmitry Timoshkov : gdi32: Do not crash on an invalid pointer passed to AddFontMemResourceEx.

Alexandre Julliard julliard at winehq.org
Mon Aug 2 11:03:56 CDT 2010


Module: wine
Branch: master
Commit: 81557b5e21551150296b811f7617bca4a75a0c70
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=81557b5e21551150296b811f7617bca4a75a0c70

Author: Dmitry Timoshkov <dmitry at codeweavers.com>
Date:   Mon Aug  2 15:35:04 2010 +0900

gdi32: Do not crash on an invalid pointer passed to AddFontMemResourceEx.

---

 dlls/gdi32/font.c       |   21 +++++++++++-
 dlls/gdi32/freetype.c   |    2 +-
 dlls/gdi32/tests/font.c |   83 +++++++++++++++++++++++++++++++++++++++++++++++
 include/wingdi.h        |    1 +
 4 files changed, 105 insertions(+), 2 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 29281f9..9ebf7b3 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -33,6 +33,7 @@
 #include "winnls.h"
 #include "wownt32.h"
 #include "gdi_private.h"
+#include "wine/exception.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
 
@@ -3184,7 +3185,25 @@ BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
  */
 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
 {
-    return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
+    HANDLE ret;
+    DWORD num_fonts;
+
+    ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
+    if (ret)
+    {
+        __TRY
+        {
+            *pcFonts = num_fonts;
+        }
+        __EXCEPT_PAGE_FAULT
+        {
+            WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
+            RemoveFontMemResourceEx(ret);
+            ret = 0;
+        }
+        __ENDTRY
+    }
+    return ret;
 }
 
 /***********************************************************************
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 532278c..e2db1aa 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -2151,7 +2151,7 @@ HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD
         {
             TRACE("AddFontToList failed\n");
             HeapFree(GetProcessHeap(), 0, pFontCopy);
-            return NULL;
+            return 0;
         }
         /* FIXME: is the handle only for use in RemoveFontMemResourceEx or should it be a true handle?
          * For now return something unique but quite random
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index d89132d..bbb54cd 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -44,6 +44,8 @@ DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi,
 DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
 BOOL  (WINAPI *pGdiRealizationInfo)(HDC hdc, DWORD *);
 HFONT (WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDV *);
+HANDLE (WINAPI *pAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
+BOOL  (WINAPI *pRemoveFontMemResourceEx)(HANDLE);
 
 static HMODULE hgdi32 = 0;
 
@@ -59,6 +61,8 @@ static void init(void)
     pGetGlyphIndicesW = (void *)GetProcAddress(hgdi32, "GetGlyphIndicesW");
     pGdiRealizationInfo = (void *)GetProcAddress(hgdi32, "GdiRealizationInfo");
     pCreateFontIndirectExA = (void *)GetProcAddress(hgdi32, "CreateFontIndirectExA");
+    pAddFontMemResourceEx = (void *)GetProcAddress(hgdi32, "AddFontMemResourceEx");
+    pRemoveFontMemResourceEx = (void *)GetProcAddress(hgdi32, "RemoveFontMemResourceEx");
 }
 
 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
@@ -3142,6 +3146,84 @@ static void test_CreateFontIndirectEx(void)
     DeleteObject(hfont);
 }
 
+static void free_font(void *font)
+{
+    UnmapViewOfFile(font);
+}
+
+static void *load_font(const char *font_name, DWORD *font_size)
+{
+    char file_name[MAX_PATH];
+    HANDLE file, mapping;
+    void *font;
+
+    if (!GetWindowsDirectory(file_name, sizeof(file_name))) return NULL;
+    strcat(file_name, "\\fonts\\");
+    strcat(file_name, font_name);
+
+    file = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
+    if (file == INVALID_HANDLE_VALUE) return NULL;
+
+    *font_size = GetFileSize(file, NULL);
+
+    mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
+    if (!mapping)
+    {
+        CloseHandle(file);
+        return NULL;
+    }
+
+    font = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+
+    CloseHandle(file);
+    CloseHandle(mapping);
+    return font;
+}
+
+static void test_AddFontMemResource(void)
+{
+    void *font;
+    DWORD font_size, num_fonts;
+    HANDLE ret;
+
+    if (!pAddFontMemResourceEx || !pRemoveFontMemResourceEx)
+    {
+        win_skip("AddFontMemResourceEx is not available on this platform\n");
+        return;
+    }
+
+    font = load_font("sserife.fon", &font_size);
+    if (!font)
+    {
+        skip("Unable to locate and load font sserife.fon\n");
+        return;
+    }
+
+    num_fonts = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = pAddFontMemResourceEx(font, font_size, NULL, &num_fonts);
+    ok(ret != 0, "AddFontMemResourceEx error %d\n", GetLastError());
+    ok(num_fonts != 0xdeadbeef, "number of loaded fonts should not be 0xdeadbeef\n");
+    ok(num_fonts != 0, "number of loaded fonts should not be 0\n");
+
+    free_font(font);
+
+    SetLastError(0xdeadbeef);
+    ok(pRemoveFontMemResourceEx(ret), "RemoveFontMemResourceEx error %d\n", GetLastError());
+
+    /* test invalid pointer to number of loaded fonts */
+    font = load_font("sserife.fon", &font_size);
+    ok(font != NULL, "Unable to locate and load font sserife.fon\n");
+
+    ret = pAddFontMemResourceEx(font, font_size, NULL, (void *)0xdeadbeef);
+    ok(!ret, "AddFontMemResourceEx should fail\n");
+
+    ret = pAddFontMemResourceEx(font, font_size, NULL, NULL);
+    ok(!ret, "AddFontMemResourceEx should fail\n");
+
+    free_font(font);
+}
+
 START_TEST(font)
 {
     init();
@@ -3162,6 +3244,7 @@ START_TEST(font)
     test_nonexistent_font();
     test_orientation();
     test_height_selection();
+    test_AddFontMemResource();
 
     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
      * I'd like to avoid them in this test.
diff --git a/include/wingdi.h b/include/wingdi.h
index 3f5058f..fa68c23 100644
--- a/include/wingdi.h
+++ b/include/wingdi.h
@@ -3630,6 +3630,7 @@ WINGDIAPI UINT        WINAPI RealizePalette(HDC);
 WINGDIAPI BOOL        WINAPI Rectangle(HDC,INT,INT,INT,INT);
 WINGDIAPI BOOL        WINAPI RectInRegion(HRGN,const RECT *);
 WINGDIAPI BOOL        WINAPI RectVisible(HDC,const RECT*);
+WINGDIAPI BOOL        WINAPI RemoveFontMemResourceEx(HANDLE);
 WINGDIAPI BOOL        WINAPI RemoveFontResourceA(LPCSTR);
 WINGDIAPI BOOL        WINAPI RemoveFontResourceW(LPCWSTR);
 #define                      RemoveFontResource WINELIB_NAME_AW(RemoveFontResource)




More information about the wine-cvs mailing list