High chrome Memory Corruption 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactMemory corruption in Dawn
DescriptionMemory corruption in Dawn
ComponentDawn
Sub-componentDawn
Bug ClassMemory Corruption
Tracker536639352
Fix commita27ffc75ee5f (dawn) +1116/-753
CISA KEVNot listed
CreditedGoogle
Disclosed2026-10-20

Changed Functions

FunctionChangeNotes
CreateDevice
src/dawn/native/Adapter.cpp
modified
if
src/dawn/native/CommandEncoder.cpp
modified

Files Changed

  • src/dawn/native/d3d11/SharedTextureMemoryD3D11.h
  • src/dawn/native/RenderBundleEncoder.cpp
  • src/dawn/native/webgpu/DeviceWGPU.h
  • src/dawn/native/metal/QueueMTL.h
  • src/dawn/native/EncodingContext.h
  • src/dawn/tests/unittests/native/mocks/DeviceMock.h
  • src/dawn/native/vulkan/SharedFenceVk.cpp
  • src/dawn/native/webgpu/ComputePipelineWGPU.cpp
  • src/dawn/native/Adapter.h
  • src/dawn/native/ComputePipeline.h
  • src/dawn/native/d3d11/RenderPipelineD3D11.h
  • src/dawn/native/vulkan/RenderPipelineVk.cpp
  • src/dawn/tests/unittests/native/mocks/RenderPipelineMock.cpp
  • src/dawn/native/Adapter.cpp
  • src/dawn/native/d3d12/DeviceD3D12.cpp
  • src/dawn/native/vulkan/TextureVk.cpp
  • src/dawn/native/d3d11/RenderPipelineD3D11.cpp
  • src/dawn/native/opengl/DeviceGL.h
  • src/dawn/native/metal/ShaderModuleMTL.mm
  • src/dawn/native/d3d12/RenderPipelineD3D12.h
  • src/dawn/tests/unittests/native/AllowedErrorTests.cpp
  • src/dawn/native/stream/BlobSource.cpp
  • src/dawn/native/IndirectDrawValidationEncoder.h
  • src/dawn/native/opengl/SharedTextureMemoryGL.cpp
  • src/dawn/native/webgpu/RenderPipelineWGPU.h
  • src/dawn/native/d3d12/ComputePipelineD3D12.cpp
  • src/dawn/native/opengl/RenderPipelineGL.cpp
  • src/dawn/native/metal/RenderPipelineMTL.h
  • src/dawn/native/Buffer.h
  • src/dawn/native/null/DeviceNull.cpp
  • src/dawn/native/vulkan/TextureVk.h
  • src/dawn/native/vulkan/external_memory/MemoryServiceImplementationAHardwareBuffer.cpp
  • src/dawn/native/CacheRequest.cpp
  • src/dawn/native/metal/SharedTextureMemoryMTL.h
  • src/dawn/native/d3d11/ShaderModuleD3D11.h
  • src/dawn/native/stream/Stream.h
  • src/dawn/native/ShaderModule.h
  • src/dawn/native/webgpu/SharedTextureMemoryWGPU.h
  • src/dawn/native/CacheRequest.h
  • src/dawn/native/CommandEncoder.h
  • src/dawn/native/RenderBundleEncoder.h
  • src/dawn/native/Instance.h
  • src/dawn/native/vulkan/RenderPipelineVk.h
  • src/dawn/native/Queue.cpp
  • src/dawn/native/metal/DeviceMTL.h
  • src/dawn/native/d3d12/ComputePipelineD3D12.h
  • src/dawn/native/webgpu/SharedFenceWGPU.h
  • src/dawn/native/opengl/EGLFunctions.cpp
  • src/dawn/native/Queue.h
  • src/dawn/native/opengl/DeviceGL.cpp
  • src/dawn/native/SwapChain.cpp
  • src/dawn/native/vulkan/DeviceVk.h
  • src/dawn/native/Device.h
  • src/dawn/native/vulkan/ComputePipelineVk.cpp
  • src/dawn/native/SharedBufferMemory.cpp
  • src/dawn/native/Texture.h
  • src/dawn/native/d3d12/SharedTextureMemoryD3D12.h
  • src/dawn/native/d3d/SharedTextureMemoryD3D.h
  • src/dawn/native/d3d12/RenderPipelineD3D12.cpp
  • src/dawn/native/IndirectDrawValidationEncoder.cpp
  • src/dawn/native/CommandEncoder.cpp
  • src/dawn/native/vulkan/SharedTextureMemoryVk.cpp
  • src/dawn/native/d3d/SharedTextureMemoryD3D.cpp
  • src/dawn/native/metal/QueueMTL.mm
  • src/dawn/native/opengl/TextureGL.cpp
  • src/dawn/native/PipelineLayout.h
  • src/dawn/common/Result.h
  • src/dawn/native/Error.h
  • src/dawn/native/webgpu/ComputePipelineWGPU.h
  • src/dawn/native/vulkan/ShaderModuleVk.cpp
  • src/dawn/native/d3d11/ShaderModuleD3D11.cpp
  • src/dawn/native/vulkan/external_memory/MemoryServiceImplementation.h
  • src/dawn/native/vulkan/SharedFenceVk.h
  • src/dawn/native/d3d12/ShaderModuleD3D12.cpp
  • src/dawn/native/webgpu/SharedFenceWGPU.cpp
  • src/dawn/native/opengl/ShaderModuleGL.cpp
  • src/dawn/native/opengl/SharedTextureMemoryEGL.h
  • src/dawn/native/vulkan/external_memory/MemoryServiceImplementationDmaBuf.cpp
  • src/dawn/native/d3d12/SharedBufferMemoryD3D12.cpp
  • src/dawn/native/Pipeline.h
  • src/dawn/native/metal/RenderPipelineMTL.mm
  • src/dawn/native/opengl/PipelineGL.h
  • src/dawn/native/d3d11/ComputePipelineD3D11.cpp
  • src/dawn/tests/unittests/native/mocks/DeviceMock.cpp
  • src/dawn/native/vulkan/external_memory/MemoryServiceImplementationOpaqueFD.cpp
  • src/dawn/native/EncodingContext.cpp
  • src/dawn/native/SharedResourceMemory.cpp
  • src/dawn/native/RenderPassEncoder.cpp
  • src/dawn/native/d3d/ShaderUtils.h
  • src/dawn/native/Instance.cpp
  • src/dawn/native/webgpu/RenderPipelineWGPU.cpp
  • src/dawn/native/metal/SharedFenceMTL.mm
  • src/dawn/native/opengl/ComputePipelineGL.cpp
  • src/dawn/native/Buffer.cpp
  • src/dawn/native/metal/ComputePipelineMTL.h
  • src/dawn/native/metal/SharedTextureMemoryMTL.mm
  • src/dawn/native/d3d12/ShaderModuleD3D12.h
  • src/dawn/native/vulkan/SwapChainVk.h
  • src/dawn/native/Pipeline.cpp
  • src/dawn/native/vulkan/DeviceVk.cpp
  • src/dawn/native/d3d12/SharedFenceD3D12.cpp
  • src/dawn/native/vulkan/external_memory/MemoryService.h
  • src/dawn/native/vulkan/SwapChainVk.cpp
  • src/dawn/native/d3d12/SharedBufferMemoryD3D12.h
  • src/dawn/native/null/DeviceNull.h
  • src/dawn/native/opengl/RenderPipelineGL.h
  • src/dawn/native/opengl/ComputePipelineGL.h
  • src/dawn/native/RenderPipeline.cpp
  • src/dawn/native/opengl/SharedTextureMemoryGL.h
  • src/dawn/tests/end2end/TextureZeroInitTests.cpp
  • src/dawn/tests/unittests/native/mocks/ComputePipelineMock.h
  • src/dawn/native/d3d/ShaderUtils.cpp
  • src/dawn/native/d3d12/SharedFenceD3D12.h
  • src/dawn/native/webgpu/DeviceWGPU.cpp
  • src/dawn/native/Error.cpp
  • src/dawn/native/SharedResourceMemory.h
  • src/dawn/native/vulkan/ShaderModuleVk.h
  • src/dawn/native/Texture.cpp
  • src/dawn/native/d3d12/DeviceD3D12.h
  • src/dawn/native/PipelineLayout.cpp
  • src/dawn/native/CreatePipelineAsyncEvent.h
  • src/dawn/native/Device.cpp
  • src/dawn/native/ComputePassEncoder.cpp
  • src/dawn/native/utils/NativeHelpers.cpp
  • src/dawn/native/RenderPipeline.h
  • src/dawn/native/vulkan/SharedTextureMemoryVk.h
  • src/dawn/native/opengl/PipelineGL.cpp
  • src/dawn/native/SwapChain.h
  • src/dawn/tests/unittests/native/CacheRequestTests.cpp
  • src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp
  • src/dawn/native/opengl/BufferGL.cpp
  • src/dawn/native/ShaderModule.cpp
  • src/dawn/native/vulkan/external_memory/MemoryService.cpp
  • src/dawn/tests/unittests/native/mocks/RenderPipelineMock.h
  • src/dawn/native/SharedTextureMemory.cpp
  • src/dawn/native/opengl/DisplayEGL.cpp
  • src/dawn/native/metal/ComputePipelineMTL.mm
  • src/dawn/native/d3d11/DeviceD3D11.cpp
  • src/dawn/native/opengl/SharedTextureMemoryEGL.cpp
  • src/dawn/native/opengl/ShaderModuleGL.h
  • src/dawn/native/ComputePipeline.cpp
  • src/dawn/native/d3d11/DeviceD3D11.h
  • src/dawn/native/webgpu/SharedTextureMemoryWGPU.cpp
  • src/dawn/native/metal/DeviceMTL.mm
  • src/dawn/native/metal/ShaderModuleMTL.h
  • src/dawn/native/Surface.h
  • src/dawn/native/d3d12/SharedTextureMemoryD3D12.cpp
  • src/dawn/tests/unittests/native/mocks/ComputePipelineMock.cpp
  • src/dawn/native/opengl/SharedFenceEGL.h
  • src/dawn/native/d3d11/ComputePipelineD3D11.h
  • src/dawn/tests/end2end/BufferZeroInitTests.cpp
  • src/dawn/native/ErrorSink.h
  • src/dawn/native/CreatePipelineAsyncEvent.cpp
  • src/dawn/native/metal/SharedFenceMTL.h
  • src/dawn/native/d3d11/SharedFenceD3D11.h
  • src/dawn/native/opengl/SharedFenceEGL.cpp
  • src/dawn/native/d3d11/SharedFenceD3D11.cpp
  • src/dawn/native/RenderEncoderBase.cpp
  • src/dawn/native/vulkan/ComputePipelineVk.h
  • src/dawn/native/Surface.cpp
  • src/dawn/tests/unittests/native/CreatePipelineAsyncEventTests.cpp
From a27ffc75ee5f141c0d623c60b58923baca533aff Mon Sep 17 00:00:00 2001
From: dan sinclair <[email protected]>
Date: Mon, 05 Oct 2026 16:40:32 -0700
Subject: [PATCH] [dawn] Add UnknownError

Add an UnknownError class. This is for the case where we don't know if
the result is an Internal or Validation error. Handles the conversion
from Validation to Internal and disallows other transforms.

Bug: 536639352
Change-Id: I293bedac746ebee5fe53053697e44457c5be6227
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/343895
Commit-Queue: dan sinclair <[email protected]>
Reviewed-by: Corentin Wallez <[email protected]>
Reviewed-by: Loko Kung <[email protected]>
SLSA-Policy-Verified: SLSA Policy Verification Service <[email protected]>
---
diff --git a/src/dawn/common/Result.h b/src/dawn/common/Result.h
index e311064..1f35588 100644
--- a/src/dawn/common/Result.h
+++ b/src/dawn/common/Result.h
@@ -211,6 +211,11 @@
         requires std::convertible_to<U*, T*>
     Result<Ref<U>, E>& operator=(Result<Ref<U>, E>&& other);
 
+    template <typename E2, typename U>
+        requires(std::convertible_to<U*, T*> && !std::same_as<E, E2> &&
+                 std::constructible_from<E, std::unique_ptr<E2>>)
+    explicit(false) Result(Result<Ref<U>, E2>&& other);
+
     ~Result();
 
     bool IsError() const;
@@ -439,6 +444,14 @@
 }
 
 template <typename T, typename E>
+template <typename E2, typename U>
+    requires(std::convertible_to<U*, T*> && !std::same_as<E, E2> &&
+             std::constructible_from<E, std::unique_ptr<E2>>)
+Result<Ref<T>, E>::Result(Result<Ref<U>, E2>&& other)
+    : Result(other.IsError() ? Result(std::make_unique<E>(other.AcquireError()))
+                             : Result(other.AcquireSuccess())) {}
+
+template <typename T, typename E>
 template <typename U>
     requires std::convertible_to<U*, T*>
 Result<Ref<U>, E>& Result<Ref<T>, E>::operator=(Result<Ref<U>, E>&& other) {
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 2274cb7..84b5a0d 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -235,7 +235,7 @@
     return ReturnToAPI(std::move(device));
 }
 
-ResultOrError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
+ResultOrUnknownError<Ref<DeviceBase>> AdapterBase::CreateDeviceInternal(
     const DeviceDescriptor* rawDescriptor,
     Ref<DeviceBase::DeviceLostEvent> lostEvent) {
     DAWN_CHECK(rawDescriptor != nullptr);
@@ -305,7 +305,7 @@
     DAWN_INVALID_IF(mAdapterIsConsumed,
                     "adapter is \"consumed\": it has already been used to create a device");
 
-    auto result =
+    ResultOrError<Ref<DeviceBase>> result =
         mPhysicalDevice->CreateDevice(this, descriptor, deviceToggles, std::move(lostEvent));
 
     // The adapter should be consumed only upon successful device creation if the instance doesn't
@@ -317,11 +317,10 @@
     if (result.IsSuccess() && consumeOnSuccess) {
         mAdapterIsConsumed = true;
     }
-
     return result;
 }
 
-std::pair<Ref<DeviceBase::DeviceLostEvent>, ResultOrError<Ref<DeviceBase>>>
+std::pair<Ref<DeviceBase::DeviceLostEvent>, ResultOrUnknownError<Ref<DeviceBase>>>
 AdapterBase::CreateDevice(const DeviceDescriptor* descriptor) {
     DAWN_CHECK(descriptor != nullptr);
 
@@ -330,7 +329,7 @@
 
     // Catch any errors to directly complete the device lost event with the error message.
     if (result.IsError()) {
-        auto error = result.AcquireError();
+        std::unique_ptr<UnknownError> error = result.AcquireError();
         lostEvent->SetLost(mInstance->GetEventManager(), wgpu::DeviceLostReason::FailedCreation,
                            "Failed to create device:\n" + error->GetFormattedMessage());
 
diff --git a/src/dawn/native/Adapter.h b/src/dawn/native/Adapter.h
index d32d3ff..7abf727 100644
--- a/src/dawn/native/Adapter.h
+++ b/src/dawn/native/Adapter.h
@@ -93,10 +93,11 @@
     const std::string& GetName() const;
 
   private:
-    std::pair<Ref<DeviceBase::DeviceLostEvent>, ResultOrError<Ref<DeviceBase>>> CreateDevice(
+    std::pair<Ref<DeviceBase::DeviceLostEvent>, ResultOrUnknownError<Ref<DeviceBase>>> CreateDevice(
         const DeviceDescriptor* rawDescriptor);
-    ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* rawDescriptor,
-                                                        Ref<DeviceBase::DeviceLostEvent> lostEvent);
+    ResultOrUnknownError<Ref<DeviceBase>> CreateDeviceInternal(
+        const DeviceDescriptor* rawDescriptor,
+        Ref<DeviceBase::DeviceLostEvent> lostEvent);
 
     ResultOrValError<UnpackedPtr<AdapterInfo>> ValidateGetInfo(AdapterInfo* info) const;
     ResultOrValError<UnpackedPtr<DawnFormatCapabilities>> ValidateGetFormatCapabilities(
diff --git a/src/dawn/native/Buffer.cpp b/src/dawn/native/Buffer.cpp
index 9d6de63..2a3e775 100644
--- a/src/dawn/native/Buffer.cpp
+++ b/src/dawn/native/Buffer.cpp
@@ -67,7 +67,7 @@
 
 namespace {
 
-std::unique_ptr<ValidationError> ConcurrentUseError() {
+UnknownError ConcurrentUseError() {
     return DAWN_VALIDATION_ERROR("Concurrent buffer operations are not allowed");
 }
 
@@ -544,7 +544,8 @@
             case BufferState::InUse: {
                 // This is never supposed to happen but another operation is happening concurrently
                 // with API Destroy() call.
-                GetDevice()->ConsumeError(ConcurrentUseError(), "calling %s.Destroy().", this);
+                GetDevice()->ConsumeError(ConcurrentUseError().TakeAsVal(), "calling %s.Destroy().",
+                                          this);
                 while (mState.load(std::memory_order::acquire) == BufferState::InUse) {
                     // Spin loop instead of wait() to avoid overhead of signal in map/unmap.
                 }
@@ -811,7 +812,7 @@
         }
 
         WGPUMapAsyncStatus errorStatus = WGPUMapAsyncStatus_Aborted;
-        MaybeValError maybeError = [&]() -> MaybeValError {
+        MaybeUnknownError maybeError = [&]() -> MaybeUnknownError {
             DAWN_TRY(GetDevice()->ValidateIsAlive());
             errorStatus = WGPUMapAsyncStatus_Error;
             DAWN_TRY(ValidateMapAsync(mode, offset, size));
@@ -842,7 +843,7 @@
         }();
 
         if (maybeError.IsError()) {
-            auto error = maybeError.AcquireError();
+            std::unique_ptr<UnknownError> error = maybeError.AcquireError();
             event = AcquireRef(new MapAsyncEvent(callbackInfo, error->GetMessage(), errorStatus));
             GetDevice()->ConsumeError(std::move(error), "calling %s.MapAsync(%s, %u, %u, ...).",
                                       this, mode, offset, size);
@@ -947,9 +948,10 @@
     if (GetDevice()->ConsumedError(ValidateUnmap(), "calling %s.Unmap().", this)) {
         return;
     }
-    auto unmap = [&]() -> MaybeError {
+    auto unmap = [&]() -> MaybeUnknownError {
         DAWN_TRY(UnmapInternal(false));
-        return GetDevice()->GetDynamicUploader()->MaybeSubmitPendingCommands();
+        DAWN_TRY(GetDevice()->GetDynamicUploader()->MaybeSubmitPendingCommands());
+        return {};
     };
     std::ignore = GetDevice()->ConsumedError(unmap(), "calling %s.Unmap().", this);
 }
@@ -1015,7 +1017,7 @@
     return std::move(mPendingMapEvent);
 }
 
-MaybeError BufferBase::UnmapInternal(bool forDestroy) {
+MaybeValError BufferBase::UnmapInternal(bool forDestroy) {
     BufferState state = mState.load(std::memory_order::acquire);
 
     // If the buffer is already destroyed, we don't need to do anything.
@@ -1239,7 +1241,7 @@
     dump->AddString(name.c_str(), "usage", absl::StrFormat("%s", GetInternalUsage()));
 }
 
-ResultOrError<Ref<TexelBufferViewBase>> BufferBase::CreateTexelView(
+ResultOrUnknownError<Ref<TexelBufferViewBase>> BufferBase::CreateTexelView(
     const TexelBufferViewDescriptor* descriptor) {
     DAWN_CHECK(descriptor != nullptr);
     return GetDevice()->CreateTexelBufferView(this, descriptor);
diff --git a/src/dawn/native/Buffer.h b/src/dawn/native/Buffer.h
index 61ee7b7..57465b5 100644
--- a/src/dawn/native/Buffer.h
+++ b/src/dawn/native/Buffer.h
@@ -210,7 +210,7 @@
     wgpu::BufferMapState APIGetMapState() const;
     uint64_t APIGetSize() const;
 
-    ResultOrError<Ref<TexelBufferViewBase>> CreateTexelView(
+    ResultOrUnknownError<Ref<TexelBufferViewBase>> CreateTexelView(
         const TexelBufferViewDescriptor* descriptor);
     TexelBufferViewBase* APICreateTexelView(const TexelBufferViewDescriptor* descriptor);
 
@@ -271,7 +271,7 @@
                                                           bool writable);
     [[nodiscard]] Ref<MapAsyncEvent> UnmapEarly(BufferState newState,
                                                 std::string_view abortMessage);
-    MaybeError UnmapInternal(bool forDestroy);
+    MaybeValError UnmapInternal(bool forDestroy);
 
     // Updates internal state to reflect that the buffer is now mapped.
     MaybeError FinalizeMap(BufferState newState);
diff --git a/src/dawn/native/CacheRequest.cpp b/src/dawn/native/CacheRequest.cpp
index 4c1ef32..fe4f901 100644
--- a/src/dawn/native/CacheRequest.cpp
+++ b/src/dawn/native/CacheRequest.cpp
@@ -35,4 +35,8 @@
     dawn::ErrorLog() << error->GetFormattedMessage();
 }
 
+void LogCacheError(std::unique_ptr<UnknownError> error) {
+    dawn::ErrorLog() << error->GetFormattedMessage();
+}
+
 }  // namespace dawn::native::detail
diff --git a/src/dawn/native/CacheRequest.h b/src/dawn/native/CacheRequest.h
index 896ad0f..23210be 100644
--- a/src/dawn/native/CacheRequest.h
+++ b/src/dawn/native/CacheRequest.h
@@ -48,6 +48,7 @@
 namespace detail {
 
 void LogCacheError(std::unique_ptr<UnrecoverableError> error);
+void LogCacheError(std::unique_ptr<UnknownError> error);
 
 }  // namespace detail
 
@@ -113,7 +114,7 @@
             std::is_convertible_v<CacheMissFn, CacheMissReturnType (*)(Request)>,
             "CacheMissFn function signature does not match, or it is not a free function.");
 
-        static_assert(detail::IsResultOrError<CacheMissReturnType>::value,
+        static_assert(detail::IsResultOrUnknownError<CacheMissReturnType>::value,
                       "CacheMissFn should return a ResultOrError.");
         using UnwrappedReturnType = typename detail::UnwrapResultOrError<CacheMissReturnType>::type;
 
@@ -122,7 +123,7 @@
                       "If CacheMissFn returns T, CacheHitFn must return T or ResultOrError<T>.");
 
         using CacheResultType = CacheResult<UnwrappedReturnType>;
-        using ReturnType = ResultOrError<CacheResultType>;
+        using ReturnType = ResultOrUnknownError<CacheResultType>;
 
         CacheKey key = r.CreateCacheKey(device);
         platform::metrics::DawnHistogramTimer cacheTimer(
diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp
index 4e39b42..7ae6f48 100644
--- a/src/dawn/native/CommandEncoder.cpp
+++ b/src/dawn/native/CommandEncoder.cpp
@@ -1035,13 +1035,13 @@
 
 // Adds a single attachment to the validation state to ensure that it is valid and can report a
 // render width and height.
-MaybeError InitializeValidationStateAttachment(DeviceBase* device,
-                                               UnpackedPtr<RenderPassDescriptor> descriptor,
-                                               RenderPassValidationState* validationState) {
+MaybeValError InitializeValidationStateAttachment(DeviceBase* device,
+                                                  UnpackedPtr<RenderPassDescriptor> descriptor,
+                                                  RenderPassValidationState* validationState) {
     TextureViewBase* representativeView = nullptr;
 
     // Check every attachment to guard against invalid objects caused by OOM errors.
-    auto CheckAttachment = [&](TextureViewBase* view) -> MaybeError {
+    auto CheckAttachment = [&](TextureViewBase* view) -> MaybeValError {
         DAWN_CHECK(view);
         DAWN_TRY(device->IsNotErrorObject(view));
         representativeView = view;
@@ -1410,7 +1410,7 @@
 
     bool success = mEncodingContext.TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeValError {
             if (GetDevice()->IsValidationEnabled()) {
                 DAWN_TRY(ValidateComputePassDescriptor(device, descriptor));
             }
@@ -1492,7 +1492,7 @@
 
     bool success = mEncodingContext.TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeUnknownError {
             DAWN_TRY_ASSIGN_CONTEXT(descriptor, ValidateAndUnpack(rawDescriptor),
                                     "validating and unpacking chained structs.");
 
@@ -1960,7 +1960,7 @@
 
     mEncodingContext.TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeUnknownError {
             if (GetDevice()->IsValidationEnabled()) {
                 DAWN_TRY(ValidateTexelCopyTextureInfo(GetDevice(), source, *copySize));
                 DAWN_TRY_CONTEXT(ValidateCanUseAs(source.texture, wgpu::TextureUsage::CopySrc,
@@ -2285,7 +2285,7 @@
     std::string_view groupLabel = utils::NormalizeMessageString(groupLabelIn);
     mEncodingContext.TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeValError {
             PushDebugGroupCmd* cmd =
                 allocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup);
             std::string_view copiedLabel =
@@ -2309,7 +2309,7 @@
 
     mEncodingContext.TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeUnknownError {
             if (GetDevice()->IsValidationEnabled()) {
                 DAWN_TRY(GetDevice()->ValidateObject(querySet));
                 DAWN_TRY(GetDevice()->ValidateObject(destination));
@@ -2346,8 +2346,9 @@
             }
 
             auto deviceGuard = GetDevice()->GetGuard();
-            return EncodeTimestampsToNanosecondsConversion(this, querySet, firstQuery, queryCount,
-                                                           destination, destinationOffset);
+            DAWN_TRY(EncodeTimestampsToNanosecondsConversion(this, querySet, firstQuery, queryCount,
+                                                             destination, destinationOffset));
+            return {};
         },
         "encoding %s.ResolveQuerySet(%s, %u, %u, %s, %u).", this, querySet, firstQuery, queryCount,
         destination, destinationOffset);
@@ -2358,7 +2359,7 @@
                                     Span<const std::byte> data) {
     mEncodingContext.TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeValError {
             if (GetDevice()->IsValidationEnabled()) {
                 DAWN_TRY(ValidateWriteBuffer(GetDevice(), buffer, bufferOffset, data.size()));
             }
@@ -2419,7 +2420,7 @@
     return ReturnToAPI(std::move(commandBuffer));
 }
 
-ResultOrError<Ref<CommandBufferBase>> CommandEncoder::Finish(
+ResultOrUnknownError<Ref<CommandBufferBase>> CommandEncoder::Finish(
     const CommandBufferDescriptor* descriptor) {
     DeviceBase* device = GetDevice();
 
@@ -2439,7 +2440,6 @@
     if (descriptor == nullptr) {
         descriptor = &defaultDescriptor;
     }
-
     return device->CreateCommandBuffer(this, descriptor);
 }
 
diff --git a/src/dawn/native/CommandEncoder.h b/src/dawn/native/CommandEncoder.h
index 0a74ad2..e6176d5 100644
--- a/src/dawn/native/CommandEncoder.h
+++ b/src/dawn/native/CommandEncoder.h
@@ -108,7 +108,7 @@
 
     Ref<ComputePassEncoder> BeginComputePass(const ComputePassDescriptor* descriptor = nullptr);
     Ref<RenderPassEncoder> BeginRenderPass(const RenderPassDescriptor* rawDescriptor);
-    ResultOrError<Ref<CommandBufferBase>> Finish(
+    ResultOrUnknownError<Ref<CommandBufferBase>> Finish(
         const CommandBufferDescriptor* descriptor = nullptr);
 
     // `InternalUsageScope` is a scoped class that temporarily changes validation such that the
diff --git a/src/dawn/native/ComputePassEncoder.cpp b/src/dawn/native/ComputePassEncoder.cpp
index 339cd44..a97caa4 100644
--- a/src/dawn/native/ComputePassEncoder.cpp
+++ b/src/dawn/native/ComputePassEncoder.cpp
@@ -208,7 +208,7 @@
 
     if (mEncodingContext->TryEncode(
             this,
-            [&](CommandAllocator* allocator) -> MaybeError {
+            [&](CommandAllocator* allocator) -> MaybeValError {
                 if (IsValidationEnabled()) {
                     DAWN_TRY(ValidateProgrammableEncoderEnd());
                 }
@@ -496,7 +496,7 @@
 void ComputePassEncoder::APISetPipeline(ComputePipelineBase* pipeline) {
     mEncodingContext->TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeValError {
             if (IsValidationEnabled()) {
                 DAWN_TRY(GetDevice()->ValidateObject(pipeline));
             }
@@ -546,7 +546,7 @@
                                          ityp::span<BindingIndex, const uint32_t> dynamicOffsets) {
     mEncodingContext->TryEncode(
         this,
-        [&](CommandAllocator* allocator) -> MaybeError {
+        [&](CommandAllocator* allocator) -> MaybeValError {
             BindGroupIndex groupIndex(groupIndexIn);
 
             if (IsValidationEnabled()) {
@@ -570,7 +570,7 @@
 void ComputePassEncoder::APISetImmediates(uint32_t offset, Span<const std::byte> data) {
     mEncodingContext->TryEncode(
... (file diff truncated)
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/src/dawn/tests/end2end/BufferZeroInitTests.cpp b/src/dawn/tests/end2end/BufferZeroInitTests.cpp
index 98800b4..6a8e7ee 100644
--- a/src/dawn/tests/end2end/BufferZeroInitTests.cpp
+++ b/src/dawn/tests/end2end/BufferZeroInitTests.cpp
@@ -1514,7 +1514,16 @@
 // executing prior commands from the rejected submit.
 //
 // https://crbug.com/563359278
-TEST_P(BufferZeroInitMaxBufferSizeTest, DISABLED_CopyTextureToBufferLargerThanMaxBufferSize) {
+TEST_P(BufferZeroInitMaxBufferSizeTest, CopyTextureToBufferLargerThanMaxBufferSize) {
+    // Requires validation to trigger on the buffer size mismatch
+    DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
+
+    // Test fails with WebGPU on WebGPU with a : `Inner Device on WebGPU backend on
+    // BackendType::Metal Apple M3 Pro"] is lost.` error. This implies it's doing the right thing,
+    // in that we are losing the device but because WebGPUOnWebGPU wraps the error we get the
+    // incorrect error output.
+    DAWN_SUPPRESS_TEST_IF(IsWebGPUOnWebGPU());
+
     constexpr wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA32Float;
     constexpr uint32_t kBytesPerTexel = 16u;
     constexpr wgpu::Extent3D kPoisonSize = {256u, 256u, 257u};
diff --git a/src/dawn/tests/end2end/TextureZeroInitTests.cpp b/src/dawn/tests/end2end/TextureZeroInitTests.cpp
index 06f4136..ab8f5cd 100644
--- a/src/dawn/tests/end2end/TextureZeroInitTests.cpp
+++ b/src/dawn/tests/end2end/TextureZeroInitTests.cpp
@@ -2902,7 +2902,10 @@
 // destination cannot be read back.
 //
 // https://crbug.com/536639352
-TEST_P(CompressedTextureZeroInitTest, DISABLED_CopyTextureToTextureLargerThanMaxBufferSize) {
+TEST_P(CompressedTextureZeroInitTest, CopyTextureToTextureLargerThanMaxBufferSize) {
+    // Requires validation to trigger on the buffer size mismatch
+    DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
+
     // Compatibility mode does not support compressed texture-to-texture copies.
     DAWN_TEST_UNSUPPORTED_IF(IsCompatibilityMode());
diff --git a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
index 3b020d0..929ede4 100644
--- a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
+++ b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
@@ -82,7 +82,7 @@
 
 TEST_F(AllowedErrorTests, QueueSubmit) {
     EXPECT_CALL(*(mDeviceMock->GetQueueMock()), SubmitImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the device lost because of the error.
     EXPECT_CALL(mDeviceLostCallback, Call(CHandleIs(device.Get()), wgpu::DeviceLostReason::Unknown,
@@ -100,7 +100,7 @@
     wgpu::Buffer buffer = wgpu::Buffer::Acquire(ToAPI(ReturnToAPI(std::move(bufferMock))));
 
     EXPECT_CALL(*(mDeviceMock->GetQueueMock()), WriteBufferImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the device lost because of the error.
     EXPECT_CALL(mDeviceLostCallback, Call(CHandleIs(device.Get()), wgpu::DeviceLostReason::Unknown,
@@ -121,7 +121,7 @@
     wgpu::Texture texture = wgpu::Texture::Acquire(ToAPI(ReturnToAPI(std::move(textureMock))));
 
     EXPECT_CALL(*(mDeviceMock->GetQueueMock()), WriteTextureImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the device lost because of the error.
     EXPECT_CALL(mDeviceLostCallback, Call(CHandleIs(device.Get()), wgpu::DeviceLostReason::Unknown,
@@ -154,7 +154,7 @@
 
     // Copying texture for browser internally allocates a buffer which we will cause to fail here.
     EXPECT_CALL(*mDeviceMock, CreateBufferImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the device lost because of the error.
     EXPECT_CALL(mDeviceLostCallback, Call(CHandleIs(device.Get()), wgpu::DeviceLostReason::Unknown,
@@ -196,7 +196,7 @@
 
     // Copying texture for browser internally allocates a buffer which we will cause to fail here.
     EXPECT_CALL(*mDeviceMock, CreateBufferImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the device lost because of the error.
     EXPECT_CALL(mDeviceLostCallback, Call(CHandleIs(device.Get()), wgpu::DeviceLostReason::Unknown,
@@ -214,7 +214,7 @@
 
     Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*computePipelineMock.Get(), InitializeImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
         .WillOnce(Return(ByMove(std::move(computePipelineMock))));
 
@@ -240,7 +240,7 @@
 
     Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*renderPipelineMock.Get(), InitializeImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
         .WillOnce(Return(ByMove(std::move(renderPipelineMock))));
 
@@ -262,7 +262,8 @@
     Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*computePipelineMock.Get(), InitializeImpl)
         .WillOnce(
-            Return(ByMove(DAWN_PIPELINE_UNCATEGORIZED_ERROR(kPipelineUncategorizedErrorMessage))));
+            Return(ByMove(DAWN_PIPELINE_UNCATEGORIZED_ERROR(kPipelineUncategorizedErrorMessage)
+                              .TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
         .WillOnce(Return(ByMove(std::move(computePipelineMock))));
 
@@ -291,7 +292,8 @@
     Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*renderPipelineMock.Get(), InitializeImpl)
         .WillOnce(
-            Return(ByMove(DAWN_PIPELINE_UNCATEGORIZED_ERROR(kPipelineUncategorizedErrorMessage))));
+            Return(ByMove(DAWN_PIPELINE_UNCATEGORIZED_ERROR(kPipelineUncategorizedErrorMessage)
+                              .TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
         .WillOnce(Return(ByMove(std::move(renderPipelineMock))));
 
@@ -316,7 +318,7 @@
 
     Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*computePipelineMock.Get(), InitializeImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
         .WillOnce(Return(ByMove(std::move(computePipelineMock))));
 
@@ -345,7 +347,7 @@
 
     Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*renderPipelineMock.Get(), InitializeImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
         .WillOnce(Return(ByMove(std::move(renderPipelineMock))));
 
@@ -369,7 +371,8 @@
 
     Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*computePipelineMock.Get(), InitializeImpl)
-        .WillOnce(Return(ByMove(DAWN_UNRECOVERABLE_ERROR(kUnrecoverableErrorMessage))));
+        .WillOnce(
+            Return(ByMove(DAWN_UNRECOVERABLE_ERROR(kUnrecoverableErrorMessage).TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
         .WillOnce(Return(ByMove(std::move(computePipelineMock))));
 
@@ -399,7 +402,8 @@
 
     Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
     EXPECT_CALL(*renderPipelineMock.Get(), InitializeImpl)
-        .WillOnce(Return(ByMove(DAWN_UNRECOVERABLE_ERROR(kUnrecoverableErrorMessage))));
+        .WillOnce(
+            Return(ByMove(DAWN_UNRECOVERABLE_ERROR(kUnrecoverableErrorMessage).TakeAsUnknown())));
     EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
         .WillOnce(Return(ByMove(std::move(renderPipelineMock))));
 
@@ -420,7 +424,7 @@
 // OOM error from buffer creation is allowed and surfaced directly.
 TEST_F(AllowedErrorTests, CreateBuffer) {
     EXPECT_CALL(*mDeviceMock, CreateBufferImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the OOM error.
     EXPECT_CALL(mDeviceErrorCallback, Call(CHandleIs(device.Get()), wgpu::ErrorType::OutOfMemory,
@@ -436,7 +440,7 @@
 // OOM error from texture creation is allowed and surfaced directly.
 TEST_F(AllowedErrorTests, CreateTexture) {
     EXPECT_CALL(*mDeviceMock, CreateTextureImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the OOM error.
     EXPECT_CALL(mDeviceErrorCallback, Call(CHandleIs(device.Get()), wgpu::ErrorType::OutOfMemory,
@@ -453,7 +457,7 @@
 // OOM error from query set creation is allowed and surfaced directly.
 TEST_F(AllowedErrorTests, CreateQuerySet) {
     EXPECT_CALL(*mDeviceMock, CreateQuerySetImpl)
-        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage))));
+        .WillOnce(Return(ByMove(DAWN_OUT_OF_MEMORY_ERROR(kOomErrorMessage).TakeAsUnrecoverable())));
 
     // Expect the OOM error.
     EXPECT_CALL(mDeviceErrorCallback, Call(CHandleIs(device.Get()), wgpu::ErrorType::OutOfMemory,
diff --git a/src/dawn/tests/unittests/native/CacheRequestTests.cpp b/src/dawn/tests/unittests/native/CacheRequestTests.cpp
index 2b3d7d5..35578fd 100644
--- a/src/dawn/tests/unittests/native/CacheRequestTests.cpp
+++ b/src/dawn/tests/unittests/native/CacheRequestTests.cpp
@@ -102,19 +102,21 @@
 TEST_P(CacheRequestTests, CacheResultTypes) {
     EXPECT_CALL(mMockCache, FindKey(_)).WillRepeatedly(Return(0));
 
-    // (int, ResultOrError<int>), should be ResultOrError<CacheResult<int>>.
+    // (int, ResultOrUnknownError<int>), should be ResultOrUnknownError<CacheResult<int>>.
     auto v1 = LoadOrRun(
         GetDevice(), CacheRequestForTesting{}, [](Blob) -> int { return 0; },
-        [](CacheRequestForTesting) -> ResultOrError<int> { return 1; });
+        [](CacheRequestForTesting) -> ResultOrUnknownError<int> { return 1; });
     v1.AcquireSuccess();
-    static_assert(std::is_same_v<ResultOrError<CacheResult<int>>, decltype(v1)>);
+    static_assert(std::is_same_v<ResultOrUnknownError<CacheResult<int>>, decltype(v1)>);
 
-    // (ResultOrError<float>, ResultOrError<float>), should be ResultOrError<CacheResult<float>>.
+    // (ResultOrUnknownError<float>, ResultOrUnknownError<float>), should be
+    // ResultOrUnknownError<CacheResult<float>>.
     auto v2 = LoadOrRun(
-        GetDevice(), CacheRequestForTesting{}, [](Blob) -> ResultOrError<float> { return 0.0; },
-        [](CacheRequestForTesting) -> ResultOrError<float> { return 1.0; });
+        GetDevice(), CacheRequestForTesting{},
+        [](Blob) -> ResultOrUnknownError<float> { return 0.0; },
+        [](CacheRequestForTesting) -> ResultOrUnknownError<float> { return 1.0; });
     v2.AcquireSuccess();
-    static_assert(std::is_same_v<ResultOrError<CacheResult<float>>, decltype(v2)>);
+    static_assert(std::is_same_v<ResultOrUnknownError<CacheResult<float>>, decltype(v2)>);
 }
 
 // Test that using a CacheRequest builds a key from the device key, the request type enum, and all
@@ -142,7 +144,7 @@
     // Load the request.
     auto result = LoadOrRun(
                       GetDevice(), std::move(req), [](Blob) -> int { return 0; },
-                      [](CacheRequestForTesting) -> ResultOrError<int> { return 0; })
+                      [](CacheRequestForTesting) -> ResultOrUnknownError<int> { return 0; })
                       .AcquireSuccess();
 
     // The created cache key should be saved on the result.
@@ -175,7 +177,7 @@
     }));
     auto r1 = LoadOrRun(
                   GetDevice(), std::move(req1), [](Blob) { return 0; },
-                  [](CacheRequestForTesting req) -> ResultOrError<int> {
+                  [](CacheRequestForTesting req) -> ResultOrUnknownError<int> {
                       return cacheMissFn.Call(std::move(req));
                   })
                   .AcquireSuccess();
@@ -188,7 +190,7 @@
     }));
     auto r2 = LoadOrRun(
                   GetDevice(), std::move(req2), [](Blob) { return 0; },
-                  [](CacheRequestForTesting req) -> ResultOrError<int> {
+                  [](CacheRequestForTesting req) -> ResultOrUnknownError<int> {
                       return cacheMissFn.Call(std::move(req));
                   })
                   .AcquireSuccess();
@@ -229,7 +231,7 @@
     auto result = LoadOrRun(
                       GetDevice(), std::move(req),
                       [](Blob blob) -> int { return cacheHitFn.Call(std::move(blob)); },
-                      [](CacheRequestForTesting req) -> ResultOrError<int> {
+                      [](CacheRequestForTesting req) -> ResultOrUnknownError<int> {
                           return cacheMissFn.Call(std::move(req));
                       })
                       .AcquireSuccess();
@@ -277,7 +279,7 @@
     auto result = LoadOrRun(
                       GetDevice(), std::move(req),
                       [](Blob blob) -> int { return cacheHitFn.Call(std::move(blob)); },
-                      [](CacheRequestForTesting req) -> ResultOrError<int> {
+                      [](CacheRequestForTesting req) -> ResultOrUnknownError<int> {
                           return cacheMissFn.Call(std::move(req));
                       })
                       .AcquireSuccess();
@@ -297,7 +299,7 @@
 
     unsigned int* cPtr = req.c.data();
 
-    static StrictMock<MockFunction<ResultOrError<int>(Blob)>> cacheHitFn;
+    static StrictMock<MockFunction<ResultOrUnknownError<int>(Blob)>> cacheHitFn;
     static StrictMock<MockFunction<int(CacheRequestForTesting)>> cacheMissFn;
 
     static constexpr char kCachedData[] = "hello world!";
@@ -338,8 +340,8 @@
     auto result =
         LoadOrRun(
             GetDevice(), std::move(req),
-            [](Blob blob) -> ResultOrError<int> { return cacheHitFn.Call(std::move(blob)); },
-            [](CacheRequestForTesting req) -> ResultOrError<int> {
+            [](Blob blob) -> ResultOrUnknownError<int> { return cacheHitFn.Call(std::move(blob)); },
+            [](CacheRequestForTesting req) -> ResultOrUnknownError<int> {
                 return cacheMissFn.Call(std::move(req));
             })
             .AcquireSuccess();
@@ -383,7 +385,7 @@
     auto result = LoadOrRun(
                       GetDevice(), std::move(req),
                       [](Blob blob) -> int { return cacheHitFn.Call(std::move(blob)); },
-                      [](CacheRequestForTesting req) -> ResultOrError<int> {
+                      [](CacheRequestForTesting req) -> ResultOrUnknownError<int> {
                           return cacheMissFn.Call(std::move(req));
                       })
                       .AcquireSuccess();
@@ -470,7 +472,7 @@
         auto result = LoadOrRun(
                           GetDevice(), std::move(req),
                           [](Blob blob) -> int { return cacheHitFn->Call(std::move(blob)); },
... (truncated)
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.