Track IDs created in functions and empty them when they leave scope

* This prevents a use-after-free issue when pointers are stored and the backing
  storage is deallocated, if the function is entered again we try to get the
  previous value to show a variable change an dereference it.
This commit is contained in:
baldurk
2022-10-07 11:43:22 +01:00
parent 18f41c6fb6
commit 9254eff490
2 changed files with 14 additions and 0 deletions
@@ -342,6 +342,11 @@ void ThreadState::SetDst(Id id, const ShaderVariable &val)
ShaderVariable prev = ids[id];
// if this id didn't exist before it's not a global so it's a local variable, function parameter,
// or plain id. Track it in the current frame so it's emptied upon return
if(prev.name.empty() && prev.type == VarType::Unknown)
callstack.back()->idsCreated.push_back(id);
ids[id] = val;
ids[id].name = GetRawName(id);
@@ -3037,6 +3042,9 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray<ThreadState>
live = callstack.back()->live;
}
for(Id id : exitingFrame->idsCreated)
ids[id] = ShaderVariable();
delete exitingFrame;
break;
@@ -143,6 +143,12 @@ struct StackFrame
// allocated storage for locals
rdcarray<ShaderVariable> locals;
// list of Ids we created, either variables/function parameters in this function, or IDs created
// in this function. When we return from this frame they will be emptied.
// This prevents a use-after-free with ShaderVariableChanges if we re-enter the same function
// and want to show the previous value of an id
rdcarray<Id> idsCreated;
// as a hack for scoping without proper debug info, we track locals from their first use
rdcarray<Id> localsUsed;