[d3d11] Validate indirect draw buffer size

Otherwise, if the draw parameter offset is out of bounds, we
may hang the GPU.

Fixes #2286.
This commit is contained in:
Philip Rebohle 2021-09-11 19:38:24 +02:00
parent 3c7e5c9300
commit de7fb51e64
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 15 additions and 0 deletions

View File

@ -1288,6 +1288,9 @@ namespace dxvk {
UINT AlignedByteOffsetForArgs) {
D3D10DeviceLock lock = LockContext();
SetDrawBuffers(pBufferForArgs, nullptr);
if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand)))
return;
// If possible, batch up multiple indirect draw calls of
// the same type into one single multiDrawIndirect call
@ -1320,6 +1323,9 @@ namespace dxvk {
D3D10DeviceLock lock = LockContext();
SetDrawBuffers(pBufferForArgs, nullptr);
if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand)))
return;
// If possible, batch up multiple indirect draw calls of
// the same type into one single multiDrawIndirect call
auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData);

View File

@ -957,6 +957,15 @@ namespace dxvk {
uint32_t stride = offset - cmdData->offset;
return stride >= minStride && stride <= 32 ? stride : 0;
}
static bool ValidateDrawBufferSize(ID3D11Buffer* pBuffer, UINT Offset, UINT Size) {
UINT bufferSize = 0;
if (likely(pBuffer != nullptr))
bufferSize = static_cast<D3D11Buffer*>(pBuffer)->Desc()->ByteWidth;
return bufferSize >= Offset + Size;
}
template<typename Cmd>
void EmitCs(Cmd&& command) {