Medium watch CVSS 4.3 chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized resource in Codecs
DescriptionUninitialized resource in Codecs
ComponentCodecs
Bug ClassUninitialized Memory
Action tierwatch — information disclosure — security-relevant, below the RCE-class bar
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker504670493
Fix commit154727b1485f (chromium/src) +41/-8
CWECWE-908
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-04-20 (per vendor advisory)
Fix landed2026-07-29 (public git)
Disclosed2026-09-08
Patch gap41 days — fix public in source before the advisory

Background

Buffered-image mode
a libjpeg decode mode (info_.buffered_image) that lets a multi-scan JPEG be re-read scan-by-scan and progressively output; the decoder enters it via the kJpegDecompressBufferedImage state (renamed from kJpegDecompressProgressive).
`coef_bits`
a libjpeg field that is non-null only for progressive JPEGs (it tracks per-component coefficient bit positions); for non-progressive multi-scan files (non-interleaved sequential or lossless) it is always null.
`all_components_seen`
an inline lambda that decides whether every component’s scan has been received, gating the call to jpeg_start_output() and the emission of output pixels.
`jpeg_input_complete`
a libjpeg predicate that returns true only once the entire compressed input has been parsed.

Root Cause Analysis

The vulnerable code lives in the kJpegDecompressBufferedImage case (formerly kJpegDecompressProgressive) of the JPEG decoder state machine in jpeg_image_decoder.cc. The gating lambda all_components_seen checked info.coef_bits and, when it iterated the progressive coefficient array without finding an unseen component, fell through to return true; crucially, when info.coef_bits was null — the non-progressive, non-interleaved multi-scan case — the if body was skipped entirely and the function still returned true. As the removed comment path shows, this meant all_components_seen() reported completion on the very first scan, before the remaining component scans had arrived, so the decoder invoked jpeg_start_output() and output pixel buffers for components that had never been parsed — i.e. uninitialized memory.

The fix tightens the check: for the coef_bits == null branch it now returns jpeg_input_complete(&info) instead of an unconditional true, deferring any output until the whole input is parsed and every component scan is complete.

The added regression test nonInterleavedSequentialBufferedDecompress confirms that a half-supplied non-interleaved JPEG now yields neither kFramePartial nor kFrameComplete until the full buffer is provided.

Key insight
The single mistake was that all_components_seen treated a null info.coef_bits (the non-progressive case) as “all components seen” by unconditionally returning true, when in fact null coef_bits gives it no completion signal at all; the fix substitutes jpeg_input_complete(&info) so completion is asserted only when the input is genuinely finished.

Attack Path

  1. Serve a crafted JPEG An attacker hosts a non-interleaved multi-scan (sequential or lossless) JPEG, which the decoder routes into buffered-image mode (info_.buffered_image true, entering kJpegDecompressBufferedImage) where info.coef_bits is null.
  2. Deliver only a partial scan The image is streamed/decoded while only the first component’s scan has been parsed and later component scans are still absent; jpeg_input_complete would still be false at this point.
  3. Premature completion signal all_components_seen skips its coef_bits loop and returns true, so the decoder calls jpeg_start_output() and emits output for components whose scans were never decoded.
  4. Uninitialized memory in output The produced ImageFrame contains uninitialized buffer contents for the unparsed components, matching the advisory’s “uninitialized resource in Codecs.” Any further disclosure of that memory to script (e.g. via canvas readback) or downstream escalation is (inferred) — the diff shows only the premature output, not a read primitive.

Impact Assessment

An attacker who gets a victim to decode a crafted non-interleaved multi-scan JPEG can cause the Blink image decoder (renderer process) to emit an image frame backed by uninitialized memory before the input is complete, an information-disclosure/uninitialized-resource condition. Preconditions are minimal: the image need only be decoded (progressive/incremental decoding of partially received data), with no user interaction beyond loading attacker-controlled content. The advisory classifies this as an uninitialized-resource bug in Codecs and does not report exploitation in the wild; escalation of the leaked bytes into a concrete read primitive or further compromise is (inferred) and not demonstrated by the patch.

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
modified
for
third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
modified
TEST
third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
modified

Files Changed

  • third_party/blink/web_tests/platform/win/images/12-55-expected.png
  • third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png
  • third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png
  • third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
  • third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
  • third_party/blink/web_tests/platform/linux/images/12-55-expected.png
  • third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png
  • third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png
  • third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/12-55-expected.png
  • third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
  • third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png
  • third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
  • third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png
  • third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png
  • third_party/blink/web_tests/platform/mac/images/12-55-expected.png
  • third_party/blink/web_tests/platform/mac/images/182-expected.png
  • third_party/blink/web_tests/platform/win/images/182-expected.png
  • third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png
  • third_party/blink/web_tests/platform/linux/images/182-expected.png
  • third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png
  • third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png
  • third_party/blink/web_tests/platform/linux/images/23-55-expected.png
  • third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png
  • third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png
  • third_party/blink/web_tests/platform/win/images/23-55-expected.png
  • third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/182-expected.png
  • third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png
  • third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png
  • third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/23-55-expected.png
  • third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png
  • third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
  • third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png
  • third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
  • third_party/blink/web_tests/platform/mac/images/23-55-expected.png

Audit Directions

  • Completion gates on optional/null metadata
    Audit any decoder logic that infers “fully received / all parts seen” from a field that is only populated in a subset of formats (like coef_bits for progressive JPEGs); a null/absent field must not be silently treated as “complete.”
  • Buffered/incremental decode output paths
    Review other codecs and image decoders that emit frames incrementally to confirm they gate output on a true input-complete predicate (e.g. jpeg_input_complete-equivalent) rather than a per-scan heuristic, especially for uncommon subtypes (non-interleaved sequential, lossless).
  • Uninitialized output buffers
    Look for cases where output/pixel buffers are handed downstream before every contributing component or channel has been parsed, since these can leak uninitialized memory even without an explicit out-of-bounds access.
From 154727b1485f72b4a02bcb9b02c1ffd004170b2e Mon Sep 17 00:00:00 2001
From: Florin Malita <fmalita@chromium.org>
Date: Wed, 29 Jul 2026 08:41:42 -0700
Subject: [PATCH] Reland "Fix premature output of non-interleaved multi-scan JPEGs"

This reverts commit a4ddaf23c2cbb85af1b09a8c0435265d68129c34.

Reason for revert: reland with additional rebaselines

Original change's description:
> Revert "Fix premature output of non-interleaved multi-scan JPEGs"
>
> This reverts commit 191dfbeb4fd602cd0ee1dcbc9f401268675e3892.
>
> Reason for revert: Causing failures on Mac15 and Win11 bots.
>
> Failure Link: https://ci.chromium.org/ui/p/chromium/builders/ci/win11-arm64-rel-tests/8088/overview
> https://ci.chromium.org/p/chromium/builders/ci/mac15-x64-rel-tests/b8675028340104321601
>
> Original change's description:
> > Fix premature output of non-interleaved multi-scan JPEGs
> >
> > In spite of its name, the kJpegDecompressProgressive code path handles
> > both progressive and non-progressive multi-scan (non-interleaved
> > sequential or lossless) JPEGs. Technically it corresponds to enabling
> > buffered-image mode.
> >
> > Previously, all_components_seen() checked if info.coef_bits was
> > non-null, which covers the progressive case.
> >
> > For non-progressive files, info.coef_bits is null. Because of this,
> > all_components_seen() returned true on the very first scan before
> > subsequent component scans were received. This triggered premature calls
> > to jpeg_start_output() and output of uninitialized memory buffers for
> > the unparsed components.
> >
> > Resolve this by checking jpeg_input_complete() for the non-progressive
> > case. This safely postpones output generation until the entire input has
> > been parsed and all component scans are complete.
> >
> > Add a unit test nonInterleavedSequentialBufferedDecompress to verify
> > that sequential, non-interleaved JPEGs are not progressively decoded
> > while input is incomplete.
> >
> > Rename kJpegDecompressProgressive -> kJpegDecompressBufferedImage to
> > better reflect its semantics.
> >
> > Bug: 504670493
> > Test: blink_platform_unittests --gtest_filter=JPEGImageDecoderTest.*
> > Change-Id: I32a44452c2b74d259a3957176eb64f95159287fe
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8141869
> > Commit-Queue: Florin Malita <fmalita@chromium.org>
> > Reviewed-by: Wan-Teh Chang <wtc@google.com>
> > Cr-Commit-Position: refs/heads/main@{#1669371}
>
> Bug: 504670493, 539967091
> Bug: 504670493
> Change-Id: I5fa309dd6f2b827eb359db19dd9288a2be71418c
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8161825
> Reviewed-by: Wan-Teh Chang <wtc@google.com>
> Auto-Submit: Dibyajyoti Pal <dibyapal@chromium.org>
> Reviewed-by: Florin Malita <fmalita@chromium.org>
> Commit-Queue: Florin Malita <fmalita@chromium.org>
> Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
> Owners-Override: Dibyajyoti Pal <dibyapal@chromium.org>
> Commit-Queue: Dibyajyoti Pal <dibyapal@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1669683}

Bug: 504670493, 539967091
Bug: 504670493
Change-Id: I1122e1404f84ef80d57d0a90c7dc011060405a2c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8165123
Reviewed-by: Wan-Teh Chang <wtc@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1670283}
---
diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
index 4d4b446a6..da1a69a4 100644
--- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
@@ -168,8 +168,8 @@
 enum jstate {
   kJpegHeader,  // Reading JFIF headers
   kJpegStartDecompress,
-  kJpegDecompressProgressive,  // Output progressive pixels
-  kJpegDecompressSequential,   // Output sequential pixels
+  kJpegDecompressBufferedImage,  // Output pixels in buffered-image mode.
+  kJpegDecompressSequential,     // Output pixels in sequential mode.
   kJpegDone
 };
 
@@ -570,8 +570,8 @@
           return false;  // I/O suspension.
         }
 
-        // If this is a progressive JPEG ...
-        state_ = (info_.buffered_image) ? kJpegDecompressProgressive
+        // If this is a JPEG requiring buffered-image mode.
+        state_ = (info_.buffered_image) ? kJpegDecompressBufferedImage
                                         : kJpegDecompressSequential;
         [[fallthrough]];
 
@@ -587,9 +587,9 @@
         }
         [[fallthrough]];
 
-      case kJpegDecompressProgressive:
-        if (state_ == kJpegDecompressProgressive) {
-          auto all_components_seen = [](const jpeg_decompress_struct& info) {
+      case kJpegDecompressBufferedImage:
+        if (state_ == kJpegDecompressBufferedImage) {
+          auto all_components_seen = [](jpeg_decompress_struct& info) -> bool {
             if (info.coef_bits) {
               for (int c = 0; c < info.num_components; ++c) {
                 if (UNSAFE_TODO(info.coef_bits[c])[0] == -1) {
@@ -597,8 +597,12 @@
                   return false;
                 }
               }
+              return true;
             }
-            return true;
+            // For non-progressive (e.g. non-interleaved sequential or lossless)
+            // images coef_bits is always null, and all components are only seen
+            // when the input is complete.
+            return jpeg_input_complete(&info);
           };
           int status = 0;
           int first_scan_to_display =
diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
index a9966f7..adab7cfc 100644
--- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
+++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
@@ -259,6 +259,35 @@
   EXPECT_TRUE(test_decoder->Failed());
 }
 
+// This tests decoding a multi-scan non-interleaved sequential JPEG.
+// Decoding should fail with incomplete data.
+TEST(JPEGImageDecoderTest, nonInterleavedSequentialBufferedDecompress) {
+  Vector<char> test_data =
+      ReadFile("/images/jpeg-suite/baseline/32x32x8_ycbcr.jpg");
+  ASSERT_FALSE(test_data.empty());
+
+  const size_t partial_size = test_data.size() / 2;
+  scoped_refptr<SharedBuffer> partial_buffer = SharedBuffer::Create();
+  partial_buffer->Append(base::span<const char>(test_data).first(partial_size));
+
+  std::unique_ptr<ImageDecoder> test_decoder = CreateJPEGDecoder();
+  test_decoder->SetData(partial_buffer, false);
+
+  ImageFrame* frame = test_decoder->DecodeFrameBufferAtIndex(0);
+  ASSERT_TRUE(frame);
+  EXPECT_NE(frame->GetStatus(), ImageFrame::kFramePartial);
+  EXPECT_NE(frame->GetStatus(), ImageFrame::kFrameComplete);
+  EXPECT_FALSE(test_decoder->Failed());
+
+  scoped_refptr<SharedBuffer> full_buffer = SharedBuffer::Create();
+  full_buffer->Append(base::span<const char>(test_data));
+  test_decoder->SetData(full_buffer, true);
+
+  frame = test_decoder->DecodeFrameBufferAtIndex(0);
+  ASSERT_TRUE(frame);
+  EXPECT_EQ(frame->GetStatus(), ImageFrame::kFrameComplete);
+}
+
 // Decode a JPEG with EXIF data that defines a density corrected size. The EXIF
 // data has the initial IFD at the end of the data blob, and out-of-line data
 // defined just after the header.
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png
index 253052e5..1b02678a 100644
--- a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png
+++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png
index 335d4394..1b02678a 100644
--- a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png
+++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/12-55-expected.png b/third_party/blink/web_tests/platform/linux/images/12-55-expected.png
index dbefbc5..5671bec 100644
--- a/third_party/blink/web_tests/platform/linux/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/182-expected.png b/third_party/blink/web_tests/platform/linux/images/182-expected.png
index 9341f9a60..5671bec 100644
--- a/third_party/blink/web_tests/platform/linux/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/23-55-expected.png b/third_party/blink/web_tests/platform/linux/images/23-55-expected.png
index 941256dc..5671bec 100644
--- a/third_party/blink/web_tests/platform/linux/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
index 3a6bc1e..0be40aa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
index cc6a061..0be40aa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
index b54ebe5..0be40aa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
index 335d4394..1b02678a 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/12-55-expected.png
deleted file mode 100644
index 2e05869c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/12-55-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/182-expected.png
deleted file mode 100644
index 82ab4ee5..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/182-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/23-55-expected.png
deleted file mode 100644
index 91d3852..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/23-55-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png
index bbb54c3..9738f19 100644
--- a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png
index 8aa0b49..9738f19 100644
--- a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png
index 8cdcd02..9738f19 100644
--- a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac/images/12-55-expected.png
index ec38fe3f..7ed9d78bc 100644
--- a/third_party/blink/web_tests/platform/mac/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/182-expected.png b/third_party/blink/web_tests/platform/mac/images/182-expected.png
index 3609f33..7ed9d78bc 100644
--- a/third_party/blink/web_tests/platform/mac/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac/images/23-55-expected.png
index f687a17..7ed9d78bc 100644
--- a/third_party/blink/web_tests/platform/mac/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png
index b3527d2..2d590a86 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png
index 95ab680..2d590a86 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png
index 8113274..2d590a86 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/12-55-expected.png b/third_party/blink/web_tests/platform/win/images/12-55-expected.png
index 3261260..3588010e 100644
--- a/third_party/blink/web_tests/platform/win/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/182-expected.png b/third_party/blink/web_tests/platform/win/images/182-expected.png
index eca92b1..3588010e 100644
--- a/third_party/blink/web_tests/platform/win/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/23-55-expected.png b/third_party/blink/web_tests/platform/win/images/23-55-expected.png
index 32fc3fc..3588010e 100644
--- a/third_party/blink/web_tests/platform/win/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png
index 4c599f97..b035de6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png
index 3ab08e4..b035de6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png
index 2f970193..b035de6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png
index b504399..389fb49 100644
--- a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png
index 329d9f12..389fb49 100644
--- a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png
index 6e3fed2..53edfcd 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png
index 4bb6cc7..53edfcd 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png
index ec7653d..53edfcd 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
index a9966f7..adab7cfc 100644
--- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
+++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc
@@ -259,6 +259,35 @@
   EXPECT_TRUE(test_decoder->Failed());
 }
 
+// This tests decoding a multi-scan non-interleaved sequential JPEG.
+// Decoding should fail with incomplete data.
+TEST(JPEGImageDecoderTest, nonInterleavedSequentialBufferedDecompress) {
+  Vector<char> test_data =
+      ReadFile("/images/jpeg-suite/baseline/32x32x8_ycbcr.jpg");
+  ASSERT_FALSE(test_data.empty());
+
+  const size_t partial_size = test_data.size() / 2;
+  scoped_refptr<SharedBuffer> partial_buffer = SharedBuffer::Create();
+  partial_buffer->Append(base::span<const char>(test_data).first(partial_size));
+
+  std::unique_ptr<ImageDecoder> test_decoder = CreateJPEGDecoder();
+  test_decoder->SetData(partial_buffer, false);
+
+  ImageFrame* frame = test_decoder->DecodeFrameBufferAtIndex(0);
+  ASSERT_TRUE(frame);
+  EXPECT_NE(frame->GetStatus(), ImageFrame::kFramePartial);
+  EXPECT_NE(frame->GetStatus(), ImageFrame::kFrameComplete);
+  EXPECT_FALSE(test_decoder->Failed());
+
+  scoped_refptr<SharedBuffer> full_buffer = SharedBuffer::Create();
+  full_buffer->Append(base::span<const char>(test_data));
+  test_decoder->SetData(full_buffer, true);
+
+  frame = test_decoder->DecodeFrameBufferAtIndex(0);
+  ASSERT_TRUE(frame);
+  EXPECT_EQ(frame->GetStatus(), ImageFrame::kFrameComplete);
+}
+
 // Decode a JPEG with EXIF data that defines a density corrected size. The EXIF
 // data has the initial IFD at the end of the data blob, and out-of-line data
 // defined just after the header.
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png
index 253052e5..1b02678a 100644
--- a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png
+++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png
index 335d4394..1b02678a 100644
--- a/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png
+++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-swiftshader/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/12-55-expected.png b/third_party/blink/web_tests/platform/linux/images/12-55-expected.png
index dbefbc5..5671bec 100644
--- a/third_party/blink/web_tests/platform/linux/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/182-expected.png b/third_party/blink/web_tests/platform/linux/images/182-expected.png
index 9341f9a60..5671bec 100644
--- a/third_party/blink/web_tests/platform/linux/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/images/23-55-expected.png b/third_party/blink/web_tests/platform/linux/images/23-55-expected.png
index 941256dc..5671bec 100644
--- a/third_party/blink/web_tests/platform/linux/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
index 3a6bc1e..0be40aa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
index cc6a061..0be40aa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
index b54ebe5..0be40aa 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
index 335d4394..1b02678a 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/12-55-expected.png
deleted file mode 100644
index 2e05869c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/12-55-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/182-expected.png
deleted file mode 100644
index 82ab4ee5..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/182-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/23-55-expected.png
deleted file mode 100644
index 91d3852..0000000
--- a/third_party/blink/web_tests/platform/mac-mac13-arm64/virtual/exotic-color-space/images/23-55-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png
index bbb54c3..9738f19 100644
--- a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png
index 8aa0b49..9738f19 100644
--- a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png
index 8cdcd02..9738f19 100644
--- a/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac26-arm64/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac/images/12-55-expected.png
index ec38fe3f..7ed9d78bc 100644
--- a/third_party/blink/web_tests/platform/mac/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/182-expected.png b/third_party/blink/web_tests/platform/mac/images/182-expected.png
index 3609f33..7ed9d78bc 100644
--- a/third_party/blink/web_tests/platform/mac/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac/images/23-55-expected.png
index f687a17..7ed9d78bc 100644
--- a/third_party/blink/web_tests/platform/mac/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png
index b3527d2..2d590a86 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png
index 95ab680..2d590a86 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png
index 8113274..2d590a86 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/12-55-expected.png b/third_party/blink/web_tests/platform/win/images/12-55-expected.png
index 3261260..3588010e 100644
--- a/third_party/blink/web_tests/platform/win/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/182-expected.png b/third_party/blink/web_tests/platform/win/images/182-expected.png
index eca92b1..3588010e 100644
--- a/third_party/blink/web_tests/platform/win/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/23-55-expected.png b/third_party/blink/web_tests/platform/win/images/23-55-expected.png
index 32fc3fc..3588010e 100644
--- a/third_party/blink/web_tests/platform/win/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png
index 4c599f97..b035de6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png
index 3ab08e4..b035de6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png
index 2f970193..b035de6 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png
index b504399..389fb49 100644
--- a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png
index 329d9f12..389fb49 100644
--- a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/23-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png
index 6e3fed2..53edfcd 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/12-55-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png
index 4bb6cc7..53edfcd 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/182-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png
index ec7653d..53edfcd 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png
+++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/exotic-color-space/images/23-55-expected.png
Binary files differ
Loading diff…

Original Bug Report

reported by vm...@google.com

Uninitialized heap disclosure in libjpeg-turbo via progressive display

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the Chrome Security team. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A potential uninitialized heap disclosure exists in libjpeg-turbo’s lossless decoder when combined with Blink’s progressive image decoding. A premature watermark advancement in libjpeg-turbo’s memory manager, coupled with a flaw in Blink’s JPEGImageDecoder::all_components_seen(), allows an attacker to leak uninitialized PartitionAlloc heap memory to a canvas. This can be used as an ASLR-defeat primitive.

Affected files:

  • third_party/libjpeg_turbo/src/jddiffct.c
  • third_party/libjpeg_turbo/src/jmemmgr.c
  • third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
  • third_party/libjpeg_turbo/src/jdlhuff.c
  • third_party/libjpeg_turbo/src/jdcolor.c

Estimated timestamp from git blame: 2025-08-07

Summary

A potential uninitialized heap disclosure vulnerability exists in the libjpeg-turbo lossless decoder (used for SOF3 JPEGs) when combined with Blink’s progressive image decoding. A Time-of-Check Time-of-Use (TOCTOU) flaw in libjpeg-turbo’s memory management, combined with incomplete state tracking in Blink’s JPEGImageDecoder, allows an attacker to read renderer process PartitionAlloc heap memory via a <canvas> element.

Technical Details

The vulnerability arises from the interaction between libjpeg-turbo’s virtual array management and Blink’s progressive display logic:

  1. Premature Watermark Advancement: In jddiffct.c, the lossless difference controller allocates virtual sample arrays with pre_zero=FALSE. When processing a scan, consume_data() calls access_virt_sarray with writable=TRUE. Inside jmemmgr.c:987, the memory manager immediately advances the first_undef_row watermark before any data is written to the buffer.
  2. Suspension: If the input stream is truncated or stalls mid-row, decompress_data() returns JPEG_SUSPENDED. The current row is left completely unwritten, but is incorrectly marked as ‘defined’ by the memory manager because the watermark was already advanced.
  3. Progressive Display Bypass: Back in Blink, JPEGImageDecoder::Decode checks if the partial image can be displayed progressively using the all_components_seen lambda (jpeg_image_decoder.cc:592). This lambda checks info.coef_bits. Because lossless JPEGs do not use DCT, coef_bits is NULL. The lambda immediately returns true, causing Blink to bypass the check and force output of the incomplete scan via jpeg_start_output.
  4. Uninitialized Read: During output generation, output_data() (jddiffct.c:315) calls access_virt_sarray with writable=FALSE to read the stalled row. Because the first_undef_row watermark was advanced in Step 1, the memory manager does not throw a JERR_BAD_VIRTUAL_ACCESS error.
  5. Leak to Canvas: output_data copies the uninitialized PartitionAlloc heap memory into the output buffer. Blink’s OutputScanlines then writes this data into the ImageFrame. An attacker can subsequently draw the partially decoded image to a canvas and use getImageData() to read the leaked heap data.

Potential Attacker Steps to Trigger

Note: These are suggested steps based on code analysis; a working Proof of Concept has not been run.

  1. Serve a crafted, multi-scan 3-component SOF3 (lossless) JPEG.
  2. Provide full entropy for the first two scans.
  3. For the third scan, provide valid entropy for the first R rows, then artificially stall the TCP connection mid-way through row R+1.
  4. In the victim’s browser, load the image and draw it to a <canvas> using ctx.drawImage().
  5. Call ctx.getImageData() and inspect the color channels corresponding to the stalled scan of row R+1. The resulting bytes will contain uninitialized heap memory.

Suggested Fix

  1. Blink: Fix the logic in all_components_seen (jpeg_image_decoder.cc:592) so that it accurately tracks component availability for lossless JPEGs, rather than defaulting to true when info.coef_bits is NULL.
  2. libjpeg-turbo: Either initialize the virtual arrays by setting pre_zero=TRUE when allocating them in jddiffct.c:392, or delay advancing first_undef_row in jmemmgr.c until the caller signals that the write has actually completed.

Evaluated with Chrome root at commit: 7353d249d9cacf9c7218e1d7b8a39cf39c72d646


Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker