Page Fault With Freetype calls

Rein Klazes wijn at wanadoo.nl
Wed Nov 16 12:15:56 CST 2005


On Wed, 16 Nov 2005 09:05:45 -0500, in gmane.comp.emulators.wine.user
you wrote:

>The aforementioned 200 lines before the exception:

Thanks, that is enough. Here is an explanation and a patch cc 'd to the
patches list for inclusion in Wine. It would be nice if you could test
the patch (you need to compile wine from source for that). 

The programs does:
- call GetFontData with buffer size zero, to return the required buffer
size;
- do that for a number of font tables, adding the required sizes;;
- allocate a buffer large enough to store the data from all the
GetFontData calls;
- then filling the buffer with GetFontData calls, using the return value
of the call to calculate the remaining free size.

size=0
size = size + GetFontData(..., NULL, 0);
...
size = size + GetFontData(..., NULL, 0);
buf = VirtualAlloc( ..., size, ...);
ret = GetFontData(..., buf, size);
size = size - ret;
buf = size + ret;
ret = GetFontData(..., buf, size);

Here it goes wrong because Wine's GetFontData is not returning the
actual size of the data put in the buffer, but the buffer size it self.
The pointer to the buffer data is now pointing beyond the boundary. It
does not go wrong immediately because size is zero now, but at the
following GetFontData call the page fault is inevitable.

Changelog:
dlls/gdi	: font.c
Make GetFontData return the actual number of bytes put in the buffer.

Rein.
-------------- next part --------------
--- wine/dlls/gdi/font.c	2005-11-09 09:34:03.000000000 +0100
+++ mywine/dlls/gdi/font.c	2005-11-16 18:31:34.000000000 +0100
@@ -2588,9 +2588,17 @@ DWORD WINAPI GetFontData(HDC hdc, DWORD 
 
     if(!dc) return GDI_ERROR;
 
-    if(dc->gdiFont)
-      ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
-
+    if(dc->gdiFont) {
+        /* GetFontData must return the actual size of the data, 
+         * WineEngGetFontData only returns that when called with size
+         * zero, otherwise it returns the supplied size. Therefore we must
+         * call it twice. */
+        if( buffer && length) {
+          ret = WineEngGetFontData( dc->gdiFont, table, offset, NULL, 0);
+          if( ret < length) length = ret; 
+        }
+        ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
+    }
     GDI_ReleaseObj(hdc);
     return ret;
 }


More information about the wine-patches mailing list