From 5b918272eaef5348673ec24c19df83987d1e6156 Mon Sep 17 00:00:00 2001 From: Brad Werth Date: Fri, 17 Nov 2023 16:11:40 +0000 Subject: [PATCH] Bug 1816731 Part 1: Prevent configuration of a WebGPU context for a too-big canvas. r=webgpu-reviewers,ErichDonGubler Differential Revision: https://phabricator.services.mozilla.com/D193567 --- dom/webgpu/CanvasContext.cpp | 2 ++ dom/webgpu/Device.cpp | 14 ++++++++++++++ dom/webgpu/Device.h | 3 +++ dom/webgpu/ipc/WebGPUParent.cpp | 7 +++---- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/dom/webgpu/CanvasContext.cpp b/dom/webgpu/CanvasContext.cpp index f1f9378823b0..ce98f491b406 100644 --- a/dom/webgpu/CanvasContext.cpp +++ b/dom/webgpu/CanvasContext.cpp @@ -100,6 +100,8 @@ void CanvasContext::GetCanvas( void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aConfig) { Unconfigure(); + // Bug 1864904: Failures in validation should throw a TypeError, per spec. + // these formats are guaranteed by the spec switch (aConfig.mFormat) { case dom::GPUTextureFormat::Rgba8unorm: diff --git a/dom/webgpu/Device.cpp b/dom/webgpu/Device.cpp index e9f4b22bed7f..d3a80d429b3f 100644 --- a/dom/webgpu/Device.cpp +++ b/dom/webgpu/Device.cpp @@ -43,6 +43,13 @@ GPU_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_INHERITED(Device, DOMEventTargetHelper, NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(Device, DOMEventTargetHelper) GPU_IMPL_JS_WRAP(Device) +/* static */ CheckedInt Device::BufferStrideWithMask( + const gfx::IntSize& aSize, const gfx::SurfaceFormat& aFormat) { + constexpr uint32_t kBufferAlignmentMask = 0xff; + return CheckedInt(aSize.width) * gfx::BytesPerPixel(aFormat) + + kBufferAlignmentMask; +} + RefPtr Device::GetBridge() { return mBridge; } Device::Device(Adapter* const aParent, RawId aId, @@ -358,6 +365,13 @@ already_AddRefed Device::InitSwapChain( return nullptr; } + // Check that aCanvasSize and aFormat will generate a texture stride + // within limits. + const auto bufferStrideWithMask = BufferStrideWithMask(aCanvasSize, aFormat); + if (!bufferStrideWithMask.isValid()) { + return nullptr; + } + const layers::RGBDescriptor rgbDesc(aCanvasSize, aFormat); // buffer count doesn't matter much, will be created on demand const size_t maxBufferCount = 10; diff --git a/dom/webgpu/Device.h b/dom/webgpu/Device.h index a5d59e8f814a..bb595c971534 100644 --- a/dom/webgpu/Device.h +++ b/dom/webgpu/Device.h @@ -90,6 +90,9 @@ class Device final : public DOMEventTargetHelper, public SupportsWeakPtr { RefPtr mFeatures; RefPtr mLimits; + static CheckedInt BufferStrideWithMask( + const gfx::IntSize& aSize, const gfx::SurfaceFormat& aFormat); + explicit Device(Adapter* const aParent, RawId aId, const ffi::WGPULimits&); RefPtr GetBridge(); diff --git a/dom/webgpu/ipc/WebGPUParent.cpp b/dom/webgpu/ipc/WebGPUParent.cpp index 5814390734ef..dd3de999eea2 100644 --- a/dom/webgpu/ipc/WebGPUParent.cpp +++ b/dom/webgpu/ipc/WebGPUParent.cpp @@ -864,15 +864,14 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateSwapChain( return IPC_OK(); } - constexpr uint32_t kBufferAlignmentMask = 0xff; - const auto bufferStrideWithMask = CheckedInt(aDesc.size().width) * - gfx::BytesPerPixel(aDesc.format()) + - kBufferAlignmentMask; + const auto bufferStrideWithMask = + Device::BufferStrideWithMask(aDesc.size(), aDesc.format()); if (!bufferStrideWithMask.isValid()) { MOZ_ASSERT_UNREACHABLE("Invalid width / buffer stride!"); return IPC_OK(); } + constexpr uint32_t kBufferAlignmentMask = 0xff; const uint32_t bufferStride = bufferStrideWithMask.value() & ~kBufferAlignmentMask; -- 2.11.4.GIT