From de7fb51e6496a22a31907c9892e597426279f5ac Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 11 Sep 2021 19:38:24 +0200 Subject: [PATCH] [d3d11] Validate indirect draw buffer size Otherwise, if the draw parameter offset is out of bounds, we may hang the GPU. Fixes #2286. --- src/d3d11/d3d11_context.cpp | 6 ++++++ src/d3d11/d3d11_context.h | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 5f6f58e2..e5259c79 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -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(m_cmdData); diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 920bc67c..483b0415 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -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(pBuffer)->Desc()->ByteWidth; + + return bufferSize >= Offset + Size; + } template void EmitCs(Cmd&& command) {