• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/src/content/test/data/gpu/webgl-overly-large-uniform.html b/src/content/test/data/gpu/webgl-overly-large-uniform.html
2new file mode 100644
3index 0000000000000..9b28fa5ebc2d6
4--- /dev/null
5+++ b/src/content/test/data/gpu/webgl-overly-large-uniform.html
6@@ -0,0 +1,137 @@
7+<html>
8+<head>
9+<script type="x-shader/x-vertex" id="vertex">
10+#version 100
11+uniform mat4 overflow;
12+
13+void main() {
14+  gl_Position = overflow * vec4(0.11, 0.22, 0.33, 1.0);
15+}
16+</script>
17+<script type="x-shader/x-fragment" id="fragment">
18+#version 100
19+void main() {
20+  gl_FragColor = vec4(0.11, 0.22, 0.33, 1.0);
21+}
22+</script>
23+<script type="text/javascript">
24+let canvas;
25+let w, h;
26+let gl;
27+let timeout;
28+
29+function send(result, message) {
30+  if (window.domAutomationController)
31+    window.domAutomationController.send(result);
32+  if (message)
33+    console.log(message);
34+}
35+
36+function onContextLost(e) {
37+  e.preventDefault();
38+  clearTimeout(timeout);
39+  // This is the last test in this file.
40+  send("SUCCESS");
41+}
42+
43+function onContextRestored() {
44+  // Could extend this test to cover context restoration, but ignore
45+  // this for now.
46+}
47+
48+function timedOut() {
49+  send("FAILURE", "Timed out waiting for context lost event");
50+}
51+
52+function onLoad() {
53+  send("LOADED");
54+
55+  canvas = document.getElementById("canvas1");
56+  w = canvas.width;
57+  h = canvas.height;
58+  if (!canvas)
59+    return;
60+  canvas.addEventListener("webglcontextlost", onContextLost, false);
61+  canvas.addEventListener("webglcontextrestored", onContextRestored, false);
62+
63+  gl = canvas.getContext("webgl");
64+  if (!gl) {
65+    send("FAILURE", "Couldn't get WebGL context");
66+    return;
67+  }
68+
69+  let vertexShader = gl.createShader(gl.VERTEX_SHADER);
70+  gl.shaderSource(vertexShader, document.querySelector("#vertex").innerHTML);
71+  gl.compileShader(vertexShader);
72+
73+  let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
74+  gl.shaderSource(fragmentShader, document.querySelector("#fragment").innerHTML);
75+  gl.compileShader(fragmentShader);
76+
77+  program = gl.createProgram();
78+  gl.attachShader(program, vertexShader);
79+  gl.attachShader(program, fragmentShader);
80+  gl.linkProgram(program);
81+
82+  overflow = gl.getUniformLocation(program, "overflow");
83+
84+  gl.useProgram(program);
85+
86+  // 2 GB memory pool, if possible. (64KB Wasm page size)
87+  //
88+  // If allocation fails (for example, on 32-bit Android), fall back
89+  // to 128 MB, and skip the portion of the test which tests the
90+  // generation of INVALID_VALUE.
91+  let gotLargeAllocation = false;
92+  let memory;
93+
94+  try {
95+    memory = new WebAssembly.Memory({initial: 32768});
96+    gotLargeAllocation = true;
97+  } catch (e) {
98+    // Must be on a system that can't allocate that much memory. Try
99+    // again with a smaller reservation.
100+    try {
101+      memory = new WebAssembly.Memory({initial: 2048});
102+    } catch (e) {
103+      // Unexpected. Fail verbosely.
104+      send("FAILURE", "Failed to allocate even the smaller Wasm memory");
105+      return;
106+    }
107+  }
108+
109+  if (gotLargeAllocation) {
110+    // Feeding in all but a few bytes of that memory pool should cause
111+    // GL_INVALID_VALUE to be generated as an implementation detail; this can not
112+    // be guaranteed by the WebGL conformance tests. Note: this behavior could be
113+    // changed to instead force a lost context if desired, per below.
114+    const fewBytes = 8;
115+    let array = new Int32Array(memory.buffer, fewBytes);
116+    gl.uniform1iv(overflow, array);
117+    let err = gl.getError();
118+    console.log("GL error after very large uniform1iv call: " + err);
119+    if (err != gl.INVALID_VALUE) {
120+      send("FAILURE", "Expected gl.INVALID_VALUE, got " + err);
121+      return;
122+    }
123+  }
124+
125+  // Feeding in significantly less of that memory pool (in this case, 64K less)
126+  // should cause a lost context as an implementation detail; this can not be
127+  // guaranteed by the WebGL conformance tests.
128+  const moreBytes = 64 * 1024;
129+  array = new Int32Array(memory.buffer, moreBytes);
130+  gl.uniform1iv(overflow, array);
131+  err = gl.getError();
132+  console.log("GL error after slightly less large uniform1iv call: " + err);
133+  // Delivery of context loss will race with execution here.
134+  // If it hasn't been delivered within 5 seconds, fail the test.
135+  timeout = setTimeout(timedOut, 5000);
136+}
137+</script>
138+</head>
139+<body onload="onLoad()">
140+<canvas id="canvas1" width="64px" height="64px">
141+</canvas>
142+</body>
143+</html>
144diff --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
145index 9096205323b23..315338ca8795a 100755
146--- a/src/content/test/gpu/gpu_tests/context_lost_integration_test.py
147+++ b/src/content/test/gpu/gpu_tests/context_lost_integration_test.py
148@@ -160,6 +160,8 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest):
149               'webgl_with_select_element.html'),
150              ('ContextLost_WebGLContextLostInHiddenTab',
151               'webgl.html?query=kill_after_notification'),
152+             ('ContextLost_WebGLContextLostOverlyLargeUniform',
153+              'webgl-overly-large-uniform.html'),
154              ('ContextLost_WebGLBlockedAfterJSNavigation',
155               'webgl-domain-blocking-page1.html'),
156              ('ContextLost_WebGLUnblockedAfterUserInitiatedReload',
157@@ -387,6 +389,16 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest):
158     tab.Activate()
159     self._WaitForTabAndCheckCompletion()
160
161+  def _ContextLost_WebGLContextLostOverlyLargeUniform(self,
162+                                                      test_path: str) -> None:
163+    self.RestartBrowserIfNecessaryWithArgs([
164+        cba.DISABLE_DOMAIN_BLOCKING_FOR_3D_APIS,
165+        '--enable-features=DisableArrayBufferSizeLimitsForTesting'
166+    ])
167+    self._NavigateAndWaitForLoad(test_path)
168+    # No reason to wait more than 10 seconds for this test to complete.
169+    self._WaitForTabAndCheckCompletion(timeout=10)
170+
171   def _ContextLost_WebGLBlockedAfterJSNavigation(self, test_path):
172     self.RestartBrowserIfNecessaryWithArgs([])
173     self._NavigateAndWaitForLoad(test_path)
174diff --git a/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc b/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc
175index 4b86fca0a696d..026ee81f42bdc 100644
176--- a/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc
177+++ b/src/gpu/command_buffer/client/client_discardable_manager_unittest.cc
178@@ -45,6 +45,9 @@ class FakeCommandBuffer : public CommandBuffer {
179     EXPECT_TRUE(found != active_ids_.end());
180     active_ids_.erase(found);
181   }
182+  void ForceLostContext(error::ContextLostReason reason) override {
183+    // No-op; doesn't need to be exercised here.
184+  }
185
186  private:
187   int32_t next_id_ = 1;
188diff --git a/src/gpu/command_buffer/client/client_test_helper.cc b/src/gpu/command_buffer/client/client_test_helper.cc
189index 4fd55a3274a87..826f466f40cfa 100644
190--- a/src/gpu/command_buffer/client/client_test_helper.cc
191+++ b/src/gpu/command_buffer/client/client_test_helper.cc
192@@ -158,6 +158,13 @@ void MockClientCommandBuffer::DelegateToFake() {
193           this, &FakeCommandBufferServiceBase::DestroyTransferBufferHelper));
194 }
195
196+void MockClientCommandBuffer::ForceLostContext(
197+    error::ContextLostReason reason) {
198+  // TODO(kbr): add a test for a call to this method.
199+  SetParseError(error::kLostContext);
200+  SetContextLostReason(reason);
201+}
202+
203 MockClientCommandBufferMockFlush::MockClientCommandBufferMockFlush() {
204   DelegateToFake();
205 }
206diff --git a/src/gpu/command_buffer/client/client_test_helper.h b/src/gpu/command_buffer/client/client_test_helper.h
207index bd0cc0739efaa..2548be832472a 100644
208--- a/src/gpu/command_buffer/client/client_test_helper.h
209+++ b/src/gpu/command_buffer/client/client_test_helper.h
210@@ -86,6 +86,8 @@ class MockClientCommandBuffer : public CommandBuffer,
211
212   void SetTokenForSetGetBuffer(int32_t token) { token_ = token; }
213
214+  void ForceLostContext(error::ContextLostReason reason) override;
215+
216  private:
217   int32_t put_offset_ = 0;
218   int32_t token_ = 10000;  // All token checks in the tests should pass.
219diff --git a/src/gpu/command_buffer/client/cmd_buffer_helper.cc b/src/gpu/command_buffer/client/cmd_buffer_helper.cc
220index 620fa6535a890..5d9d1c23dddf7 100644
221--- a/src/gpu/command_buffer/client/cmd_buffer_helper.cc
222+++ b/src/gpu/command_buffer/client/cmd_buffer_helper.cc
223@@ -157,7 +157,8 @@ void CommandBufferHelper::UpdateCachedState(const CommandBuffer::State& state) {
224       (state.set_get_buffer_count != set_get_buffer_count_);
225   cached_get_offset_ = service_on_old_buffer_ ? 0 : state.get_offset;
226   cached_last_token_read_ = state.token;
227-  context_lost_ = error::IsError(state.error);
228+  // Don't transition from a lost context to a working context.
229+  context_lost_ |= error::IsError(state.error);
230 }
231
232 bool CommandBufferHelper::WaitForGetOffsetInRange(int32_t start, int32_t end) {
233@@ -296,7 +297,6 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) {
234   if (!AllocateRingBuffer())
235     return;
236   DCHECK(HaveRingBuffer());
237-  DCHECK(count < total_entry_count_);
238   if (put_ + count > total_entry_count_) {
239     // There's not enough room between the current put and the end of the
240     // buffer, so we need to wrap. We will add noops all the way to the end,
241@@ -344,7 +344,16 @@ void CommandBufferHelper::WaitForAvailableEntries(int32_t count) {
242                                    put_))
243         return;
244       CalcImmediateEntries(count);
245-      DCHECK_GE(immediate_entry_count_, count);
246+      if (immediate_entry_count_ < count) {
247+        // Tell the underlying command buffer to signal a lost context to higher
248+        // levels.
249+        command_buffer_->ForceLostContext(error::kGuilty);
250+        // Free the ring buffer and lose context.
251+        FreeRingBuffer();
252+        usable_ = false;
253+        context_lost_ = true;
254+        return;
255+      }
256     }
257   }
258 }
259diff --git a/src/gpu/command_buffer/common/command_buffer.h b/src/gpu/command_buffer/common/command_buffer.h
260index 6335c4757f2e2..5ac9069424fe3 100644
261--- a/src/gpu/command_buffer/common/command_buffer.h
262+++ b/src/gpu/command_buffer/common/command_buffer.h
263@@ -125,6 +125,10 @@ class GPU_EXPORT CommandBuffer {
264   // before it is safe to call this function to destroy it.
265   virtual void DestroyTransferBuffer(int32_t id) = 0;
266
267+  // Forcibly lose this context. Used by higher-level code when it determines
268+  // the necessity to do so. Has no effect if the context has already been lost.
269+  virtual void ForceLostContext(error::ContextLostReason reason) = 0;
270+
271  private:
272   DISALLOW_COPY_AND_ASSIGN(CommandBuffer);
273 };
274diff --git a/src/gpu/command_buffer/service/command_buffer_direct.cc b/src/gpu/command_buffer/service/command_buffer_direct.cc
275index e32139b6bfd65..6a7f7e55487ef 100644
276--- a/src/gpu/command_buffer/service/command_buffer_direct.cc
277+++ b/src/gpu/command_buffer/service/command_buffer_direct.cc
278@@ -63,6 +63,11 @@ void CommandBufferDirect::DestroyTransferBuffer(int32_t id) {
279   service_.DestroyTransferBuffer(id);
280 }
281
282+void CommandBufferDirect::ForceLostContext(error::ContextLostReason reason) {
283+  service_.SetContextLostReason(reason);
284+  service_.SetParseError(error::kLostContext);
285+}
286+
287 CommandBufferServiceClient::CommandBatchProcessedResult
288 CommandBufferDirect::OnCommandBatchProcessed() {
289   return kContinueExecution;
290diff --git a/src/gpu/command_buffer/service/command_buffer_direct.h b/src/gpu/command_buffer/service/command_buffer_direct.h
291index d03ac687b6f4b..4d8175c3f56fa 100644
292--- a/src/gpu/command_buffer/service/command_buffer_direct.h
293+++ b/src/gpu/command_buffer/service/command_buffer_direct.h
294@@ -40,6 +40,7 @@ class GPU_EXPORT CommandBufferDirect : public CommandBuffer,
295       TransferBufferAllocationOption option =
296           TransferBufferAllocationOption::kLoseContextOnOOM) override;
297   void DestroyTransferBuffer(int32_t id) override;
298+  void ForceLostContext(error::ContextLostReason reason) override;
299
300   // CommandBufferServiceClient implementation:
301   CommandBatchProcessedResult OnCommandBatchProcessed() override;
302diff --git a/src/gpu/ipc/client/command_buffer_proxy_impl.cc b/src/gpu/ipc/client/command_buffer_proxy_impl.cc
303index bfafcdc9524d8..77455d492fbfc 100644
304--- a/src/gpu/ipc/client/command_buffer_proxy_impl.cc
305+++ b/src/gpu/ipc/client/command_buffer_proxy_impl.cc
306@@ -407,6 +407,22 @@ void CommandBufferProxyImpl::DestroyTransferBuffer(int32_t id) {
307       GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id));
308 }
309
310+void CommandBufferProxyImpl::ForceLostContext(error::ContextLostReason reason) {
311+  CheckLock();
312+  base::AutoLock lock(last_state_lock_);
313+  if (last_state_.error == gpu::error::kLostContext) {
314+    // Per specification, do nothing if the context is already lost.
315+    return;
316+  }
317+  last_state_.error = gpu::error::kLostContext;
318+  // The caller determines the context lost reason.
319+  last_state_.context_lost_reason = reason;
320+  // Calling code may be in an indeterminate state (possibly including
321+  // being in a GpuControlClient callback), so avoid re-entering the
322+  // GpuControlClient here.
323+  DisconnectChannelInFreshCallStack();
324+}
325+
326 void CommandBufferProxyImpl::SetGpuControlClient(GpuControlClient* client) {
327   CheckLock();
328   gpu_control_client_ = client;
329diff --git a/src/gpu/ipc/client/command_buffer_proxy_impl.h b/src/gpu/ipc/client/command_buffer_proxy_impl.h
330index 3a541f708a32e..540ca3486d869 100644
331--- a/src/gpu/ipc/client/command_buffer_proxy_impl.h
332+++ b/src/gpu/ipc/client/command_buffer_proxy_impl.h
333@@ -111,6 +111,7 @@ class GPU_EXPORT CommandBufferProxyImpl : public gpu::CommandBuffer,
334       TransferBufferAllocationOption option =
335           TransferBufferAllocationOption::kLoseContextOnOOM) override;
336   void DestroyTransferBuffer(int32_t id) override;
337+  void ForceLostContext(error::ContextLostReason reason) override;
338
339   // gpu::GpuControl implementation:
340   void SetGpuControlClient(GpuControlClient* client) override;
341diff --git a/src/gpu/ipc/in_process_command_buffer.cc b/src/gpu/ipc/in_process_command_buffer.cc
342index 18dc45de9fa89..e3e9c59e54588 100644
343--- a/src/gpu/ipc/in_process_command_buffer.cc
344+++ b/src/gpu/ipc/in_process_command_buffer.cc
345@@ -1040,6 +1040,21 @@ void InProcessCommandBuffer::DestroyTransferBuffer(int32_t id) {
346                      gpu_thread_weak_ptr_factory_.GetWeakPtr(), id));
347 }
348
349+void InProcessCommandBuffer::ForceLostContext(error::ContextLostReason reason) {
350+  ScheduleGpuTask(
351+      base::BindOnce(&InProcessCommandBuffer::ForceLostContextOnGpuThread,
352+                     gpu_thread_weak_ptr_factory_.GetWeakPtr(), reason));
353+}
354+
355+void InProcessCommandBuffer::ForceLostContextOnGpuThread(
356+    error::ContextLostReason reason) {
357+  DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
358+
359+  // Similar implementation to CommandBufferDirect.
360+  command_buffer_->SetContextLostReason(reason);
361+  command_buffer_->SetParseError(error::kLostContext);
362+}
363+
364 void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32_t id) {
365   DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
366   command_buffer_->DestroyTransferBuffer(id);
367diff --git a/src/gpu/ipc/in_process_command_buffer.h b/src/gpu/ipc/in_process_command_buffer.h
368index 82d4dc1c7263d..5c32e278a30ca 100644
369--- a/src/gpu/ipc/in_process_command_buffer.h
370+++ b/src/gpu/ipc/in_process_command_buffer.h
371@@ -142,6 +142,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer
372       TransferBufferAllocationOption option =
373           TransferBufferAllocationOption::kLoseContextOnOOM) override;
374   void DestroyTransferBuffer(int32_t id) override;
375+  void ForceLostContext(error::ContextLostReason reason) override;
376
377   // GpuControl implementation (called on client thread):
378   void SetGpuControlClient(GpuControlClient*) override;
379@@ -313,6 +314,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT InProcessCommandBuffer
380   void RegisterTransferBufferOnGpuThread(int32_t id,
381                                          scoped_refptr<Buffer> buffer);
382   void DestroyTransferBufferOnGpuThread(int32_t id);
383+  void ForceLostContextOnGpuThread(error::ContextLostReason reason);
384
385   void CreateImageOnGpuThread(int32_t id,
386                               gfx::GpuMemoryBufferHandle handle,
387diff --git a/src/ppapi/proxy/ppapi_command_buffer_proxy.cc b/src/ppapi/proxy/ppapi_command_buffer_proxy.cc
388index a76aaab2f9ab9..ff4d71888f74c 100644
389--- a/src/ppapi/proxy/ppapi_command_buffer_proxy.cc
390+++ b/src/ppapi/proxy/ppapi_command_buffer_proxy.cc
391@@ -171,6 +171,12 @@ void PpapiCommandBufferProxy::DestroyTransferBuffer(int32_t id) {
392       ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
393 }
394
395+void PpapiCommandBufferProxy::ForceLostContext(gpu::error::ContextLostReason) {
396+  // This entry point was added to CommandBuffer well after PPAPI's
397+  // deprecation. No current clients determined its necessity, so it
398+  // will not be implemented.
399+}
400+
401 void PpapiCommandBufferProxy::SetLock(base::Lock*) {
402   NOTREACHED();
403 }
404diff --git a/src/ppapi/proxy/ppapi_command_buffer_proxy.h b/src/ppapi/proxy/ppapi_command_buffer_proxy.h
405index ce2697a5a869e..9c40ab8eaaf45 100644
406--- a/src/ppapi/proxy/ppapi_command_buffer_proxy.h
407+++ b/src/ppapi/proxy/ppapi_command_buffer_proxy.h
408@@ -55,6 +55,7 @@ class PPAPI_PROXY_EXPORT PpapiCommandBufferProxy : public gpu::CommandBuffer,
409       gpu::TransferBufferAllocationOption option =
410           gpu::TransferBufferAllocationOption::kLoseContextOnOOM) override;
411   void DestroyTransferBuffer(int32_t id) override;
412+  void ForceLostContext(gpu::error::ContextLostReason reason) override;
413
414   // gpu::GpuControl implementation:
415   void SetGpuControlClient(gpu::GpuControlClient*) override;
416diff --git a/src/third_party/blink/common/features.cc b/src/third_party/blink/common/features.cc
417index 4b469825b4cda..766786ebc2dd9 100644
418--- a/src/third_party/blink/common/features.cc
419+++ b/src/third_party/blink/common/features.cc
420@@ -887,5 +887,9 @@ const base::FeatureParam<std::string>
421 const base::Feature kCLSM90Improvements{"CLSM90Improvements",
422                                         base::FEATURE_ENABLED_BY_DEFAULT};
423
424+const base::Feature kDisableArrayBufferSizeLimitsForTesting{
425+    "DisableArrayBufferSizeLimitsForTesting",
426+    base::FEATURE_DISABLED_BY_DEFAULT};
427+
428 }  // namespace features
429 }  // namespace blink
430diff --git a/src/third_party/blink/public/common/features.h b/src/third_party/blink/public/common/features.h
431index e371d93b8ffbd..89c12448b0ec8 100644
432--- a/src/third_party/blink/public/common/features.h
433+++ b/src/third_party/blink/public/common/features.h
434@@ -364,6 +364,12 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<std::string>
435
436 BLINK_COMMON_EXPORT extern const base::Feature kCLSM90Improvements;
437
438+// TODO(https://crbug.com/1201109): temporary flag to disable new ArrayBuffer
439+// size limits, so that tests can be written against code receiving these
440+// buffers. Remove when the bindings code instituting these limits is removed.
441+BLINK_COMMON_EXPORT extern const base::Feature
442+    kDisableArrayBufferSizeLimitsForTesting;
443+
444 }  // namespace features
445 }  // namespace blink
446
447diff --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
448index 86415db444bd7..00666c5ff35d8 100644
449--- a/src/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
450+++ b/src/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
451@@ -8310,6 +8310,22 @@ bool WebGLRenderingContextBase::ValidateUniformMatrixParameters(
452     SynthesizeGLError(GL_INVALID_VALUE, function_name, "invalid size");
453     return false;
454   }
455+  // By design the command buffer has an internal (signed) 32-bit
456+  // limit, so ensure that the amount of data passed down to it
457+  // doesn't exceed what it can handle. Only integer or float typed
458+  // arrays can be passed into the uniform*v or uniformMatrix*v
459+  // functions; each has 4-byte elements.
460+  base::CheckedNumeric<int32_t> total_size(actual_size);
461+  total_size *= 4;
462+  // Add on a fixed constant to account for internal metadata in the
463+  // command buffer.
464+  constexpr int32_t kExtraCommandSize = 1024;
465+  total_size += kExtraCommandSize;
466+  if (!total_size.IsValid()) {
467+    SynthesizeGLError(GL_INVALID_VALUE, function_name,
468+                      "size * elementSize, plus a constant, is too large");
469+    return false;
470+  }
471   return true;
472 }
473
474diff --git a/src/third_party/libwebp/README.chromium b/src/third_party/libwebp/README.chromium
475index fd77980a907cc..4968eaea94686 100644
476--- a/src/third_party/libwebp/README.chromium
477+++ b/src/third_party/libwebp/README.chromium
478@@ -1,7 +1,7 @@
479 Name: WebP image encoder/decoder
480 Short Name: libwebp
481 URL: http://developers.google.com/speed/webp
482-Version: v1.2.0
483+Version: 20ef03ee351d4ff03fc5ff3ec4804a879d1b9d5c
484 CPEPrefix: cpe:/a:webmproject:libwebp:1.2.0
485 License: BSD
486 License File: LICENSE
487@@ -9,7 +9,7 @@ Security Critical: Yes
488
489 Description:
490 Source archive:
491-  https://chromium.googlesource.com/webm/libwebp/+archive/v1.2.0.tar.gz
492+  https://chromium.googlesource.com/webm/libwebp/+archive/20ef03ee351d4ff03fc5ff3ec4804a879d1b9d5c.tar.gz
493
494 WebP is an image format that does both lossy and lossless compression of
495 digital photographic images. WebP consists of a codec based on VP8, that Google
496diff --git a/src/third_party/libwebp/src/dsp/alpha_processing_neon.c b/src/third_party/libwebp/src/dsp/alpha_processing_neon.c
497index 9d55421704cc8..27d717507c5fe 100644
498--- a/src/third_party/libwebp/src/dsp/alpha_processing_neon.c
499+++ b/src/third_party/libwebp/src/dsp/alpha_processing_neon.c
500@@ -83,7 +83,7 @@ static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first,
501 static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
502                               int width, int height,
503                               uint8_t* dst, int dst_stride) {
504-  uint32_t alpha_mask = 0xffffffffu;
505+  uint32_t alpha_mask = 0xffu;
506   uint8x8_t mask8 = vdup_n_u8(0xff);
507   uint32_t tmp[2];
508   int i, j;
509@@ -107,6 +107,7 @@ static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
510     dst += dst_stride;
511   }
512   vst1_u8((uint8_t*)tmp, mask8);
513+  alpha_mask *= 0x01010101;
514   alpha_mask &= tmp[0];
515   alpha_mask &= tmp[1];
516   return (alpha_mask != 0xffffffffu);
517@@ -134,7 +135,7 @@ static void DispatchAlphaToGreen_NEON(const uint8_t* alpha, int alpha_stride,
518 static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
519                              int width, int height,
520                              uint8_t* alpha, int alpha_stride) {
521-  uint32_t alpha_mask = 0xffffffffu;
522+  uint32_t alpha_mask = 0xffu;
523   uint8x8_t mask8 = vdup_n_u8(0xff);
524   uint32_t tmp[2];
525   int i, j;
526@@ -156,6 +157,7 @@ static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
527     alpha += alpha_stride;
528   }
529   vst1_u8((uint8_t*)tmp, mask8);
530+  alpha_mask *= 0x01010101;
531   alpha_mask &= tmp[0];
532   alpha_mask &= tmp[1];
533   return (alpha_mask == 0xffffffffu);
534diff --git a/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c b/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c
535index 0412a093cf9ab..9963051798eee 100644
536--- a/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c
537+++ b/src/third_party/libwebp/src/dsp/lossless_enc_mips32.c
538@@ -347,24 +347,24 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[],
539 static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb,
540                              uint32_t* pout, int size) {
541   uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
542-  const uint32_t end = ((size) / 4) * 4;
543+  const int end = ((size) / 4) * 4;
544   const uint32_t* const LoopEnd = pa + end;
545   int i;
546   ASM_START
547   ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)
548   ASM_END_0
549-  for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i];
550+  for (i = 0; i < size - end; ++i) pout[i] = pa[i] + pb[i];
551 }
552
553 static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) {
554   uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
555-  const uint32_t end = ((size) / 4) * 4;
556+  const int end = ((size) / 4) * 4;
557   const uint32_t* const LoopEnd = pa + end;
558   int i;
559   ASM_START
560   ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)
561   ASM_END_1
562-  for (i = end; i < size; ++i) pout[i] += pa[i];
563+  for (i = 0; i < size - end; ++i) pout[i] += pa[i];
564 }
565
566 #undef ASM_END_1
567diff --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
568index 516abd73eb45c..5eb24d449953d 100644
569--- a/src/third_party/libwebp/src/enc/backward_references_cost_enc.c
570+++ b/src/third_party/libwebp/src/enc/backward_references_cost_enc.c
571@@ -577,7 +577,7 @@ static int BackwardReferencesHashChainDistanceOnly(
572       (CostModel*)WebPSafeCalloc(1ULL, cost_model_size);
573   VP8LColorCache hashers;
574   CostManager* cost_manager =
575-      (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager));
576+      (CostManager*)WebPSafeCalloc(1ULL, sizeof(*cost_manager));
577   int offset_prev = -1, len_prev = -1;
578   double offset_cost = -1;
579   int first_offset_is_constant = -1;  // initialized with 'impossible' value
580diff --git a/src/third_party/libwebp/src/enc/backward_references_enc.c b/src/third_party/libwebp/src/enc/backward_references_enc.c
581index 519b36a09153e..d5e931efdd8cf 100644
582--- a/src/third_party/libwebp/src/enc/backward_references_enc.c
583+++ b/src/third_party/libwebp/src/enc/backward_references_enc.c
584@@ -976,15 +976,16 @@ static int GetBackwardReferences(int width, int height,
585       const VP8LHashChain* const hash_chain_tmp =
586           (lz77_types_best[i] == kLZ77Standard) ? hash_chain : &hash_chain_box;
587       const int cache_bits = (i == 1) ? 0 : *cache_bits_best;
588-      if (VP8LBackwardReferencesTraceBackwards(width, height, argb, cache_bits,
589-                                               hash_chain_tmp, &refs[i],
590-                                               refs_tmp)) {
591-        double bit_cost_trace;
592-        VP8LHistogramCreate(histo, refs_tmp, cache_bits);
593-        bit_cost_trace = VP8LHistogramEstimateBits(histo);
594-        if (bit_cost_trace < bit_costs_best[i]) {
595-          BackwardRefsSwap(refs_tmp, &refs[i]);
596-        }
597+      double bit_cost_trace;
598+      if (!VP8LBackwardReferencesTraceBackwards(width, height, argb, cache_bits,
599+                                                hash_chain_tmp, &refs[i],
600+                                                refs_tmp)) {
601+        goto Error;
602+      }
603+      VP8LHistogramCreate(histo, refs_tmp, cache_bits);
604+      bit_cost_trace = VP8LHistogramEstimateBits(histo);
605+      if (bit_cost_trace < bit_costs_best[i]) {
606+        BackwardRefsSwap(refs_tmp, &refs[i]);
607       }
608     }
609
610diff --git a/src/third_party/libwebp/src/enc/vp8l_enc.c b/src/third_party/libwebp/src/enc/vp8l_enc.c
611index 0b44ebe46ec54..1875e53552d31 100644
612--- a/src/third_party/libwebp/src/enc/vp8l_enc.c
613+++ b/src/third_party/libwebp/src/enc/vp8l_enc.c
614@@ -1706,11 +1706,16 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
615   const WebPWorkerInterface* const worker_interface = WebPGetWorkerInterface();
616   int ok_main;
617
618+  if (enc_main == NULL || !VP8LBitWriterInit(&bw_side, 0)) {
619+    WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
620+    VP8LEncoderDelete(enc_main);
621+    return 0;
622+  }
623+
624   // Analyze image (entropy, num_palettes etc)
625-  if (enc_main == NULL ||
626-      !EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main,
627+  if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main,
628                       &red_and_blue_always_zero) ||
629-      !EncoderInit(enc_main) || !VP8LBitWriterInit(&bw_side, 0)) {
630+      !EncoderInit(enc_main)) {
631     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
632     goto Error;
633   }
634