UE4SS-RE / RE-UE4SS

Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games
http://docs.ue4ss.com/
MIT License
1.38k stars 188 forks source link

[BUG - Release] UWorld::SpawnActor() crashes too often in a game thread #527

Open massclown opened 6 months ago

massclown commented 6 months ago

Branch or Release v3.0.1

Game and Engine Version Half Sword (Steam demo v0.3), UE5.1 (UE5+Release-5.1-CL-23901901) HalfSwordUE5-Win64-Shipping.exe, SHA256: CB6ABB5D568F48F9FC477EC4B093878BBD5A04A05FA9E6A0282EEE02669BE865

Describe the bug

Mods directory The reproducer mod (see notes below, Lua, C++) is installed on top of a clean UE4SS 3.0.1 from Github releases.

To Reproduce Steps to reproduce the behavior:

  1. Launch game with the reproducer mod
  2. Spawn actors a few times
  3. Observe the crash

Expected behavior Given that CheatManager::summon() appears to allow spawning the exact same actor class infinitely, it seems to be an issue in UE4SS.

Screenshots, UE4SS Log, and .dmp file N/A

Desktop (please complete the following information):

Additional context

Minimized Lua reproducer mod: https://gist.github.com/massclown/35387c06389d1831cdde6905db72681b Minimized C++ reproducer mod: https://gist.github.com/massclown/919b6bc37c05d1a8e717afb27e6822ca

Surprisingly, the crash happens exactly the same when:

Calling CheatManager::summon() from the UE4SS function caller, which uses Hook::RegisterProcessEventPostCallback(...) to inject into the game thread also leads to a very similar crash.

The crash appears to be in exactly the same call stack in all these 4 cases (Lua or C++, in game thread or not), regardless of when read from a crashdump, or when running under a debugger, and happens when a memcpy target appears to be null inside UObject::execLocalVariable of Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp (looking at UE 5.1 sources and disassembly of the target game). The memcpy() call appears to be inlined CopyCompleteValueToScriptVM().

In the stack below:

VCRUNTIME140!memcpy+0x11c 
HalfSwordUE5_Win64_Shipping!png_get_uint_16+0x148dc71  
HalfSwordUE5_Win64_Shipping!png_get_uint_16+0x14880ee 
UE4SS!RC::Unreal::HookedProcessLocalScriptFunction+0x72 
HalfSwordUE5_Win64_Shipping!png_get_uint_16+0x1488055 
UE4SS!RC::Unreal::HookedProcessInternal+0x72 
HalfSwordUE5_Win64_Shipping!png_get_uint_16+0x13b18c9 
HalfSwordUE5_Win64_Shipping!png_get_uint_16+0x1487f02 
UE4SS!RC::Unreal::HookedProcessEvent+0x79 
HalfSwordUE5_Win64_Shipping!src_strerror+0x5687b1 
HalfSwordUE5_Win64_Shipping!src_strerror+0x7557fa 
HalfSwordUE5_Win64_Shipping!src_strerror+0x747a40 
HalfSwordUE5_Win64_Shipping!src_strerror+0x74c143 
HalfSwordUE5_Win64_Shipping!src_strerror+0x6c8052 
HalfSwordUE5_Win64_Shipping!src_strerror+0x6dc61a 
HalfSwordUE5_Win64_Shipping!src_strerror+0xcdeccd 
HalfSwordUE5_Win64_Shipping!src_strerror+0xcb4503 
HalfSwordUE5_Win64_Shipping!src_strerror+0xcb46e3 
HalfSwordUE5_Win64_Shipping!src_strerror+0xcd2bd0 
HalfSwordUE5_Win64_Shipping!src_strerror+0x4eabbe 
HalfSwordUE5_Win64_Shipping!src_strerror+0x4ed189 
HalfSwordUE5_Win64_Shipping!src_strerror+0x885273 
HalfSwordUE5_Win64_Shipping!png_get_uint_16+0x13b18c9 
HalfSwordUE5_Win64_Shipping!png_get_uint_16+0x1487f02 
UE4SS!RC::Unreal::HookedProcessEvent+0x79 
UE4SS!RC::Unreal::UObject::ProcessEvent+0x194 
UE4SS!RC::Unreal::UGameplayStatics::FinishSpawningActor+0x9f 
UE4SS!RC::Unreal::UWorld::SpawnActor+0x2a3 

The code of UE4SS repeating twice in the call stack is UE4SS!RC::Unreal::HookedProcessEvent+0x79 (which seems to be the line calling RC::Unreal::HookTrampolineProcessEvent(Context, Function, Parms)). Is that hook supposed to be OK with that?

The call stack and exception summary from WinDBG:

massclown commented 5 months ago

Any ideas for further debugging that I can do myself here are appreciated.

igromanru commented 1 week ago

What I wonder is how the hell are you even using the SpawnActor function from UWorld? I can't remember a single game where the SpawnActor was an UFunction aka. exposed to UE reflection system. Is it a special case or are you trying to call it blindly?
devenv_kG84oAJYPW
In original Unreal Engine code, it's definitely not an UFunction.

jesjino commented 1 week ago

I had the same problem with the Blueprint project for ue5.4. Calling UWorld::SpawnActor() in a game thread from both Lua and C++ leads to crashes after 3-10 actors spawned on average.

jesjino commented 1 week ago

I try to use the hook ". / Script/Engine GameplayStatics: FinishSpawningActor "see SpawnActor BeginDeferredActorSpawnFromClass in error Return nullptr. I added it to cpp

AActor* Actor = UGameplayStatics::BeginDeferredActorSpawnFromClass(this, InClass, Transform); if (Actor) { UGameplayStatics::FinishSpawningActor(Actor, Transform);

return Actor;

} return nullptr; //Temporary solution

igromanru commented 1 week ago

What I wonder is how the hell are you even using the SpawnActor function from UWorld? I can't remember a single game where the SpawnActor was an UFunction aka. exposed to UE reflection system. Is it a special case or are you trying to call it blindly? devenv_kG84oAJYPW In original Unreal Engine code, it's definitely not an UFunction.

I take it back. It isn't documented anywhere. But SpawnActor is an own re-implementation in UE4SS. https://github.com/UE4SS-RE/RE-UE4SS/blob/7cd4e3fee46460e377dcbc26175633d417914cb4/UE4SS/src/LuaType/LuaUWorld.cpp#L62 https://github.com/Re-UE4SS/UEPseudo/blob/96be30aedb0cad36c261e486c3bc6129747f9ad6/src/World.cpp