[Bug 59926] New: kernelbase: CharPrevA/CharPrevExA crash on NULL start pointer (MapleStory 216150 fails to launch)
http://bugs.winehq.org/show_bug.cgi?id=59926 Bug ID: 59926 Summary: kernelbase: CharPrevA/CharPrevExA crash on NULL start pointer (MapleStory 216150 fails to launch) Product: Wine Version: unspecified Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: major Priority: P2 Component: kernel32 Assignee: wine-bugs@list.winehq.org Reporter: f0rm4tm3@gmail.com Distribution: --- MapleStory (Steam app 216150) fails to launch under Wine: the process crashes with an access violation (0xc0000005) during startup. Root cause: CharPrevA() and CharPrevExA() in dlls/kernelbase/string.c dereference the start pointer in their loop condition without a NULL guard: LPSTR WINAPI CharPrevExA(WORD codepage, const char *start, const char *ptr, DWORD flags) { while (*start && (start < ptr)) /* crashes when start == NULL */ The game passes a NULL start pointer at launch, triggering the crash. CharPrevA() has the same bug. Suggested fix: return NULL early when start is NULL, matching how other kernelbase string helpers (e.g. StrChrA) already handle NULL input: if (!start) return NULL; while (*start && (start < ptr)) ... Reproduce: 1. Steam -> MapleStory (216150) under any recent Wine/Proton. 2. Launch -> process crashes at startup (0xc0000005 in kernelbase, inside CharPrevExA). Patch: two commits attached as git format-patch files (git am them): 1. kernelbase/tests: Add tests for CharPrevA. 2. kernelbase: Don't dereference NULL in CharPrevA/CharPrevExA. (I would have opened a merge request, but my gitlab.winehq.org account is awaiting validation and cannot fork; attaching the patch here instead.) -- 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=59926 --- Comment #1 from James M <f0rm4tm3@gmail.com> --- Created attachment 81264 --> http://bugs.winehq.org/attachment.cgi?id=81264 0001-kernelbase-tests-Add-tests-for-CharPrevA.patch -- 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=59926 --- Comment #2 from James M <f0rm4tm3@gmail.com> --- Created attachment 81265 --> http://bugs.winehq.org/attachment.cgi?id=81265 0002-kernelbase-Don-t-dereference-NULL-in-CharPrevA-CharP.patch -- 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=59926 --- Comment #3 from Nikolay Sivov <bunglehead@gmail.com> --- For the test please make sure it actually executes the case you are fixing. Right now test is not for the case you're fixing. -- 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=59926 Nikolay Sivov <bunglehead@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|major |normal -- 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=59926 Nikolay Sivov <bunglehead@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Component|kernel32 |user32 -- 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=59926 Nikolay Sivov <bunglehead@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Summary|kernelbase: |CharPrevA/CharPrevExA crash |CharPrevA/CharPrevExA crash |on NULL start pointer |on NULL start pointer |(MapleStory 216150 fails to |(MapleStory 216150 fails to |launch) |launch) | -- 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=59926 James M <f0rm4tm3@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #81264|0 |1 is obsolete| | Attachment #81265|0 |1 is obsolete| | --- Comment #4 from James M <f0rm4tm3@gmail.com> --- Created attachment 81270 --> http://bugs.winehq.org/attachment.cgi?id=81270 0001-kernelbase-tests-Add-tests-for-CharPrevA.patch (v2) -- 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=59926 --- Comment #5 from James M <f0rm4tm3@gmail.com> --- Created attachment 81271 --> http://bugs.winehq.org/attachment.cgi?id=81271 0002-kernelbase-Don-t-dereference-NULL-in-CharPrevA-CharP.patch (v2) -- 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=59926 --- Comment #6 from James M <f0rm4tm3@gmail.com> --- Thanks for the review. You're right — the test in the first patch didn't exercise the NULL start case; that case was only added in the second patch alongside the fix, so it could never demonstrate the bug on its own. Revised series attached: #81270 — kernelbase/tests: Add tests for CharPrevA. #81271 — kernelbase: Don't dereference NULL in CharPrevA/CharPrevExA. The test commit now drives the NULL-start path directly: it calls CharPrevA() and CharPrevExA() with start == NULL and a real, non-NULL current pointer (str + 1), rather than the degenerate start == ptr boundary. The return value is captured once so the ok() message doesn't re-invoke the function. Without the fix this NULL dereference crashes the test process; with the fix both calls return NULL and the assertions pass. The second patch is now the implementation change only (the two `if (!start) return NULL;` guards) — no test lines — so the split is test-then-fix as intended. Both patches apply cleanly with `git am` on current master. The earlier attachments (#81264, #81265) are marked obsolete. -- 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=59926 --- Comment #7 from Nikolay Sivov <bunglehead@gmail.com> --- Again, tests should demonstrate the problem, and should pass on Windows, not simply match your changes. If you're using any LLM tool to produce those changes, please don't. It's not worth it, and the diffs show that. -- 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=59926 --- Comment #8 from James M <f0rm4tm3@gmail.com> --- Created attachment 81272 --> http://bugs.winehq.org/attachment.cgi?id=81272 0001-kernelbase-tests-Add-tests-for-CharPrevA-NULL-start.patch (v3) -- 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=59926 --- Comment #9 from James M <f0rm4tm3@gmail.com> --- Created attachment 81273 --> http://bugs.winehq.org/attachment.cgi?id=81273 0002-kernelbase-Don-t-dereference-NULL-in-CharPrevA-CharPrevExA.patch (v3) -- 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=59926 --- Comment #10 from James M <f0rm4tm3@gmail.com> --- Thanks, I went back and measured native Windows behavior instead of asserting the behavior from my Wine patch. Since I'm on Linux and don't have a Windows machine, I used GitHub Actions windows-latest to run a native MSVC probe. Public repo: https://github.com/oldschoola/charprev-native-probe-20260628214054 Minimal v3 probe run: https://github.com/oldschoola/charprev-native-probe-20260628214054/actions/r... Build and run both succeeded. Output: PASS CharPrevA(str, str + 2): got 000000EB1DAFFD91 PASS CharPrevA(str, str): got 000000EB1DAFFD90 PASS CharPrevA(NULL, str + 1): got 000000EB1DAFFD90 PASS CharPrevA(NULL, str + 2): got 000000EB1DAFFD91 PASS CharPrevExA(CP_ACP, NULL, str + 1, 0): got 000000EB1DAFFD90 PASS CharPrevExA(CP_ACP, NULL, str + 2, 0): got 000000EB1DAFFD91 v3 CharPrev native behavior check passed So v2 was wrong: native Windows does not return NULL for these cases. It returns the previous character pointer. The v3 Wine conformance test encodes those Windows results directly, and wraps the NULL-start calls with Wine's exception macros (__TRY / __EXCEPT_PAGE_FAULT / __ENDTRY) so unpatched Wine reports a clean failure instead of crashing the whole test process. For the tested ASCII/CP_ACP cases, NULL start behaves as ptr - 1. I also ran an earlier exploratory probe that included CP932/DBCS: https://github.com/oldschoola/charprev-native-probe-20260628214054/actions/r... That showed CharPrevExA(932, NULL, dbcs + 2, 0) returned the DBCS lead byte, not a simple byte-wise ptr - 1. Because that expands the fix into DBCS backtracking semantics, I'm keeping CP932 out of v3 and will not claim a generic ptr - 1 rule for all code pages. Revised series attached: #81272 — kernelbase/tests: Add tests for CharPrevA NULL start. #81273 — kernelbase: Don't dereference NULL start in CharPrevA/CharPrevExA. -- 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=59926 --- Comment #11 from Ken Sharp <imwellcushtymelike@gmail.com> --- Which version of Wine? -- 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=59926 --- Comment #12 from James M <f0rm4tm3@gmail.com> --- wine-11.0 (Staging) -- 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=59926 Alex Henrie <alexhenrie24@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |alexhenrie24@gmail.com Keywords| |patch See Also| |https://bugs.winehq.org/sho | |w_bug.cgi?id=60069 --- Comment #13 from Alex Henrie <alexhenrie24@gmail.com> --- I sent https://gitlab.winehq.org/wine/wine/-/merge_requests/11485 before I found this bug report. I have now amended that MR to handle the cases from this bug as well. It turns out Windows just assumes that the start char passed to CharPrevExA is not a DBCS continuation byte and then it searches backwards, no loop required. -- 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=59926 Alex Henrie <alexhenrie24@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |9c62f14e696c6a303b3fa5fe633 | |1224c2dc8b587 Status|UNCONFIRMED |RESOLVED Resolution|--- |FIXED --- Comment #14 from Alex Henrie <alexhenrie24@gmail.com> --- Fixed by https://gitlab.winehq.org/wine/wine/-/commit/9c62f14e696c6a303b3fa5fe6331224... -- 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=59926 Alexandre Julliard <julliard@winehq.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED --- Comment #15 from Alexandre Julliard <julliard@winehq.org> --- Closing bugs fixed in 11.15. -- 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.
participants (1)
-
WineHQ Bugzilla