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