gdi32: Do not crash on an invalid pointer passed to AddFontMemResourceEx. Take 2.
Dmitry Timoshkov
dmitry at codeweavers.com
Mon Aug 2 01:35:04 CDT 2010
The test passes under XP. I've also changed WineEngAddFontMemResourceEx
to return 0 on all code paths for consistency.
This patch fixes the problem reported in the bug 23849.
This version of the patch links to AddFontMemResourceEx and RemoveFontMemResourceEx
at run-time to make the tests run under Win9x and NT4.
---
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)
--
1.7.0.6
More information about the wine-patches
mailing list