https://bugs.winehq.org/show_bug.cgi?id=56367
Andrew Nguyen arethusa26@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 Status|UNCONFIRMED |NEW
--- Comment #1 from Andrew Nguyen arethusa26@gmail.com --- I can confirm the Tomb Raider 3 demo crashes on wine-9.4.
The read-only protection on the IDirectDraw vtable concealed a buffer overrun that becomes apparent when the vtable was made writable. The overrun occurs when the game modifies during IDirect3D2::EnumDevices enumeration the contents of the buffer holding the device description string for the DirectDraw reference device. The buffer happens to be located just before the IDirectDraw vtable:
Thread 1 "01c0" hit Hardware watchpoint 1: ddraw1_vtbl.Compact
Old value = (HRESULT (*)(IDirectDraw *)) 0x78267b60 <ddraw1_Compact> New value = (HRESULT (*)(IDirectDraw *)) 0x6e6f69
Wine-gdb> print ddraw1_vtbl $2 = {QueryInterface = 0x72614320, AddRef = 0x6d452064, Release = 0x74616c75, Compact = 0x6e6f69, CreateClipper = 0x7826d400 <ddraw1_CreateClipper>, CreatePalette = 0x78262ce0 <ddraw1_CreatePalette>, ... Wine-gdb> print (char *)&ddraw1_vtbl $3 = 0x7829c080 <ddraw1_vtbl> " Card Emulation" Wine-gdb> info symbol (char *)&ddraw1_vtbl - 1 reference_description + 23 in section .data of /home/arethusa/wine32/dlls/ddraw/i386-windows/ddraw.dll Wine-gdb> print (char *)&ddraw1_vtbl - 24 $4 = 0x7829c068 <reference_description> "Core Design MMX Hardware Card Emulation"
Reserving some extra space in the reference_description array declared inside the d3d3_EnumDevices implementation function avoids the buffer overrun and prevents the game from crashing.
I also notice that Windows 8 and newer versions implement an additional integrity protection of the IDirectDraw vtable. The function pointers in the vtable continue to be mutable, but when all IDirectDraw instances are destroyed and a new instance is created again, the original vtable function pointers are restored to undo any modifications.
This remediation logic is not necessary to resolve the crash in the Tomb Raider 3 demo but it would also have been an effective solution, since the game releases all DirectDraw instances it used for device enumeration before it creates a new one for the game launch.