Skip to content

fix(libc): keep case comparisons in the guest C locale - #5002

Closed
QRMOE wants to merge 4 commits into
boykopovar:mainfrom
QRMOE:fix-guest-string-case-locale
Closed

QRMOE wants to merge 4 commits into
boykopovar:mainfrom
QRMOE:fix-guest-string-case-locale

Conversation

@QRMOE

@QRMOE QRMOE commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

Keep strcasecmp, strncasecmp and strcasestr in the guest C locale, independently of the host's character locale. The guest setlocale supports only C/POSIX, but these functions use host std::tolower. Under German_Germany.1252, main therefore compares bytes 0xc9 and 0xe9 as equal and reports a substring match, despite the guest C locale requiring distinct bytes.

Fold ASCII uppercase letters only, matching the existing guest character conversion tables and WebKit's case-folding helper. The behavior follows the C-locale cases of FreeBSD 11.4 strcasecmp.c and strcasestr.c. Other guest locales and console behavior remain unverified and are recorded in technical debt. No exports are added.

Tested

  • Final review check: merged this PR locally into main 075169f7b without conflicts. The explicit libs build and all six relevant checks passed: strings, character functions, classic locale, formatting, fnmatch and patched-library loading (7.57 seconds total). The new string check took 1.41 seconds. Main's helper accessor fix 3a9cc6368 resolves the earlier unwind import failure described below.

Windows, MinGW GCC 15.2, Release, BUILD_TESTING=ON, final base 6d7b87370:

  • The final regression fails with unchanged main library sources: Host locale German_Germany.1252 leaked into guest C comparisons: strcasecmp=0, strncasecmp=0, strcasestr=matched.
  • All 65,536 byte pairs are checked under the host C and German locales against an explicit letter table. Cover empty strings/needles, bounded nonterminated one-byte arrays, zero-length comparisons and both comparison and search results. The original host locale is restored. The exhaustive C-locale checks also run on other platforms.
  • Explicit libs build passed. Strings, character functions, classic locale, formatting and fnmatch passed on the final base (5/5); strings completed in 1.30 seconds. Conventions and whitespace passed. Nearby PRs fix(libc): convert the character argument of strrchr to char #4928, fix(libc): clear exhausted strtok continuation state #4625, fix(libc): terminate truncated wcsxfrm results #4633, fix(libc): reject invalid setlocale categories #3934 and fix(libc): use guest locale character conversions #1614 merged cleanly in local merge checks.
  • Patched-library loading passed on base 30caf2b2a. On final base 6d7b87370, it reports 121 libraries loaded and 3 failures: libSceAgc, libSceAgcDriver and libSceVideoOut. PE inspection identifies a missing host import _ZN10LibcUnwind11CursorSlotsE in libSceAgcDriver after the new main unwind-cursor change. This is independent of case folding; patched-library loading success on the final base is not claimed.
  • Full Windows build attempted on base 30caf2b2a; all unblocked components built, but Windows denied recreation of eight unrelated test outputs (guest_sce_net, guest_poll, guest_socket_read_write, guest_tcp, guest_socket_pair, guest_dup, guest_socket_events and guest_fstatfs). Avast logs automatic sandboxing of test programs. The local full-build limitation remains; local full-build success is not claimed.
  • No title playback or console measurement performed. No open PR implements the same case-folding fix.

Ready for maintainer review. Full Linux/Windows CI requires a maintainer's manual dispatch; marking this PR ready does not claim those jobs passed.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#3953 docs/dev/debt/libc.md L30
#3965 docs/dev/debt/libc.md L30
#5596 docs/dev/debt/libc.md L30
#5599 docs/dev/debt/libc.md L30

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title is known to reach this. With the queue at 700+ open PRs, please hold off on new PRs that don't name a title needing the change until it's down. If a title stops on this on current main, reopen with the title ID and the log line.

@QRMOE

QRMOE commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

Understood. I’ll leave this closed and revisit it only with a title ID and a current-main log showing the failure. I’ll hold off on new PRs without a title needing the change while the queue is high.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants