Description

Currently there's no validation within the animation attribute container that bone ids are valid.  This means that client/game code can add attributes with invalid bone ids into the container and this will then fail when, later in the frame, we attempt to call TAttributeContainer::CopyFrom because at that point, we access the BoneIndicesArray on the BoneContainer so we can read off the end of the array.

And example of this failing can be reproduced via control rig.  The GetAnimAttributeValue rig unit in RigUnit_AnimAttribute.h uses the ref skeleton to add attributes against, but if an attribute is added on a bone that exists in the ref skeleton but not the currently active mesh, this will later fail in TAttributeContainer::CopyFrom.

We should probably have some form of validation or filtering when copying the attribute buffers to catch this.

Steps to Reproduce
  1. Open the attached project
  2. Open L_006677537 level
  3. This will immediately break/crash in TAttributeContainer::CopyFrom
    1. The issue is that the control rig that's active on the mesh in the level is adding an attribute to the container for an invalid bone
Callstack
>    UnrealEditor-Engine-Win64-Debug.dll!FBoneContainer::MakeMeshPoseIndex(const FCompactPoseBoneIndex & BoneIndex) Line 644    C++
     UnrealEditor-Engine-Win64-Debug.dll!UE::Anim::TAttributeContainer<FMeshPoseBoneIndex,TSizedDefaultAllocator<32>>::CopyFrom<FCompactPoseBoneIndex,TSizedDefaultAllocator<32>>(const UE::Anim::TAttributeContainer<FCompactPoseBoneIndex,TSizedDefaultAllocator<32>> & Other, const FBoneContainer & BoneContainer) Line 117    C++
     UnrealEditor-Engine-Win64-Debug.dll!USkeletalMeshComponent::FinalizeAttributeEvaluationResults(const FBoneContainer & BoneContainer, const UE::Anim::FHeapAttributeContainer & FinalContainer, UE::Anim::FMeshAttributeContainer & OutContainer) Line 578    C++
     UnrealEditor-Engine-Win64-Debug.dll!USkeletalMeshComponent::PerformAnimationProcessing(const USkeletalMesh * InSkeletalMesh, UAnimInstance * InAnimInstance, bool bInDoEvaluation, TArray<UE::Math::TTransform<double>,TSizedDefaultAllocator<32>> & OutSpaceBases, TArray<UE::Math::TTransform<double>,TSizedDefaultAllocator<32>> & OutBoneSpaceTransforms, UE::Math::TVector<double> & OutRootBoneTranslation, FBlendedHeapCurve & OutCurve, UE::Anim::FMeshAttributeContainer & OutAttributes) Line 2058    C++
     UnrealEditor-Engine-Win64-Debug.dll!USkeletalMeshComponent::ParallelAnimationEvaluation() Line 3974    C++
     UnrealEditor-Engine-Win64-Debug.dll!FParallelAnimationEvaluationTask::DoTask(ENamedThreads::Type CurrentThread, const TRefCountPtr<FGraphEvent> & MyCompletionGraphEvent) Line 153    C++
     UnrealEditor-Engine-Win64-Debug.dll!TGraphTask<FParallelAnimationEvaluationTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & NewTasks, ENamedThreads::Type CurrentThread, bool bDeleteOnCompletion) Line 1267    C++
     UnrealEditor-Core-Win64-Debug.dll!FTaskGraphCompatibilityImplementation::QueueTask::__l5::<lambda>() Line 1973    C++
     UnrealEditor-Core-Win64-Debug.dll!LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48>::TTaskDelegateImpl<`LowLevelTasks::FTask::Init<`FTaskGraphCompatibilityImplementation::QueueTask'::`5'::void <lambda>(const TArray<FString,TSizedDefaultAllocator<32>> &, UWorld *, FOutputDevice &)>'::`17'::void <lambda>(const TArray<FString,TSizedDefaultAllocator<32>> &, UWorld *, FOutputDevice &),0>::CallAndMove(LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48> & Destination, void * InlineData, unsigned int DestInlineSize, bool <Params_0>) Line 171    C++
     UnrealEditor-Core-Win64-Debug.dll!LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48>::CallAndMove<48>(LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48> & Destination, bool <Params_0>) Line 309    C++
     UnrealEditor-Core-Win64-Debug.dll!LowLevelTasks::FTask::ExecuteTask() Line 627    C++
     UnrealEditor-Core-Win64-Debug.dll!LowLevelTasks::FScheduler::ExecuteTask(LowLevelTasks::FTask * & InOutTask) Line 150    C++
     UnrealEditor-Core-Win64-Debug.dll!LowLevelTasks::FScheduler::TryExecuteTaskFrom<LowLevelTasks::TLocalQueueRegistry<1024>::TLocalQueue,&LowLevelTasks::TLocalQueueRegistry<1024>::TLocalQueue::DequeueGlobal,0>(LowLevelTasks::TLocalQueueRegistry<1024>::TLocalQueue * Queue, LowLevelTasks::TLocalQueueRegistry<1024>::FOutOfWork & OutOfWork, bool bPermitBackgroundWork, bool bDisableThrottleStealing) Line 350    C++
     UnrealEditor-Core-Win64-Debug.dll!LowLevelTasks::FScheduler::WorkerMain(LowLevelTasks::FSleepEvent * WorkerEvent, LowLevelTasks::TLocalQueueRegistry<1024>::TLocalQueue * WorkerLocalQueue, unsigned int WaitCycles, bool bPermitBackgroundWork) Line 378    C++
     UnrealEditor-Core-Win64-Debug.dll!LowLevelTasks::FScheduler::CreateWorker::__l2::<lambda>() Line 71    C++
     UnrealEditor-Core-Win64-Debug.dll!UE::Core::Private::Function::TFunctionRefCaller<`LowLevelTasks::FScheduler::CreateWorker'::`2'::void <lambda>(const TArray<FString,TSizedDefaultAllocator<32>> &, UWorld *, FOutputDevice &),void __cdecl(void)>::Call(void * Obj) Line 480    C++
     UnrealEditor-Core-Win64-Debug.dll!UE::Core::Private::Function::TFunctionRefBase<UE::Core::Private::Function::TFunctionStorage<1>,void __cdecl(void)>::operator()() Line 630    C++
     UnrealEditor-Core-Win64-Debug.dll!FThreadImpl::Run() Line 68    C++
     UnrealEditor-Core-Win64-Debug.dll!FRunnableThreadWin::Run() Line 146    C++
     UnrealEditor-Core-Win64-Debug.dll!FRunnableThreadWin::GuardedRun() Line 71    C++
     UnrealEditor-Core-Win64-Debug.dll!FRunnableThreadWin::_ThreadProc(void * pThis) Line 39    C++
 

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-218079 in the post.

1
Login to Vote

Unresolved
ComponentUE - Anim - Runtime
Affects Versions5.4
Target Fix5.6
CreatedJun 16, 2024
UpdatedSep 16, 2024
View Jira Issue