Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cr.sav corruption engine crash #166

Open
BellringerQuinn opened this issue Sep 25, 2024 · 4 comments
Open

Cr.sav corruption engine crash #166

BellringerQuinn opened this issue Sep 25, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@BellringerQuinn
Copy link
Collaborator

BellringerQuinn commented Sep 25, 2024

The credentials are currently saved to a Cr.sav file located at /Saved/SaveGames/Cr.sav

If something happens that corrupts or modifies the Cr.sav file from the format that is expected, the engine will crash whenever we try to access the wallet or credentials and give a rather unhelpful stack trace.

The current workaround is to delete the Cr.sav file. The dev will need to login again as their credentials will no longer be cached (not a big deal). In the current state, the engine will continue to crash until the Cr.sav file is deleted.

We should catch the exception when reading credentials so that the engine doesn't crash and delete the Cr.sav file. This way integrators are not caught with an annoying and hard to debug crash.

@BellringerQuinn BellringerQuinn added the bug Something isn't working label Sep 25, 2024
@BellringerQuinn BellringerQuinn changed the title Cr.sav corruption crash Cr.sav corruption engine crash Sep 25, 2024
@BellringerQuinn
Copy link
Collaborator Author

I was able to replicate this bug by modifying the Cr.sav file in a hex editor - it took some trial and error, so attaching my Cr.sav file (as Google Drive link)

Some things I noticed that may be helpful:

In Authenticator.cpp there is:

bool UAuthenticator::GetStoredCredentials(FCredentials_BE* Credentials) const
{
	bool ret = false;
	if (const UStorableCredentials* LoadedCredentials = Cast<UStorableCredentials>(UGameplayStatics::LoadGameFromSlot(this->SaveSlot, this->UserIndex)))
	{
		FString CTR_Json = "";
		if (Encryptor)
		{//Use set encryptor
			CTR_Json = Encryptor->Decrypt(LoadedCredentials->EK); // this line throws
		}
		else
		{//Use the fallback
			CTR_Json = USequenceEncryptor::Decrypt(LoadedCredentials->EK, LoadedCredentials->KL);
		}

		ret = USequenceSupport::JSONStringToStruct<FCredentials_BE>(CTR_Json, Credentials);
		ret &= Credentials->RegisteredValid();
	}
	return ret;
}

It seems as though NativeAppleEncryptor.mm is throwing the exception and the exception is not propagating up the stack for some reason out into our unreal code (tested by wrapping the GetStoredCredentials logic in a try catch block). We likely need to handle the exception in the .mm file code; my assumption is that there is some sort of barrier (of sorts) between Unreal and the native code that prevents the exceptions from propagating up the stack to where we can catch and handle it effectively. We'll likely need to handle the exception in the native code.

When I used the debugger, I kept getting stuck infinitely on this line
CFDataRef cfDecryptedData = SecKeyCreateDecryptedData(PrivateKeyRef,algorithm,plainText,&error);
At first, I thought this was causing a stack overflow error, but I think it may just be that the Rider debugger doesn't know how to handle itself in this scenario. Especially since my minidump.dmp file reveals a separate exception

My minidump.dmp file reveals the exception is:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'SecKeyCreateDecryptedData() called with NULL ciphertext'
Full file attached: minidump.dmp

@BellringerQuinn
Copy link
Collaborator Author

Note: while the above exception appears to be a Mac issue, it is likely that the same Cr.sav will lead to a crash on the windows side as well - worth checking.

@BellringerQuinn
Copy link
Collaborator Author

Also uploading a .rtf with the hex pasted in just in case future readers are unable to download and use the .sav file above from google drive directly

@BellringerQuinn
Copy link
Collaborator Author

It is possible that the exceptions are not propagating up the stack due to a lack of pre-processor directive or macro

We should investigate this - I don't have a lot of context, but from what I understand it is possible that in some cases the Unreal compiler will just ignore try catch blocks during compilation unless configured appropriately
https://forums.unrealengine.com/t/try-catch-fails-to-catch-exception/463146/3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant