diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index 89a7126e2..7543e1a23 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -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 live = callstack.back()->live; } + for(Id id : exitingFrame->idsCreated) + ids[id] = ShaderVariable(); + delete exitingFrame; break; diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.h b/renderdoc/driver/shaders/spirv/spirv_debug.h index 372109a94..e00ac8797 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.h +++ b/renderdoc/driver/shaders/spirv/spirv_debug.h @@ -143,6 +143,12 @@ struct StackFrame // allocated storage for locals rdcarray 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 idsCreated; + // as a hack for scoping without proper debug info, we track locals from their first use rdcarray localsUsed;