Fix dangling pointer for T2B if copy size is zero
T2B: remove the early return when copy size is zero.
Instead encode a CopyTextureToBufferCmd, which is
handled on the backends to no-op a zero sized copy.
Add regression unittests.
Bug: 405316877
Change-Id: Icdf8f49b18267fdbdc6f7957874653fcc5b390d0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/232694
Auto-Submit: Shrek Shao <shrekshao@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Shrek Shao <shrekshao@google.com>
Reviewed-by: Quyen Le <lehoangquyen@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp
index f89de32..a776905 100644
--- a/src/dawn/native/CommandEncoder.cpp
+++ b/src/dawn/native/CommandEncoder.cpp
@@ -940,7 +940,13 @@
bool ShouldUseTextureToBufferBlit(const DeviceBase* device,
const Format& format,
- const Aspect& aspect) {
+ const Aspect& aspect,
+ const Extent3D& copySize) {
+ // Noop copy, do not use blit.
+ if (copySize.width == 0 || copySize.height == 0 || copySize.depthOrArrayLayers == 0) {
+ return false;
+ }
+
// Snorm
if (format.IsSnorm() && device->IsToggleEnabled(Toggle::UseBlitForSnormTextureToBufferCopy)) {
return true;
@@ -1694,17 +1700,11 @@
TexelCopyBufferLayout dstLayout = destination->layout;
ApplyDefaultTexelCopyBufferLayoutOptions(&dstLayout, blockInfo, *copySize);
- if (copySize->width == 0 || copySize->height == 0 ||
- copySize->depthOrArrayLayers == 0) {
- // Noop copy but is valid, simply skip encoding any command.
- return {};
- }
-
auto format = source.texture->GetFormat();
auto aspect = ConvertAspect(format, source.aspect);
// Workaround to use compute pass to emulate texture to buffer copy
- if (ShouldUseTextureToBufferBlit(GetDevice(), format, aspect)) {
+ if (ShouldUseTextureToBufferBlit(GetDevice(), format, aspect, *copySize)) {
// This function might create new resources. Need to lock the Device.
// TODO(crbug.com/dawn/1618): In future, all temp resources should be created at
// Command Submit time, so the locking would be removed from here at that point.
diff --git a/src/dawn/tests/unittests/native/CommandBufferEncodingTests.cpp b/src/dawn/tests/unittests/native/CommandBufferEncodingTests.cpp
index 1ad37e0..1e68eaf 100644
--- a/src/dawn/tests/unittests/native/CommandBufferEncodingTests.cpp
+++ b/src/dawn/tests/unittests/native/CommandBufferEncodingTests.cpp
@@ -32,6 +32,7 @@
#include "dawn/native/Commands.h"
#include "dawn/native/ComputePassEncoder.h"
#include "dawn/tests/DawnNativeTest.h"
+#include "dawn/utils/TestUtils.h"
#include "dawn/utils/WGPUHelpers.h"
namespace dawn::native {
@@ -321,5 +322,91 @@
EXPECT_FALSE(stateTracker->HasPipeline());
}
+// Regression test for crbug.com/405316877.
+// Make sure a zero size no-op copy would not cause dereferencing to a dangling pointer,
+// if the buffer is destroyed immediately after the encoding.
+TEST_F(CommandBufferEncodingTests, DanglingDestroyedBufferPointerB2T) {
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ {
+ wgpu::Buffer buffer;
+ {
+ wgpu::BufferDescriptor descriptor = {};
+ descriptor.size = 1024;
+ descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
+ buffer = device.CreateBuffer(&descriptor);
+ }
+
+ constexpr wgpu::Extent3D kTextureSize = {4, 4, 1};
+ wgpu::Texture texture;
+ {
+ wgpu::TextureDescriptor descriptor;
+ descriptor.size = kTextureSize;
+ descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
+ descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;
+ texture = device.CreateTexture(&descriptor);
+ }
+
+ wgpu::TexelCopyBufferInfo texelCopyBufferInfo = utils::CreateTexelCopyBufferInfo(
+ buffer, 0, kTextureBytesPerRowAlignment, kTextureSize.height);
+ wgpu::TexelCopyTextureInfo texelCopyTextureInfo =
+ utils::CreateTexelCopyTextureInfo(texture, 0, {0, 0, 0});
+ constexpr wgpu::Extent3D kCopySize = {0, 0, 0};
+ encoder.CopyBufferToTexture(&texelCopyBufferInfo, &texelCopyTextureInfo, &kCopySize);
+
+ // Destroy and release the buffer immediately.
+ buffer.Destroy();
+ }
+
+ wgpu::CommandBuffer commands = encoder.Finish();
+
+ device.PushErrorScope(wgpu::ErrorFilter::Validation);
+ device.GetQueue().Submit(1, &commands);
+ device.PopErrorScope(wgpu::CallbackMode::AllowProcessEvents,
+ [](wgpu::PopErrorScopeStatus, wgpu::ErrorType, wgpu::StringView) {});
+}
+
+// Regression test for crbug.com/405316877.
+// Make sure a zero size no-op copy would not cause dereferencing to a dangling pointer,
+// if the buffer is destroyed immediately after the encoding.
+TEST_F(CommandBufferEncodingTests, DanglingDestroyedBufferPointerT2B) {
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ {
+ wgpu::Buffer buffer;
+ {
+ wgpu::BufferDescriptor descriptor = {};
+ descriptor.size = 1024;
+ descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
+ buffer = device.CreateBuffer(&descriptor);
+ }
+
+ constexpr wgpu::Extent3D kTextureSize = {4, 4, 1};
+ wgpu::Texture texture;
+ {
+ wgpu::TextureDescriptor descriptor;
+ descriptor.size = kTextureSize;
+ descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
+ descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;
+ texture = device.CreateTexture(&descriptor);
+ }
+
+ wgpu::TexelCopyBufferInfo texelCopyBufferInfo = utils::CreateTexelCopyBufferInfo(
+ buffer, 0, kTextureBytesPerRowAlignment, kTextureSize.height);
+ wgpu::TexelCopyTextureInfo texelCopyTextureInfo =
+ utils::CreateTexelCopyTextureInfo(texture, 0, {0, 0, 0});
+ constexpr wgpu::Extent3D kCopySize = {0, 0, 0};
+ encoder.CopyTextureToBuffer(&texelCopyTextureInfo, &texelCopyBufferInfo, &kCopySize);
+
+ // Destroy and release the buffer immediately.
+ buffer.Destroy();
+ }
+
+ wgpu::CommandBuffer commands = encoder.Finish();
+
+ device.PushErrorScope(wgpu::ErrorFilter::Validation);
+ device.GetQueue().Submit(1, &commands);
+ device.PopErrorScope(wgpu::CallbackMode::AllowProcessEvents,
+ [](wgpu::PopErrorScopeStatus, wgpu::ErrorType, wgpu::StringView) {});
+}
+
} // anonymous namespace
} // namespace dawn::native