Skip to content

Fix a crash in Unreal Engine games when system language is Chinese#182

Merged
XuYicong merged 1 commit intoPlayCover:masterfrom
viatearz:ue_fix
Apr 16, 2025
Merged

Fix a crash in Unreal Engine games when system language is Chinese#182
XuYicong merged 1 commit intoPlayCover:masterfrom
viatearz:ue_fix

Conversation

@viatearz
Copy link
Copy Markdown
Contributor

Summary

Recently some Unreal Engine games started using the Extended Virtual Addressing feature. When this feature is enabled, Unreal Engine attempts to extract the Entitlement from the executable and checks whether it contains com.apple.developer.kernel.extended-virtual-addressing.
However, due to an issue in Unreal Engine’s code, it read 8 extra bytes. These extra bytes cause a string decoding failure when the system language is set to Chinese, ultimately leading to a crash.

Explanations

FApplePlatformMemory.cpp
This function calls FIOSPlatformMisc::IsEntitlementEnabled.

bool FApplePlatformMemory::CanOverallocateVirtualMemory()
{
    static bool bHasExtendedVirtualAddressingEntitlement = FIOSPlatformMisc::IsEntitlementEnabled("com.apple.developer.kernel.extended-virtual-addressing");
    return bHasExtendedVirtualAddressingEntitlement;
}

FIOSPlatformMisc.cpp
EntitlementsData() returns an empty string, but the range is nonzero, causing stringByReplacingOccurrencesOfString to crash with a Range out of bounds error.

bool FIOSPlatformMisc::IsEntitlementEnabled(const char * EntitlementToCheck)
{
    NSString* TrueFlag = @"</key><true/>";
    NSString* EntitlementsToFind = [NSString stringWithFormat: @"%s%@" , EntitlementToCheck, TrueFlag];
    
    // Crash here!!!
    NSString* CleanedEntitlementData = [EntitlementsData() stringByReplacingOccurrencesOfString: @"\\s+" withString: @"" options: NSRegularExpressionSearch range: NSMakeRange(0, EntitlementsToFind.length)];

    // ...
}

IOSPlatformMisc.cpp
It reads 8 extra bytes, which causes a decoding failure and returns an empty string.

typedef struct __Blob {
    uint32_t magic;
    uint32_t length;
    char data[];
} CS_GenericBlob;

extern NSString *EntitlementsData(void)
{
    // ...
	
    CS_GenericBlob blob;
    Count = fread(&blob, sizeof(CS_GenericBlob), 1, file);
	
    if (__builtin_bswap32(blob.magic) == 0xfade7171)
    {
        uint32 blobLength = ntohl(blob.length);
        char data[blobLength];
        fread(&data[0], sizeof(char) * blobLength, 1, file);
        NSString *stringFromData = [NSString stringWithFormat: @"%s", data];
        NSLog(@"%@", stringFromData);
        fclose(file);
        return stringFromData;
    }
	
    // ...
}

Why has it read 8 extra bytes?
The blob.length represents the total length of CS_GenericBlob, not the data array.
The actual length of the data array should be blob.length - 8 bytes.

Why does it return an empty string?
Expected data: <plist>...</plist>
Actual data read: <plist>...</plist>\xfa\xde\x71\x72
When we pass the data to stringWithFormat, it uses the encoding returned by CFStringGetSystemEncoding() to decode it. When the system language is set to Chinese, it will use CFStringEncodingMacChineseSimp, but the decoding fails, returning an empty string.

Why doesn’t the crash happen on iOS?
On iOS, CFStringGetSystemEncoding() always returns 0 regardless of the system language, so it works fine. On macOS, CFStringGetSystemEncoding() returns different values depending on the system language.

How to Fix

Hook the string replacement function. If the source string is empty, return immediately to prevent a Range out of bounds error.

@viatearz
Copy link
Copy Markdown
Contributor Author

also related: PlayCover/PlayCover#1755

@viatearz
Copy link
Copy Markdown
Contributor Author

viatearz commented Feb 1, 2025

I have submitted the new codes. Compared to the previous version, now PTSwizzleLoader will remain untouched.

@XuYicong XuYicong requested a review from ohaiibuzzle April 15, 2025 00:45
@XuYicong XuYicong merged commit e5bcd90 into PlayCover:master Apr 16, 2025
@viatearz viatearz deleted the ue_fix branch May 3, 2025 01:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: CN Wuthering Waves crash [Bug]:CN 'Wuthering Wave' (MingChao) Crash While 1.4 Version

3 participants