https://bugs.winehq.org/show_bug.cgi?id=47726
Bug ID: 47726 Summary: too many fonts cause memory corruption in Post Mortem and Still Life, need some limiting Product: Wine Version: 4.15 Hardware: x86 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: gdi32 Assignee: wine-bugs@winehq.org Reporter: zakarjor@yahoo.com Distribution: ---
I upgraded to Fedora 30 x86_64, and I now have a lot more fonts (lots of multilingual fonts) than before.
When starting Post Mortem or Still Life, I get the following error:
wine: Unhandled page fault on read access to 0x3235363d at address 0x24036828 (thread 0009), starting debugger...
Running with WINEDEBUG=warn+heap I get 0009:Call msvcrt.??@YAPAXI@Z(0000ffff) ret=2429ef15 0009:Call ntdll.RtlAllocateHeap(00410000,00000000,0000ffff) ret=7e558363 ... 0009:Call msvcrt.??@YAPAXI@Z(00000000) ret=2429ef15 0009:Call ntdll.RtlAllocateHeap(00410000,00000000,00000000) ret=7e558363 0009:Call ntdll.RtlAllocateHeap() retval=00480270 ret=7e558363 ... 0009:Call ntdll.RtlFreeHeap(00410000,00000000,00480270) ret=7e55842a 0009:err:heap:HEAP_ValidateInUseArena Heap 0x410000: block 0x480270 tail overwritten at 0x480270 (byte 0/24 == 0x33)
The register eax is supposed to be an address but looks like part of a font name in ASCII.
After going thru debugger, I found that there is a bug/limitation of string size of 64KB, and when the list of font names is just below 64KB (0xffff), and then appends one character, it goes over 64KB, but wraps around the size to 0 byte, which causes the memory corruption.
It would be nice to have gdi font module to limit the number of fonts to return to the caller, or have some way to filter the type of fonts to return (like don't return any Linux fonts), which should be consistent with Windows environment.
https://bugs.winehq.org/show_bug.cgi?id=47726
Zachary J zakarjor@yahoo.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Distribution|--- |Fedora Hardware|x86 |x86-64
https://bugs.winehq.org/show_bug.cgi?id=47726
Nikolay Sivov bunglehead@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|gdi32 |-unknown
--- Comment #1 from Nikolay Sivov bunglehead@gmail.com --- How exactly does this application ask for such names?
https://bugs.winehq.org/show_bug.cgi?id=47726
--- Comment #2 from Zachary J zakarjor@yahoo.com --- (In reply to Nikolay Sivov from comment #1)
How exactly does this application ask for such names?
0009: Call gdi32.EnumFontFamiliesA(00120051,00000000,2538e4b0,0034f510) ret=2538e71d
then some loops of LdrAccessRessource() and LdrFindResource_U(), then lots of repeated loops with calls of pairs of msvcrt.??@YAPAXI@Z() and ntdll.RtlAllocateHeap(00041000,00000000,000000XX), msvcrt.??@YAXPAX@Z(XXXXXXXX) and ntdll.RtlFreeHeap(00410000,00000000,XXXXXXXX) with increasing size (3rd parameter) in ntdll.RtlAllocateHeap(), before eventually page fault after allocating with size 0000ffff and then subsequently allocating with size 0000000 (which is smaller than 0000ffff) as shown in my previous comment.
So it looks like it's calling EnumFontFamiliesA() with a custom callback function, which seems to append font names into a string, every time resizing the string by allocating new larger string, copying over old string to new string, then deleting the old string.
I checked the wine source and EnumFontFamiliesA() eventually calls freetype_EnumFonts() in dlls/gdi32/freetype.c, which seems to indicate there is a way to filter the list of font names by character set.
I wonder if this is something I can do now. How do I make the function only send US ASCII fonts?
Currently I have en_US.utf8 character set, and I guess that's why it sends names of all the multilingual fonts. I've tried setting LANG=C but that didn't help.
https://bugs.winehq.org/show_bug.cgi?id=47726
--- Comment #3 from Zachary J zakarjor@yahoo.com --- WINEDEBUG=+font shows that charset = 0: 0024:trace:font:freetype_EnumFonts facename = L"Tahoma" charset 0
Is there a way to set charset to something like ASCII in Linux command line before running wine, and will that force the EnumFontFamiliesA() function to filter only ASCII fonts?
https://bugs.winehq.org/show_bug.cgi?id=47726
Zachary J zakarjor@yahoo.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|-unknown |gdi32
https://bugs.winehq.org/show_bug.cgi?id=47726
--- Comment #4 from Nikolay Sivov bunglehead@gmail.com --- You can make any modification you want, but is there a bug really?
https://bugs.winehq.org/show_bug.cgi?id=47726
--- Comment #5 from Zachary J zakarjor@yahoo.com --- Ok, here my finding so far.
It looks like the game is sending parameter lpFamily=NULL in EnumFontFamiliesA(), and freetype_EnumFonts() sets lf.lfCharSet = DEFAULT_CHARSET (1).
If I replace DEFAULT_CHARSET (1) with ANSI_CHARSET (0) in the debugger, the game runs.
(In reply to Nikolay Sivov from comment #4)
You can make any modification you want, but is there a bug really?
How do I make wine think that DEFAULT_CHARSET is ANSI_CHARSET instead of some other multilingual character set, short of patching wine?
I guess it would be a request for feature if this is not possible.
https://bugs.winehq.org/show_bug.cgi?id=47726
Bernhard Übelacker bernhardu@mailbox.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |bernhardu@mailbox.org
--- Comment #6 from Bernhard Übelacker bernhardu@mailbox.org --- Another application not prepared for too many installed fonts seems to be the Lotus Notes 6.5 client. https://bugs.debian.org/946699
https://bugs.winehq.org/show_bug.cgi?id=47726
qsniyg qsniyg@mail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |qsniyg@mail.com
--- Comment #7 from qsniyg qsniyg@mail.com --- Under Windows EnumFontFamilies only enumerates a single font name per charset, whereas EnumFontFamiliesEx will enumerate all fonts.
Wine currently implements EnumFontFamilies on top of EnumFontFamiliesEx, which is incorrect as far as I can tell (I can't find any options to make EnumFontFamiliesEx behave like EnumFontFamilies).
I've sent in a patchset to fix this issue, but I'm not sure if it'll be accepted. It now exposes a separate issue where EnumFontFamilies doesn't list aliases (such as "Times New Roman CYR"), which therefore fails the "NULL family should enumerate RUSSIAN_CHARSET" test.
I forgot to mention this when sending in the patchset, which is why I'm mentioning it here (this bug is linked there).
Here are the patches:
https://source.winehq.org/patches/data/189695 (test case) https://source.winehq.org/patches/data/189696 (the patch itself)