[Bug 60225] New: FL Mafia Desktop 2.1.2 (Tauri app) crashes with page fault in ole32 at window creation
http://bugs.winehq.org/show_bug.cgi?id=60225 Bug ID: 60225 Summary: FL Mafia Desktop 2.1.2 (Tauri app) crashes with page fault in ole32 at window creation Product: Wine Version: 11.0 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: ole32 Assignee: wine-bugs@list.winehq.org Reporter: germanshtyrov@gmail.com Target Milestone: --- Distribution: --- FL Mafia Desktop 2.1.2 is a Tauri-based application (Rust + WebView2). On startup it consistently crashes with an unhandled page fault inside ole32, in the main thread, while the window is being created. No window is ever shown. The WebView2 child processes and DXVK initialise correctly; the crash happens in the main application thread, independently of the WebView2 renderer. The faulting instruction dereferences RAX, which holds an invalid pointer: ole32+0x35e48: movq (%rax), %rdx The backtrace shows the fault occurring inside ole32 while a window message is being dispatched through user32 into the application's window procedure. Suspected call path: the application vendor states that Tauri on Windows calls OleInitialize followed by RegisterDragDrop during window creation, before WebView2 is initialised, and that this is the code path executing at the point of the crash. This is consistent with the observed backtrace. Since this OleInitialize + RegisterDragDrop sequence is standard Tauri boilerplate on Windows rather than anything specific to this application, this may affect Tauri-based applications in general. Steps to reproduce: 1. Install a WebView2 runtime into the prefix 2. Install FL Mafia Desktop 2.1.2 (FL Mafia_2.1.2_x64-setup.exe) 3. Run flmafia-desktop.exe 4. No window appears; the process dies with a page fault Expected result: the application window opens. Tested Wine builds - all crash identically in ole32, always in the main thread: - wine-11.0 (vanilla, distro package): ole32+0x35e48 - wine-experimental.bleeding.edge.11.0.411656.20260810 (TkG "soda"): ole32+0x33aeb - wine-11.0 with "explorer /desktop=" virtual desktop: ole32+0x35e48. The application survives noticeably longer here (EdgeUpdate and the WebView2 GPU process both come up) but it still hits the same fault at the same offset. Possibly relevant observation: across three separate crash dumps the faulting pointer in RAX was 00001f04009ba070 00003b7400d21680 00004b5400ec83f0 In each case the low 32 bits look like a plausible heap address while the upper 32 bits look like unrelated garbage. This may suggest a value losing its upper half somewhere before being dereferenced as a pointer. System: Arch Linux, kernel 7.1.9-arch1-2, Intel Core i5-8350U, Intel UHD Graphics 620 (KBL GT2), Mesa 26.1.6. 64-bit prefix in Windows 10 mode, DXVK 3.0.2. Reproduced both under Bottles (flatpak) and with a plain wine invocation. Full logs and backtraces are attached. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60225 --- Comment #1 from germanshtyrov@gmail.com --- Created attachment 81924 --> http://bugs.winehq.org/attachment.cgi?id=81924 Backtraces from wine-11.0 and wine-experimental 11.0 (TkG) -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60225 --- Comment #2 from germanshtyrov@gmail.com --- Created attachment 81925 --> http://bugs.winehq.org/attachment.cgi?id=81925 Full console log, wine-11.0 with virtual desktop -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60225 --- Comment #3 from germanshtyrov@gmail.com --- Update from the application vendor, which narrows this down considerably. They looked at the logs and found that their main application window deliberately disables the system drag-and-drop hook, but the splash screen window - which is created first - does not. The crash therefore appears to happen on the splash window's drag-and-drop registration. That is consistent with the crash occurring before WebView2 is initialised: the splash window is created earlier. They will disable the hook for the splash screen as well. According to them this changes nothing on Windows and macOS. The change is expected in their next release, roughly within a week. I will report back here whether the crash is gone with that build. If it persists, the problem is deeper in ole32. Note on reproducing: this application requires a paid subscription, which makes it a poor test case for anyone wanting to debug this. If a freely available Tauri application shows the same fault, that would be a much better reproducer - Tauri creates the same drag-and-drop registration on Windows for every app, so this may well not be specific to this one. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60225 --- Comment #4 from germanshtyrov@gmail.com --- Root cause found, with a patch that fixes it. Please disregard the truncation guess in my first comment - that was wrong, there is no truncation involved. RegisterDragDrop stores the raw IDropTarget pointer in the window property "OleDropTargetInterface", and refuses windows owned by another process: GetWindowThreadProcessId(hwnd, &pid); if (pid != GetCurrentProcessId()) return DRAGDROP_E_INVALIDHWND; so that pointer is only ever valid inside the window's owning process. RevokeDragDrop (dlls/ole32/ole2.c) has no such check: drop_target = GetPropW(hwnd, prop_oledroptarget); if(drop_target) IDropTarget_Release(drop_target); IDropTarget_Release() dereferences the pointer to reach the vtable, which is the faulting instruction. When one process revokes a window that a different process registered, that read hits a foreign address. WINEDEBUG=+ole shows exactly that pairing - the WebView2 browser process registers, the host application process revokes the same window: 0188:trace:ole:RegisterDragDrop (000000000001009A,00001A64009A7D20) 00f4:trace:ole:RevokeDragDrop (000000000001009A) and in the resulting fault RAX is exactly that registered pointer while RBX is exactly that window: rax:00001a64009a7d20 rbx:000000000001009a ole32+0x35e48: movq (%rax), %rdx The application vendor independently confirmed the call path: Tauri calls OleInitialize and RegisterDragDrop during window creation, and their splash window - unlike their main window - does not disable it. This cannot be worked around by configuration. WebView2 is always out-of-process relative to its host application, so any Tauri application can hit it. I also tried forcing the WebView2 renderer and GPU in-process through the documented AdditionalBrowserArguments policy (--single-process): the internal children do collapse into one process (Chrome_InProcGpuThread and Chrome_InProcRendererThread appear), but the WebView2 browser process stays separate from the host and the crash is unchanged. Proposed fix - only release the raw pointer when the current process owns the window. The marshalled drop target and the window properties are cleaned up as before: --- a/dlls/ole32/ole2.c +++ b/dlls/ole32/ole2.c @@ -628,6 +628,7 @@ HRESULT WINAPI RevokeDragDrop(HWND hwnd) IStream *stream; IDropTarget *drop_target; HRESULT hr; + DWORD pid = 0; TRACE("(%p)\n", hwnd); @@ -643,8 +644,15 @@ HRESULT WINAPI RevokeDragDrop(HWND hwnd) if (!(map = get_droptarget_handle(hwnd))) return DRAGDROP_E_NOTREGISTERED; - drop_target = GetPropW(hwnd, prop_oledroptarget); - if(drop_target) IDropTarget_Release(drop_target); + /* The raw pointer in prop_oledroptarget is only valid in the process that + * called RegisterDragDrop, which is always the process owning the window. + * Releasing it from any other process dereferences a foreign address. */ + GetWindowThreadProcessId(hwnd, &pid); + if (pid == GetCurrentProcessId()) + { + drop_target = GetPropW(hwnd, prop_oledroptarget); + if(drop_target) IDropTarget_Release(drop_target); + } RemovePropW(hwnd, prop_oledroptarget); RemovePropW(hwnd, prop_marshalleddroptarget); Verified: I built Wine 11.0 with and without this change and ran the same application against both. Vanilla 11.0 crashes on every start, at the moment the splash window is destroyed. With the patch the application starts and keeps running; its own log gets past the point that used to be fatal: "close_splashscreen: main window shown" "close_splashscreen: splash destroyed" Patch script and the build workflow: https://github.com/G6rm0k/wine-ole32-fix One open question. Skipping the release when a foreign process revokes leaks the owner's reference. Mirroring RegisterDragDrop and rejecting the call outright with DRAGDROP_E_INVALIDHWND may be the more correct behaviour - I did not do that because it changes the return value for existing callers. Happy to redo it either way. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60225 --- Comment #5 from Ken Sharp <imwellcushtymelike@gmail.com> --- Did AI write that patch? Wine is already onto 11.16. https://gitlab.winehq.org/wine/wine/-/wikis/Download -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
deelnemers (1)
-
WineHQ Bugzilla