From d936d3fe3cbfde0ec28cfc3b20d23ce390276371 Mon Sep 17 00:00:00 2001 From: Rodrigo Iglesias <8595185+RigleGit@users.noreply.github.com> Date: Wed, 29 Apr 2026 22:05:00 +0200 Subject: [PATCH] Guard macOS filename normalization behind __APPLE__ --- src/common/string_util.cpp | 8 +++----- src/common/string_util.h | 4 +++- src/core/file_sys/disk_archive.cpp | 8 +++++--- src/tests/common/file_util.cpp | 6 +++--- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 8fd9a437b..3c695e08b 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -170,12 +170,12 @@ std::u16string UTF8ToUTF16(std::string_view input) { return boost::locale::conv::utf_to_utf(input.data(), input.data() + input.size()); } +#if defined(__APPLE__) // macOS filesystems may expose decomposed Unicode names through directory listings. // Normalize to NFC before passing names to guest APIs that expect stable text. -std::string NormalizeUTF8ToNFC(std::string_view input) { +std::string NormalizeNFDToNFC(std::string_view input) { const std::string fallback(input); -#if defined(__APPLE__) //Core Foundation string CFStringRef source = CFStringCreateWithBytes( kCFAllocatorDefault, @@ -221,10 +221,8 @@ std::string NormalizeUTF8ToNFC(std::string_view input) { output.resize(std::strlen(output.c_str())); return output; -#else - return fallback; -#endif } +#endif #ifdef _WIN32 static std::wstring CPToUTF16(u32 code_page, const std::string& input) { diff --git a/src/common/string_util.h b/src/common/string_util.h index 2d5355d2d..033c3ddb1 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -50,7 +50,9 @@ void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _P [[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); [[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); // Returns UTF-8 normalized to NFC on platforms that need explicit Unicode normalization. -[[nodiscard]] std::string NormalizeUTF8ToNFC(std::string_view input); +#if defined(__APPLE__) +[[nodiscard]] std::string NormalizeNFDToNFC(std::string_view input); +#endif #ifdef _WIN32 [[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input); diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index 3e81bf42c..969252cfa 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp @@ -66,7 +66,11 @@ u32 DiskDirectory::Read(const u32 count, Entry* entries) { const FileUtil::FSTEntry& file = *children_iterator; // Directory entries are exposed to the guest as UTF-16. Normalize host UTF-8 names first // so host Unicode normalization differences do not leak into guest-visible SDMC paths. - const std::string filename = Common::NormalizeUTF8ToNFC(file.virtualName); +#if defined(__APPLE__) + const std::string filename = Common::NormalizeNFDToNFC(file.virtualName); +#else + const std::string& filename = file.virtualName; +#endif const std::u16string filename_utf16 = Common::UTF8ToUTF16(filename); Entry& entry = entries[entries_read]; @@ -97,6 +101,4 @@ u32 DiskDirectory::Read(const u32 count, Entry* entries) { } return entries_read; } - - } // namespace FileSys diff --git a/src/tests/common/file_util.cpp b/src/tests/common/file_util.cpp index 90b6a4be0..ec3f86d02 100644 --- a/src/tests/common/file_util.cpp +++ b/src/tests/common/file_util.cpp @@ -25,13 +25,13 @@ TEST_CASE("SplitFilename83 Sanity", "[common]") { REQUIRE(std::memcmp(extension.data(), expected_extension.data(), extension.size()) == 0); } -TEST_CASE("NormalizeUTF8ToNFC Sanity", "[common]") { +TEST_CASE("NormalizeNFDToNFC Sanity", "[common]") { const std::string decomposed = "i\xCC\x81"; const std::string composed = "\xC3\xAD"; #if defined(__APPLE__) - REQUIRE(Common::NormalizeUTF8ToNFC(decomposed) == composed); + REQUIRE(Common::NormalizeNFDToNFC(decomposed) == composed); #else - REQUIRE(Common::NormalizeUTF8ToNFC(decomposed) == decomposed); + REQUIRE(Common::NormalizeNFDToNFC(decomposed) == decomposed); #endif }