mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 13:20:54 +00:00
Clamp out-of-bounds descriptor access when getting bindless feedback
This commit is contained in:
@@ -42,8 +42,8 @@ struct feedbackData
|
||||
};
|
||||
|
||||
void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
|
||||
const std::map<rdcspv::Binding, feedbackData> &offsetMap, VkDeviceAddress addr,
|
||||
bool bufferAddressKHR, rdcarray<uint32_t> &modSpirv)
|
||||
const std::map<rdcspv::Binding, feedbackData> &offsetMap, uint32_t maxSlot,
|
||||
VkDeviceAddress addr, bool bufferAddressKHR, rdcarray<uint32_t> &modSpirv)
|
||||
{
|
||||
rdcspv::Editor editor(modSpirv);
|
||||
|
||||
@@ -51,6 +51,12 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
|
||||
|
||||
const bool useBufferAddress = (addr != 0);
|
||||
|
||||
const uint32_t targetIndexWidth = useBufferAddress ? 64 : 32;
|
||||
|
||||
// store the maximum slot we can use, for clamping outputs to avoid writing out of bounds
|
||||
rdcspv::Id maxSlotID = useBufferAddress ? editor.AddConstantImmediate<uint64_t>(maxSlot)
|
||||
: editor.AddConstantImmediate<uint32_t>(maxSlot);
|
||||
|
||||
rdcspv::Id uint32ID = editor.DeclareType(rdcspv::scalar<uint32_t>());
|
||||
rdcspv::Id int32ID = editor.DeclareType(rdcspv::scalar<int32_t>());
|
||||
rdcspv::Id uint64ID, int64ID;
|
||||
@@ -409,7 +415,6 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
|
||||
it++;
|
||||
|
||||
// upcast the index to uint32 or uint64 depending on which path we're taking
|
||||
uint32_t targetIndexWidth = useBufferAddress ? 64 : 32;
|
||||
{
|
||||
rdcspv::Id indexType = editor.GetIDType(index);
|
||||
|
||||
@@ -457,6 +462,27 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
|
||||
}
|
||||
}
|
||||
|
||||
// clamp the index to the maximum slot. If the user is reading out of bounds, don't write
|
||||
// out of bounds.
|
||||
{
|
||||
rdcspv::Id glsl450 = editor.ImportExtInst("GLSL.std.450");
|
||||
|
||||
rdcspv::Id clampedtype =
|
||||
editor.DeclareType(rdcspv::Scalar(rdcspv::Op::TypeInt, targetIndexWidth, false));
|
||||
rdcspv::Id clampedindex = editor.MakeId();
|
||||
|
||||
editor.AddOperation(
|
||||
it, rdcspv::Operation(
|
||||
rdcspv::Op::ExtInst,
|
||||
{
|
||||
clampedtype.value(), clampedindex.value(), glsl450.value(),
|
||||
(uint32_t)rdcspv::GLSLstd450::UMin, index.value(), maxSlotID.value(),
|
||||
}));
|
||||
it++;
|
||||
|
||||
index = clampedindex;
|
||||
}
|
||||
|
||||
rdcspv::Id bufptr;
|
||||
|
||||
if(useBufferAddress)
|
||||
@@ -563,6 +589,10 @@ void VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
|
||||
std::map<rdcspv::Binding, feedbackData> offsetMap;
|
||||
|
||||
// reserve some space at the start for a general counter indicating that successful data was
|
||||
// written.
|
||||
feedbackStorageSize += 16;
|
||||
|
||||
{
|
||||
const rdcarray<ResourceId> &descSetLayoutIds =
|
||||
creationInfo.m_PipelineLayout[pipeInfo.layout].descSetLayouts;
|
||||
@@ -596,6 +626,11 @@ void VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t maxSlot = uint32_t(feedbackStorageSize / sizeof(uint32_t));
|
||||
|
||||
// add some extra padding just in case of out-of-bounds writes
|
||||
feedbackStorageSize += 128;
|
||||
|
||||
// if we don't have any array descriptors to feedback then just return now
|
||||
if(offsetMap.empty())
|
||||
return;
|
||||
@@ -723,7 +758,7 @@ void VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
|
||||
rdcarray<uint32_t> modSpirv = moduleInfo.spirv.GetSPIRV();
|
||||
|
||||
AnnotateShader(*pipeInfo.shaders[5].patchData, stage.pName, offsetMap, bufferAddress,
|
||||
AnnotateShader(*pipeInfo.shaders[5].patchData, stage.pName, offsetMap, maxSlot, bufferAddress,
|
||||
useBufferAddressKHR, modSpirv);
|
||||
|
||||
moduleCreateInfo.pCode = modSpirv.data();
|
||||
@@ -748,8 +783,8 @@ void VulkanReplay::FetchShaderFeedback(uint32_t eventId)
|
||||
|
||||
rdcarray<uint32_t> modSpirv = moduleInfo.spirv.GetSPIRV();
|
||||
|
||||
AnnotateShader(*pipeInfo.shaders[idx].patchData, stage.pName, offsetMap, bufferAddress,
|
||||
useBufferAddressKHR, modSpirv);
|
||||
AnnotateShader(*pipeInfo.shaders[idx].patchData, stage.pName, offsetMap, maxSlot,
|
||||
bufferAddress, useBufferAddressKHR, modSpirv);
|
||||
|
||||
moduleCreateInfo.pCode = modSpirv.data();
|
||||
moduleCreateInfo.codeSize = modSpirv.size() * sizeof(uint32_t);
|
||||
|
||||
Reference in New Issue
Block a user