This pull request has been designated for reprocessing. Please check back in a few minutes.

Fix UTF-8 filename #19497

Merged
digant73 opened 5:10pm on September 14, 2026 wanted to merge 81 Ξ” into rpcs3/rpcs3 master from
fix_utf8_filename

Pull Request Overview

  • Opened on September 14, 2026
  • Status Merged
  • Commit count 3 with first commit September 14, 2026

Total Delta

81 Total Diff Delta

Open Days

Open 5 weekdays

Test Delta

0 Diff Delta in Test Files
Breakdown by Phase

How long has this pull request spent in each phase of its lifecycle?

Fraction of total time Business days Phase
N/A 157.0 days Issue creation to work beginning
 
0.0 days Authoring 1 commit before pull request opened for review
 
0.0 days Awaiting first review
 
0.2 days Revising work with 2 commits in response to 1 review that left 7 comments
 
3.9 days Merge to deploy (still awaiting deployment)

Total time for pull request 0.2 business days from first commit authored to merge
Still awaiting deployment

Author avatar

Fix UTF-8 filename

Fix vfs::escape() to properly manage UTF-8 host-name conversion on any platform.
Analysis and fix proposed by Opus 5.

fixes #18152

What the fix covers:

Where it acts is vfs::escape(), the single
guest-name β†’ host-name conversion. So it covers every caller, not just the ticket's case:

path: PKG installation (the ticket #18152)
where: unpkg.cpp:964
────────────────────────────────────────
path: every open/stat/listing the game performs
where: vfs::get(), VFS.cpp:373
────────────────────────────────────────
path: trophy extraction
where: TRP.cpp:62
────────────────────────────────────────
path: mself extraction
where: mself.cpp:53
────────────────────────────────────────
path: savedata directory names
where: cellSaveData.cpp
────────────────────────────────────────
path: the reverse direction (the game sees its
original bytes again)
where: vfs::unescape from sys_fs, cellSearch,
cellSaveData, the media list overlay

Which forms of broken UTF-8 β€” all of them exhaustively covered by the probe (every single byte, every pair 0x80-0xFF Γ— 0x00-0xFF): invalid leading bytes (C0, C1, F5-FF), orphaned continuation bytes, truncated sequences β€” including truncation at the end of the name β€”, overlong encodings (E0 80…, F0 80…), surrogate halves (ED A0…), code points past U+10FFFF (F4 90…).

Per platform, and the gain is not macOS-only:
- macOS: from EILSEQ and an aborted installation to a file that gets created. That is the ticket #18152.
- Windows: MultiByteToWideChar used to replace every invalid byte with U+FFFD, so two names differing only in that byte collided, and unescape handed the game back U+FFFD instead of the original bytes. They are now distinct and reversible.
- Linux: the raw bytes worked; now they are explicit and consistent with the other platforms.

On top of that, the pre-existing bug found along the way: control characters (0x00-0x1F) in names now come back correctly from unescape, instead of leaking two bytes of the escape sequence into the result.

What it does NOT cover


  1. Content already installed. Files written by earlier builds keep their old names (U+FFFD on Windows, raw bytes on Linux): the emulator now looks for οΌ…8A and will not find them. They have to be reinstalled.

  2. Unicode normalization (NFC/NFD). The other thing the reporter suggested. A valid UTF-8 name in NFC that macOS gives back in NFD is not handled: unescape would hand the game bytes other than the ones it wrote. That is a separate and real problem on macOS, and this fix does not touch it.

  3. Name length. Every invalid byte becomes 5 bytes. A PKG name may reach PKG_MAX_FILENAME_SIZE = 256, so in the pathological case it expands to ~1280 bytes and blows past NAME_MAX (255) on Linux/macOS. The problem already exists with the current escapes (1 byte β†’ 3); the fix makes the extreme case worse, and no guard was added.

  4. Case sensitivity across different hosts: unchanged, pre-existing.

  5. Paths that never go through vfs::escape: files read inside an ISO image, for instance, never touch the host filesystem and need nothing.

Quick summary

On macOS (APFS), RPCS3 PKG installation aborts when extracting certain PSN packages containing filenames with invalid UTF-8 byte sequences (e.g., 204_οΏ½p.dds in NPEB00554's USRDIR/flashtextures/vault/concepts/), resulting in errno 92 (EILSEQ - Illegal byte sequence) during file creation. macOS enforces strict UTF-8 validation, whereas Windows and Linux permit irregular sequences and install successfully. Reproduction occurs reliably with Street Fighter III: 3rd Strike Online Edition (NPEB00554) on RPCS3 0.0.39-18761-ebf9374c. No sanitization or normalization of filenames is currently performed during extraction, causing the installer to fail entirely.

Details

Platform: macOS 26.1 (25B78) Hardware: MacBook Air M2 RPCS3 Version: 0.0.39-18761-ebf9374c (Alpha build dated approximately February 2026)

Describe the bug Installation of certain PSN PKG files fails during extraction on macOS when a filename in the package contains byte sequences that are invalid under strict UTF-8 encoding rules. macOS (APFS) rejects file creation attempts with errno 92 (EILSEQ - Illegal byte sequence), causing the entire PKG installer to abort.

Steps to reproduce

Launch RPCS3 on macOS (build 0.0.39-18761-ebf9374c or equivalent recent master). Ensure the latest PS3 firmware is installed via File β†’ Install Firmware. Navigate to File β†’ Install Packages/Raps/Edats, or drag-and-drop the .pkg file onto the RPCS3 window. Select the PKG for Street Fighter III: 3rd Strike Online Edition (title ID: NPEB00554). Monitor the installation progress until failure.

Expected behavior The PKG extractor should either:

Sanitize invalid byte sequences (e.g., replace with safe placeholders such as underscore or removal), Normalize/decompose filenames during path creation, or Provide a user-facing warning and option to proceed with skipped or renamed files while preserving game integrity.

Actual behavior Extraction halts with an error when attempting to create a file with an invalid sequence. Example from log: textE PKG: Failed to create file /Users/[username]/Emulation/RPCS3/dev_hdd0/game/NPEB00554/USRDIR/flashtextures/vault/concepts/204_οΏ½p.dds (is_buffered=0, did_overwrite=0, error=Unknown error [errno=92]) E PKG: Package failed to install ('/Users/[username]/Emulation/RPCS3/dev_hdd0/game/NPEB00554/') E GUI: Failed to install /path/to/Street-Fighter-III-3rd-Strike-Online-Edition_Full.pkg. The character "οΏ½" is the Unicode replacement glyph for the invalid byte(s) in the original filename. Logs / Attachments

Attach the complete RPCS3.log file generated during the failed attempt (located in the RPCS3 application directory or ~/Library/Application Support/rpcs3/). Relevant log excerpt provided above.

Additional context

The issue reproduces consistently with NPEB00554 and likely affects other PSN titles with similar filename encoding artifacts. Workarounds currently in use: Install the PKG on a Windows or Linux system/VM, then transfer the extracted dev_hdd0/game/NPEB00554/ folder to macOS. Source pre-extracted folder dumps of the title instead of using PKG files.

No existing open or closed issues in the RPCS3 repository directly address this macOS-specific errno 92 failure during PKG extraction (based on searches of GitHub issues and forums). macOS enforces strict UTF-8 validation for filenames, unlike more lenient handling on other platforms.

Possible implementation suggestions

Add filename sanitization logic in the PKG extraction code (e.g., in Emu/PKG.cpp or related path-handling routines) to replace invalid sequences with "_" or a fallback character. Introduce a macOS-specific code path that attempts to create files with normalized UTF-8 (using CFString or ICU libraries if feasible). Log a more descriptive error message (e.g., "macOS rejected filename due to invalid UTF-8 byte sequence") and optionally prompt the user for continuation with modifications.

This enhancement would significantly improve usability for macOS users encountering legacy PSN content. Thank you for your continued development of RPCS3 and for considering this report.

Attach a log file

  • SYS: RPCS3 v0.0.39-18761-ebf9374c Alpha | master
  • SYS: Apple M2 (4P+4E) | 8 Threads | 24.00 GiB RAM | TSC: 0.024GHz | FMA3
  • SYS: Operating system: macOS, Version: 26.1.0
  • SYS: Current Time: 2026-02-05T22:38:15
  • RSX: Found Vulkan-compatible GPU: 'Apple M2' running on driver 0.2.160
  • RSX: Found Vulkan-compatible GPU: 'Apple M2' running on driver 0.2.161
  • SYS: LLVM version: 21.1.8
  • SYS: Firmware version: 4.92 S UPDATER: RPCS3 is up to date! E PKG: Failed to create file /Users/[username]/Emulation/RPCS3/dev_hdd0/game/NPEB00554/USRDIR/flashtextures/vault/concepts/204_οΏ½p.dds (is_buffered=0, did_overwrite=0, error=Unknown error [errno=92]) E PKG: Package failed to install ('/Users/[username]/Emulation/RPCS3/dev_hdd0/game/NPEB00554/') E GUI: Failed to install /Users/e[username]/downloads//Street Fighter III - 3rd Strike Online Edition - Fight For The Future (NPEB00554 - Eng)/Street Fighter III - 3rd Strike Online Edition - Fight For The Future Install.pkg. S GUI: Successfully installed /Users/[username]/downloads/Street Fighter III - 3rd Strike Online Edition - Fight For The Future (NPEB00554 - Eng)/Street Fighter III - 3rd Strike Online Edition - Fight For The Future Fix.pkg (title_id=, title=Street Fighter III - 3rd Strike Online Edition - Fight For The Future Fix.pkg, version=). E PKG: Failed to create file /Users/ericspector/Emulation/RPCS3/dev_hdd0/game/NPEB00554/USRDIR/flashtextures/vault/concepts/204_οΏ½p.dds (is_buffered=0, did_overwrite=0, error=Unknown error [errno=92]) E PKG: Package failed to install ('/Users/[username]/Emulation/RPCS3/dev_hdd0/game/NPEB00554/') E GUI: Failed to install /Users/[username]/downloads/Street Fighter III - 3rd Strike Online Edition - Fight For The Future (NPEB00554 - Eng)/Street Fighter III - 3rd Strike Online Edition - Fight For The Future Install.pkg.

Attach capture files for visual issues

No response

System configuration

No response

Other details

No response

Comments Threads Pending Resolution

Resolved Comment Threads

Megamouse reviewed on September 14, 2026
rpcs3/Emu/VFS.cpp
Outdated
610
	{
611
		const uchar b = name[i];
612
613
		// A name is ASCII nearly every time, and every byte of a sequence is outside it, so this one test is all
614
		// such a name pays: "utf8_left" can only be standing on a byte of 0x80 and above