Medium CVSS 8.8 chrome OOB 📄 Reporter bug report

Overview

Medium
Severity
8.8
CVSS
No
Exploited ITW
Embargoed
Fix Status
ImpactBuffer overflow in Media
DescriptionBuffer overflow in Media
ComponentMedia
Bug ClassOOB
Tracker504356442
CWECWE-122 (Heap buffer overflow)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-04-19 (per vendor advisory)
Disclosed2026-08-25

Fix not yet public

No public source fix for this bug has been identified on the main branch yet — it is embargoed or not yet disclosed. Root-cause analysis is withheld until the fix commit is available.

Original Bug Report

reported by [email protected]

Potential Heap OOB write in FFmpeg FLAC RISC-V Vector kernels via loop underflow

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 go/chrome-ai-generated-security-bugs-faq for more information.

Overview: The RISC-V Vector (RVV) FLAC LPC kernels in FFmpeg fail to guard against cases where the number of samples equals the predictor order. This leads to an immediate loop counter underflow and a sequential heap out-of-bounds write in the renderer process. The issue is reachable via standard web audio APIs on supported hardware.

Affected files:

  • third_party/ffmpeg/libavcodec/riscv/flacdsp_rvv.S
  • third_party/ffmpeg/libavcodec/flacdec.c
  • third_party/ffmpeg/libavcodec/riscv/flacdsp_init.c

Estimated timestamp from git blame: 2024-05-27

Description

A potential heap out-of-bounds (OOB) write vulnerability exists in the RISC-V Vector (RVV) implementation of FLAC LPC (Linear Predictive Coding) reconstruction kernels within Chromium’s FFmpeg copy.

In third_party/ffmpeg/libavcodec/riscv/flacdsp_rvv.S, the DSP kernels (e.g., ff_flac_lpc16_rvv) calculate their loop iteration count by subtracting the predictor order (pred_order) from the total length (len). The kernels use a do-while loop structure without an initial guard to ensure len > pred_order. If len == pred_order, the loop counter initializes to 0, immediately underflows to -1 (0xFFFFFFFFFFFFFFFF) inside the loop, and continues for approximately 2^64 iterations, causing a massive sequential OOB read-modify-write across the heap.

Root Cause Analysis

There are two interacting flaws that make this reachable:

  1. Permissive Check in Decoder: In third_party/ffmpeg/libavcodec/flacdec.c, the function decode_residuals verifies the predictor order against the number of samples in a partition: if (pred_order > samples) { ... return AVERROR_INVALIDDATA; } (line 270). This check uses strict inequality. If a crafted frame sets blocksize to 32, pred_order to 32, and rice_order to 0, then samples evaluates to 32. The check passes because 32 is not greater than 32.
  2. Missing Guard in Assembly: The execution proceeds to call the DSP functions (e.g., s->dsp.lpc16) passing s->blocksize (32) as the len argument and 32 as pred_order. In flacdsp_rvv.S (line 23, ff_flac_lpc16_rvv):
            sub     a4, a4, a2          // a4 (counter) = 32 - 32 = 0
            ...
    1:
            // ... loop body ...
            addi    a4, a4, -1          // a4 underflows to -1
            // ... out of bounds memory write occurs here ...
            bnez    a4, 1b              // Branches back because -1 != 0
    
    Unlike the C and x86/ARM assembly implementations which safely skip the loop if len <= pred_order, the RVV implementation falls straight through.

Potential Impact & Exploitability

This is a classic ‘wild copy’ vulnerability occurring in the sandboxed renderer process when processing media via the <audio> tag or WebCodecs. While the enormous loop will inevitably attempt to access an unmapped page and trigger a SIGSEGV, the sequential writing takes measurable CPU time.

An attacker could potentially exploit this by running a concurrent Web Worker. By grooming the heap layout prior to the OOB write, the Web Worker could race the crash window to hijack corrupted Javascript objects or function pointers before the kernel terminates the process, potentially leading to Remote Code Execution (RCE) within the sandbox. Because the corruption occurs in uninstrumented third-party assembly via raw pointers, MiraclePtr (BackupRefPtr) provides no protection.

Potential Reproduction Steps

(Note: These are suggested steps based on static analysis; our tooling agent cannot execute code to verify.)

  1. Use a Chromium build for riscv64 with RVV support enabled (e.g., in QEMU with -cpu rv64,v=true).
  2. Craft a FLAC audio file containing a frame where:
    • blocksize is explicitly set to 32.
    • A subframe is type LPC with a prediction order of 32.
    • The subframe’s residual data uses a rice_order of 0.
  3. Host the file and load it in the renderer using an HTML5 <audio> tag.
  4. The ff_flac_lpc16_rvv function will trigger the massive loop, ultimately causing a renderer crash (SIGSEGV), demonstrating the memory corruption.

Suggested Fix

  1. Assembly Guard: Update the RVV kernels in third_party/ffmpeg/libavcodec/riscv/flacdsp_rvv.S to include a branch instruction before the loop to exit early if the calculated iteration count is zero or negative (e.g., blez a4, end).
  2. Upstream FFmpeg: Ensure this fix is contributed back to upstream FFmpeg.
  3. Decoder Check (Optional but recommended): Re-evaluate the logic in flacdec.c to determine if pred_order == samples is semantically valid for all partitions. If it implies no residuals are present, skipping the DSP call entirely in C might be safer.

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