http://bugs.winehq.org/show_bug.cgi?id=60399 Bug ID: 60399 Summary: C++ exception reproducer (ARM64): crashes when a DLL function ends with a call to a noreturn throw helper Product: Wine Version: 11.18 Hardware: aarch64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: msvcirt Assignee: wine-bugs@list.winehq.org Reporter: micronenator@gmail.com Target Milestone: --- Distribution: --- Created attachment 82197 --> http://bugs.winehq.org/attachment.cgi?id=82197 reproducer and logs A small ARM64 C++ exception test crashes in Wine's C++ runtime when a DLL function ends with a call to a noreturn throw helper, as MSVC lays such functions out. The reproducer (source and binaries) is attached. Tested on native aarch64 Ubuntu 24.04 with WineHQ master 4e819f054dd2d9ee855ee3f1e30d8c1bb8f80fcf (wine-11.18), built from official source (headless: --without-x and some optional libraries disabled; the test is a console program). Clean WINEPREFIX, Wine's builtin DLLs, no DLL overrides. Steps to reproduce: 1. Unpack the attached cxxeh-bug.tar.gz and cd into reproducer/. 2. Run: wine ./cxxeh.exe 5 Expected: "caught: OK", exit code 0 (as for cases 1-4). Actual: exit code 5 after a NULL read in ucrtbase!cxx_frame_handler+0x15c (WineDbg: ldr w9, [x0] with x0 = 0). Cases 1-4 (throw/catch in the exe, inside a DLL, from a DLL to the exe, catch (...)) all pass. What case 5 does: A DLL function with a local destructor object ends with a call to a noreturn throw helper. Its ARM64 unwind range ends right after that call, matching MSVC's layout (clang's trailing brk is left out of the range), so the unwound return address lies just past the function. Analysis: In dlls/msvcrt/except.c, cxx_frame_handler() passes the raw dispatch->ControlPc to RtlLookupFunctionEntry() for the nested exception check and dereferences the result without checking it. The neighbouring exception state lookups use get_exception_pc(), which subtracts 4 on ARM64 when ControlPcIsUnwound is set. Using the adjusted PC and skipping the check when no function entry is found fixes case 5 here; cases 1-4 still pass. A patch will follow as a merge request. Controls: - Microsoft's ARM64 VC++ runtime next to the test, with an explicit native override for vcruntime140.dll: case 5 passes. (Not used in the reported run.) Real-world code: Seen first with Unity OpenXR 1.14.3 in an ARM64 Unity game under Proton 11.0: the game crashed when the tracking origin changed, and Microsoft's runtime avoided it. UnityOpenXR.dll is MSVC-built and has this layout: 449 of its functions use __CxxFrameHandler3, 25 of them end with a call to a noreturn throw helper, and for 18 of those the unwound return address lies in no function. The report above uses only the standalone test. Attachment: cxxeh-bug.tar.gz reproducer/ source, build script, layout tool, README and the small ARM64 test binaries (no Microsoft DLLs) logs/ terminal output as .txt files: baseline-case1..5.txt unmodified Wine (case 5 with WineDbg trace) baseline-seh.txt unmodified Wine, WINEDEBUG=+seh fixed-case1..5.txt patched Wine fixed-seh.txt patched Wine, WINEDEBUG=+seh control-case5.txt Microsoft runtime control prefix-init.txt clean prefix initialization -- 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.