diff --git a/patch/Release-823.patch b/patch/Release-823.patch new file mode 100644 index 0000000000000000000000000000000000000000..3ca3787c1bb85c5683fb58067c33017bc0f29935 --- /dev/null +++ b/patch/Release-823.patch @@ -0,0 +1,633 @@ +diff --git a/src/content/test/data/gpu/webgl-overly-large-uniform.html b/src/content/test/data/gpu/webgl-overly-large-uniform.html +new file mode 100644 +index 0000000000000..9b28fa5ebc2d6 +--- /dev/null ++++ b/src/content/test/data/gpu/webgl-overly-large-uniform.html +@@ -0,0 +1,137 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/content/test/gpu/gpu_tests/context_lost_integration_test.py b/src/content/test/gpu/gpu_tests/context_lost_integration_test.py +index 9096205323b23..315338ca8795a 100755 +--- a/src/content/test/gpu/gpu_tests/context_lost_integration_test.py ++++ b/src/content/test/gpu/gpu_tests/context_lost_integration_test.py +@@ -160,6 +160,8 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest): + 'webgl_with_select_element.html'), + ('ContextLost_WebGLContextLostInHiddenTab', + 'webgl.html?query=kill_after_notification'), ++ ('ContextLost_WebGLContextLostOverlyLargeUniform', ++ 'webgl-overly-large-uniform.html'), + ('ContextLost_WebGLBlockedAfterJSNavigation', + 'webgl-domain-blocking-page1.html'), + ('ContextLost_WebGLUnblockedAfterUserInitiatedReload', +@@ -387,6 +389,16 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest): + tab.Activate() + self._WaitForTabAndCheckCompletion() + ++ def _ContextLost_WebGLContextLostOverlyLargeUniform(self, ++ test_path: str) -> None: ++ self.RestartBrowserIfNecessaryWithArgs([ ++ cba.DISABLE_DOMAIN_BLOCKING_FOR_3D_APIS, ++ '--enable-features=DisableArrayBufferSizeLimitsForTesting' ++ ]) ++ self._NavigateAndWaitForLoad(test_path) ++ # No reason to wait more than 10 seconds for this test to complete. ++ self._WaitForTabAndCheckCompletion(timeout=10) ++ + def _ContextLost_WebGLBlockedAfterJSNavigation(self, test_path): + self.RestartBrowserIfNecessaryWithArgs([]) + self._NavigateAndWaitForLoad(test_path) +diff --git a/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc b/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc +index 4b86fca0a696d..026ee81f42bdc 100644 +--- a/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc ++++ b/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc +@@ -45,6 +45,9 @@ class FakeCommandBuffer : public CommandBuffer { + EXPECT_TRUE(found != active_ids_.end()); + active_ids_.erase(found); + } ++ void ForceLostContext(error::ContextLostReason reason) override { ++ // No-op; doesn't need to be exercised here. ++ } + + private: + int32_t next_id_ = 1; +diff --git a/src/gpu/command_buffer/client/client_test_helper.cc b/src/gpu/command_buffer/client/client_test_helper.cc +index 4fd55a3274a87..826f466f40cfa 100644 +--- a/src/gpu/command_buffer/client/client_test_helper.cc ++++ b/src/gpu/command_buffer/client/client_test_helper.cc +@@ -158,6 +158,13 @@ void MockClientCommandBuffer::DelegateToFake() { + this, &FakeCommandBufferServiceBase::DestroyTransferBufferHelper)); + } + ++void MockClientCommandBuffer::ForceLostContext( ++ error::ContextLostReason reason) { ++ // TODO(kbr): add a test for a call to this method. ++ SetParseError(error::kLostContext); ++ SetContextLostReason(reason); ++} ++ + MockClientCommandBufferMockFlush::MockClientCommandBufferMockFlush() { + DelegateToFake(); + } +diff --git a/src/gpu/command_buffer/client/client_test_helper.h b/src/gpu/command_buffer/client/client_test_helper.h +index bd0cc0739efaa..2548be832472a 100644 +--- a/src/gpu/command_buffer/client/client_test_helper.h ++++ b/src/gpu/command_buffer/client/client_test_helper.h +@@ -86,6 +86,8 @@ class MockClientCommandBuffer : public CommandBuffer, + + void SetTokenForSetGetBuffer(int32_t token) { token_ = token; } + ++ void ForceLostContext(error::ContextLostReason reason) override; ++ + private: + int32_t put_offset_ = 0; + int32_t token_ = 10000; // All token checks in the tests should pass. +diff --git a/src/gpu/command_buffer/client/cmd_buffer_helper.cc b/src/gpu/command_buffer/client/cmd_buffer_helper.cc +index 620fa6535a890..5d9d1c23dddf7 100644 +--- a/src/gpu/command_buffer/client/cmd_buffer_helper.cc ++++ b/src/gpu/command_buffer/client/cmd_buffer_helper.cc +@@ -157,7 +157,8 @@ void CommandBufferHelper::UpdateCachedState(const CommandBuffer::State& state) { + (state.set_get_buffer_count != set_get_buffer_count_); + cached_get_offset_ = service_on_old_buffer_ ? 0 : state.get_offset; + cached_last_token_read_ = state.token; +- context_lost_ = error::IsError(state.error); ++ // Don't transition from a lost context to a working context. ++ context_lost_ |= error::IsError(state.error); + } + + bool CommandBufferHelper::WaitForGetOffsetInRange(int32_t start, int32_t end) { +@@ -296,7 +297,6 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) { + if (!AllocateRingBuffer()) + return; + DCHECK(HaveRingBuffer()); +- DCHECK(count < total_entry_count_); + if (put_ + count > total_entry_count_) { + // There's not enough room between the current put and the end of the + // buffer, so we need to wrap. We will add noops all the way to the end, +@@ -344,7 +344,16 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) { + put_)) + return; + CalcImmediateEntries(count); +- DCHECK_GE(immediate_entry_count_, count); ++ if (immediate_entry_count_ < count) { ++ // Tell the underlying command buffer to signal a lost context to higher ++ // levels. ++ command_buffer_->ForceLostContext(error::kGuilty); ++ // Free the ring buffer and lose context. ++ FreeRingBuffer(); ++ usable_ = false; ++ context_lost_ = true; ++ return; ++ } + } + } + } +diff --git a/src/gpu/command_buffer/common/command_buffer.h b/src/gpu/command_buffer/common/command_buffer.h +index 6335c4757f2e2..5ac9069424fe3 100644 +--- a/src/gpu/command_buffer/common/command_buffer.h ++++ b/src/gpu/command_buffer/common/command_buffer.h +@@ -125,6 +125,10 @@ class GPU_EXPORT CommandBuffer { + // before it is safe to call this function to destroy it. + virtual void DestroyTransferBuffer(int32_t id) = 0; + ++ // Forcibly lose this context. Used by higher-level code when it determines ++ // the necessity to do so. Has no effect if the context has already been lost. ++ virtual void ForceLostContext(error::ContextLostReason reason) = 0; ++ + private: + DISALLOW_COPY_AND_ASSIGN(CommandBuffer); + }; +diff --git a/src/gpu/command_buffer/service/command_buffer_direct.cc b/src/gpu/command_buffer/service/command_buffer_direct.cc +index e32139b6bfd65..6a7f7e55487ef 100644 +--- a/src/gpu/command_buffer/service/command_buffer_direct.cc ++++ b/src/gpu/command_buffer/service/command_buffer_direct.cc +@@ -63,6 +63,11 @@ void CommandBufferDirect::DestroyTransferBuffer(int32_t id) { + service_.DestroyTransferBuffer(id); + } + ++void CommandBufferDirect::ForceLostContext(error::ContextLostReason reason) { ++ service_.SetContextLostReason(reason); ++ service_.SetParseError(error::kLostContext); ++} ++ + CommandBufferServiceClient::CommandBatchProcessedResult + CommandBufferDirect::OnCommandBatchProcessed() { + return kContinueExecution; +diff --git a/src/gpu/command_buffer/service/command_buffer_direct.h b/src/gpu/command_buffer/service/command_buffer_direct.h +index d03ac687b6f4b..4d8175c3f56fa 100644 +--- a/src/gpu/command_buffer/service/command_buffer_direct.h ++++ b/src/gpu/command_buffer/service/command_buffer_direct.h +@@ -40,6 +40,7 @@ class GPU_EXPORT CommandBufferDirect : public CommandBuffer, + TransferBufferAllocationOption option = + TransferBufferAllocationOption::kLoseContextOnOOM) override; + void DestroyTransferBuffer(int32_t id) override; ++ void ForceLostContext(error::ContextLostReason reason) override; + + // CommandBufferServiceClient implementation: + CommandBatchProcessedResult OnCommandBatchProcessed() override; +diff --git a/src/gpu/ipc/client/command_buffer_proxy_impl.cc b/src/gpu/ipc/client/command_buffer_proxy_impl.cc +index bfafcdc9524d8..77455d492fbfc 100644 +--- a/src/gpu/ipc/client/command_buffer_proxy_impl.cc ++++ b/src/gpu/ipc/client/command_buffer_proxy_impl.cc +@@ -407,6 +407,22 @@ void CommandBufferProxyImpl::DestroyTransferBuffer(int32_t id) { + GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id)); + } + ++void CommandBufferProxyImpl::ForceLostContext(error::ContextLostReason reason) { ++ CheckLock(); ++ base::AutoLock lock(last_state_lock_); ++ if (last_state_.error == gpu::error::kLostContext) { ++ // Per specification, do nothing if the context is already lost. ++ return; ++ } ++ last_state_.error = gpu::error::kLostContext; ++ // The caller determines the context lost reason. ++ last_state_.context_lost_reason = reason; ++ // Calling code may be in an indeterminate state (possibly including ++ // being in a GpuControlClient callback), so avoid re-entering the ++ // GpuControlClient here. ++ DisconnectChannelInFreshCallStack(); ++} ++ + void CommandBufferProxyImpl::SetGpuControlClient(GpuControlClient* client) { + CheckLock(); + gpu_control_client_ = client; +diff --git a/src/gpu/ipc/client/command_buffer_proxy_impl.h b/src/gpu/ipc/client/command_buffer_proxy_impl.h +index 3a541f708a32e..540ca3486d869 100644 +--- a/src/gpu/ipc/client/command_buffer_proxy_impl.h ++++ b/src/gpu/ipc/client/command_buffer_proxy_impl.h +@@ -111,6 +111,7 @@ class GPU_EXPORT CommandBufferProxyImpl : public gpu::CommandBuffer, + TransferBufferAllocationOption option = + TransferBufferAllocationOption::kLoseContextOnOOM) override; + void DestroyTransferBuffer(int32_t id) override; ++ void ForceLostContext(error::ContextLostReason reason) override; + + // gpu::GpuControl implementation: + void SetGpuControlClient(GpuControlClient* client) override; +diff --git a/src/gpu/ipc/in_process_command_buffer.cc b/src/gpu/ipc/in_process_command_buffer.cc +index 18dc45de9fa89..e3e9c59e54588 100644 +--- a/src/gpu/ipc/in_process_command_buffer.cc ++++ b/src/gpu/ipc/in_process_command_buffer.cc +@@ -1040,6 +1040,21 @@ void InProcessCommandBuffer::DestroyTransferBuffer(int32_t id) { + gpu_thread_weak_ptr_factory_.GetWeakPtr(), id)); + } + ++void InProcessCommandBuffer::ForceLostContext(error::ContextLostReason reason) { ++ ScheduleGpuTask( ++ base::BindOnce(&InProcessCommandBuffer::ForceLostContextOnGpuThread, ++ gpu_thread_weak_ptr_factory_.GetWeakPtr(), reason)); ++} ++ ++void InProcessCommandBuffer::ForceLostContextOnGpuThread( ++ error::ContextLostReason reason) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); ++ ++ // Similar implementation to CommandBufferDirect. ++ command_buffer_->SetContextLostReason(reason); ++ command_buffer_->SetParseError(error::kLostContext); ++} ++ + void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32_t id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + command_buffer_->DestroyTransferBuffer(id); +diff --git a/src/gpu/ipc/in_process_command_buffer.h b/src/gpu/ipc/in_process_command_buffer.h +index 82d4dc1c7263d..5c32e278a30ca 100644 +--- a/src/gpu/ipc/in_process_command_buffer.h ++++ b/src/gpu/ipc/in_process_command_buffer.h +@@ -142,6 +142,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer + TransferBufferAllocationOption option = + TransferBufferAllocationOption::kLoseContextOnOOM) override; + void DestroyTransferBuffer(int32_t id) override; ++ void ForceLostContext(error::ContextLostReason reason) override; + + // GpuControl implementation (called on client thread): + void SetGpuControlClient(GpuControlClient*) override; +@@ -313,6 +314,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer + void RegisterTransferBufferOnGpuThread(int32_t id, + scoped_refptr buffer); + void DestroyTransferBufferOnGpuThread(int32_t id); ++ void ForceLostContextOnGpuThread(error::ContextLostReason reason); + + void CreateImageOnGpuThread(int32_t id, + gfx::GpuMemoryBufferHandle handle, +diff --git a/src/ppapi/proxy/ppapi_command_buffer_proxy.cc b/src/ppapi/proxy/ppapi_command_buffer_proxy.cc +index a76aaab2f9ab9..ff4d71888f74c 100644 +--- a/src/ppapi/proxy/ppapi_command_buffer_proxy.cc ++++ b/src/ppapi/proxy/ppapi_command_buffer_proxy.cc +@@ -171,6 +171,12 @@ void PpapiCommandBufferProxy::DestroyTransferBuffer(int32_t id) { + ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id)); + } + ++void PpapiCommandBufferProxy::ForceLostContext(gpu::error::ContextLostReason) { ++ // This entry point was added to CommandBuffer well after PPAPI's ++ // deprecation. No current clients determined its necessity, so it ++ // will not be implemented. ++} ++ + void PpapiCommandBufferProxy::SetLock(base::Lock*) { + NOTREACHED(); + } +diff --git a/src/ppapi/proxy/ppapi_command_buffer_proxy.h b/src/ppapi/proxy/ppapi_command_buffer_proxy.h +index ce2697a5a869e..9c40ab8eaaf45 100644 +--- a/src/ppapi/proxy/ppapi_command_buffer_proxy.h ++++ b/src/ppapi/proxy/ppapi_command_buffer_proxy.h +@@ -55,6 +55,7 @@ class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy : public gpu::CommandBuffer, + gpu::TransferBufferAllocationOption option = + gpu::TransferBufferAllocationOption::kLoseContextOnOOM) override; + void DestroyTransferBuffer(int32_t id) override; ++ void ForceLostContext(gpu::error::ContextLostReason reason) override; + + // gpu::GpuControl implementation: + void SetGpuControlClient(gpu::GpuControlClient*) override; +diff --git a/src/third_party/blink/common/features.cc b/src/third_party/blink/common/features.cc +index 4b469825b4cda..766786ebc2dd9 100644 +--- a/src/third_party/blink/common/features.cc ++++ b/src/third_party/blink/common/features.cc +@@ -887,5 +887,9 @@ const base::FeatureParam + const base::Feature kCLSM90Improvements{"CLSM90Improvements", + base::FEATURE_ENABLED_BY_DEFAULT}; + ++const base::Feature kDisableArrayBufferSizeLimitsForTesting{ ++ "DisableArrayBufferSizeLimitsForTesting", ++ base::FEATURE_DISABLED_BY_DEFAULT}; ++ + } // namespace features + } // namespace blink +diff --git a/src/third_party/blink/public/common/features.h b/src/third_party/blink/public/common/features.h +index e371d93b8ffbd..89c12448b0ec8 100644 +--- a/src/third_party/blink/public/common/features.h ++++ b/src/third_party/blink/public/common/features.h +@@ -364,6 +364,12 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam + + BLINK_COMMON_EXPORT extern const base::Feature kCLSM90Improvements; + ++// TODO(https://crbug.com/1201109): temporary flag to disable new ArrayBuffer ++// size limits, so that tests can be written against code receiving these ++// buffers. Remove when the bindings code instituting these limits is removed. ++BLINK_COMMON_EXPORT extern const base::Feature ++ kDisableArrayBufferSizeLimitsForTesting; ++ + } // namespace features + } // namespace blink + +diff --git a/src/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/src/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +index 86415db444bd7..00666c5ff35d8 100644 +--- a/src/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc ++++ b/src/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +@@ -8310,6 +8310,22 @@ bool WebGLRenderingContextBase::ValidateUniformMatrixParameters( + SynthesizeGLError(GL_INVALID_VALUE, function_name, "invalid size"); + return false; + } ++ // By design the command buffer has an internal (signed) 32-bit ++ // limit, so ensure that the amount of data passed down to it ++ // doesn't exceed what it can handle. Only integer or float typed ++ // arrays can be passed into the uniform*v or uniformMatrix*v ++ // functions; each has 4-byte elements. ++ base::CheckedNumeric total_size(actual_size); ++ total_size *= 4; ++ // Add on a fixed constant to account for internal metadata in the ++ // command buffer. ++ constexpr int32_t kExtraCommandSize = 1024; ++ total_size += kExtraCommandSize; ++ if (!total_size.IsValid()) { ++ SynthesizeGLError(GL_INVALID_VALUE, function_name, ++ "size * elementSize, plus a constant, is too large"); ++ return false; ++ } + return true; + } + +diff --git a/src/third_party/libwebp/README.chromium b/src/third_party/libwebp/README.chromium +index fd77980a907cc..4968eaea94686 100644 +--- a/src/third_party/libwebp/README.chromium ++++ b/src/third_party/libwebp/README.chromium +@@ -1,7 +1,7 @@ + Name: WebP image encoder/decoder + Short Name: libwebp + URL: http://developers.google.com/speed/webp +-Version: v1.2.0 ++Version: 20ef03ee351d4ff03fc5ff3ec4804a879d1b9d5c + CPEPrefix: cpe:/a:webmproject:libwebp:1.2.0 + License: BSD + License File: LICENSE +@@ -9,7 +9,7 @@ Security Critical: Yes + + Description: + Source archive: +- https://chromium.googlesource.com/webm/libwebp/+archive/v1.2.0.tar.gz ++ https://chromium.googlesource.com/webm/libwebp/+archive/20ef03ee351d4ff03fc5ff3ec4804a879d1b9d5c.tar.gz + + WebP is an image format that does both lossy and lossless compression of + digital photographic images. WebP consists of a codec based on VP8, that Google +diff --git a/src/third_party/libwebp/src/dsp/alpha_processing_neon.c b/src/third_party/libwebp/src/dsp/alpha_processing_neon.c +index 9d55421704cc8..27d717507c5fe 100644 +--- a/src/third_party/libwebp/src/dsp/alpha_processing_neon.c ++++ b/src/third_party/libwebp/src/dsp/alpha_processing_neon.c +@@ -83,7 +83,7 @@ static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first, + static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint8_t* dst, int dst_stride) { +- uint32_t alpha_mask = 0xffffffffu; ++ uint32_t alpha_mask = 0xffu; + uint8x8_t mask8 = vdup_n_u8(0xff); + uint32_t tmp[2]; + int i, j; +@@ -107,6 +107,7 @@ static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride, + dst += dst_stride; + } + vst1_u8((uint8_t*)tmp, mask8); ++ alpha_mask *= 0x01010101; + alpha_mask &= tmp[0]; + alpha_mask &= tmp[1]; + return (alpha_mask != 0xffffffffu); +@@ -134,7 +135,7 @@ static void DispatchAlphaToGreen_NEON(const uint8_t* alpha, int alpha_stride, + static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride, + int width, int height, + uint8_t* alpha, int alpha_stride) { +- uint32_t alpha_mask = 0xffffffffu; ++ uint32_t alpha_mask = 0xffu; + uint8x8_t mask8 = vdup_n_u8(0xff); + uint32_t tmp[2]; + int i, j; +@@ -156,6 +157,7 @@ static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride, + alpha += alpha_stride; + } + vst1_u8((uint8_t*)tmp, mask8); ++ alpha_mask *= 0x01010101; + alpha_mask &= tmp[0]; + alpha_mask &= tmp[1]; + return (alpha_mask == 0xffffffffu); +diff --git a/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c b/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c +index 0412a093cf9ab..9963051798eee 100644 +--- a/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c ++++ b/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c +@@ -347,24 +347,24 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[], + static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb, + uint32_t* pout, int size) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; +- const uint32_t end = ((size) / 4) * 4; ++ const int end = ((size) / 4) * 4; + const uint32_t* const LoopEnd = pa + end; + int i; + ASM_START + ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) + ASM_END_0 +- for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i]; ++ for (i = 0; i < size - end; ++i) pout[i] = pa[i] + pb[i]; + } + + static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) { + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; +- const uint32_t end = ((size) / 4) * 4; ++ const int end = ((size) / 4) * 4; + const uint32_t* const LoopEnd = pa + end; + int i; + ASM_START + ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) + ASM_END_1 +- for (i = end; i < size; ++i) pout[i] += pa[i]; ++ for (i = 0; i < size - end; ++i) pout[i] += pa[i]; + } + + #undef ASM_END_1 +diff --git a/src/third_party/libwebp/src/enc/backward_references_cost_enc.c b/src/third_party/libwebp/src/enc/backward_references_cost_enc.c +index 516abd73eb45c..5eb24d449953d 100644 +--- a/src/third_party/libwebp/src/enc/backward_references_cost_enc.c ++++ b/src/third_party/libwebp/src/enc/backward_references_cost_enc.c +@@ -577,7 +577,7 @@ static int BackwardReferencesHashChainDistanceOnly( + (CostModel*)WebPSafeCalloc(1ULL, cost_model_size); + VP8LColorCache hashers; + CostManager* cost_manager = +- (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager)); ++ (CostManager*)WebPSafeCalloc(1ULL, sizeof(*cost_manager)); + int offset_prev = -1, len_prev = -1; + double offset_cost = -1; + int first_offset_is_constant = -1; // initialized with 'impossible' value +diff --git a/src/third_party/libwebp/src/enc/backward_references_enc.c b/src/third_party/libwebp/src/enc/backward_references_enc.c +index 519b36a09153e..d5e931efdd8cf 100644 +--- a/src/third_party/libwebp/src/enc/backward_references_enc.c ++++ b/src/third_party/libwebp/src/enc/backward_references_enc.c +@@ -976,15 +976,16 @@ static int GetBackwardReferences(int width, int height, + const VP8LHashChain* const hash_chain_tmp = + (lz77_types_best[i] == kLZ77Standard) ? hash_chain : &hash_chain_box; + const int cache_bits = (i == 1) ? 0 : *cache_bits_best; +- if (VP8LBackwardReferencesTraceBackwards(width, height, argb, cache_bits, +- hash_chain_tmp, &refs[i], +- refs_tmp)) { +- double bit_cost_trace; +- VP8LHistogramCreate(histo, refs_tmp, cache_bits); +- bit_cost_trace = VP8LHistogramEstimateBits(histo); +- if (bit_cost_trace < bit_costs_best[i]) { +- BackwardRefsSwap(refs_tmp, &refs[i]); +- } ++ double bit_cost_trace; ++ if (!VP8LBackwardReferencesTraceBackwards(width, height, argb, cache_bits, ++ hash_chain_tmp, &refs[i], ++ refs_tmp)) { ++ goto Error; ++ } ++ VP8LHistogramCreate(histo, refs_tmp, cache_bits); ++ bit_cost_trace = VP8LHistogramEstimateBits(histo); ++ if (bit_cost_trace < bit_costs_best[i]) { ++ BackwardRefsSwap(refs_tmp, &refs[i]); + } + } + +diff --git a/src/third_party/libwebp/src/enc/vp8l_enc.c b/src/third_party/libwebp/src/enc/vp8l_enc.c +index 0b44ebe46ec54..1875e53552d31 100644 +--- a/src/third_party/libwebp/src/enc/vp8l_enc.c ++++ b/src/third_party/libwebp/src/enc/vp8l_enc.c +@@ -1706,11 +1706,16 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, + const WebPWorkerInterface* const worker_interface = WebPGetWorkerInterface(); + int ok_main; + ++ if (enc_main == NULL || !VP8LBitWriterInit(&bw_side, 0)) { ++ WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); ++ VP8LEncoderDelete(enc_main); ++ return 0; ++ } ++ + // Analyze image (entropy, num_palettes etc) +- if (enc_main == NULL || +- !EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main, ++ if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main, + &red_and_blue_always_zero) || +- !EncoderInit(enc_main) || !VP8LBitWriterInit(&bw_side, 0)) { ++ !EncoderInit(enc_main)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + }