High chrome Integer Overflow 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInteger overflow in Chromecast
DescriptionInteger overflow in Chromecast
ComponentChromecast
Bug ClassInteger Overflow
Tracker491894115
Fix commit6e070afc3d3e (chromium/src) +11/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Files Changed

  • chromecast/media/audio/net/audio_socket.cc
From 6e070afc3d3e59fdfcfdf09656ab9ff3dbca25bb Mon Sep 17 00:00:00 2001
From: Simeon Anfinrud <sanfin@chromium.org>
Date: Mon, 11 May 2026 20:52:37 -0700
Subject: [PATCH] [chromecast] Fix Potential Integer Underflow and OOB Write in AudioSocket::ParseAudio

Adds an explicit bounds check to ensure size >= sizeof(int32_t) before
processing padding bytes. This prevents an integer underflow that bypasses
later bounds checks.

Bug: 491894115
Test: Compiled and passed unit tests.
Change-Id: I57d2c71e9276cfee6229483b1e3825baf07ccfd3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7765504
Auto-Submit: Simeon Anfinrud <sanfin@chromium.org>
Commit-Queue: Sandeep Vijayasekar <sandv@google.com>
Reviewed-by: Sandeep Vijayasekar <sandv@google.com>
Cr-Commit-Position: refs/heads/main@{#1629038}
---

diff --git a/chromecast/media/audio/net/audio_socket.cc b/chromecast/media/audio/net/audio_socket.cc
index 8c42dd8..babacee 100644
--- a/chromecast/media/audio/net/audio_socket.cc
+++ b/chromecast/media/audio/net/audio_socket.cc
@@ -349,7 +349,7 @@
 bool AudioSocket::ParseAudio(char* data, size_t size) {
   int64_t timestamp;
   if (size < sizeof(timestamp)) {
-    LOG(ERROR) << "Invalid audio packet size " << size << " from " << this;
+    LOG(ERROR) << "Invalid audio buffer size " << size << " from " << this;
     delegate_->OnConnectionError();
     return false;
   }
@@ -359,6 +359,11 @@
   size -= sizeof(timestamp);
 
   // Handle padding bytes.
+  if (size < sizeof(int32_t)) {
+    LOG(ERROR) << "Invalid audio buffer size " << size << " from " << this;
+    delegate_->OnConnectionError();
+    return false;
+  }
   UNSAFE_TODO(data += sizeof(int32_t));
   size -= sizeof(int32_t);
 
@@ -380,6 +385,11 @@
   size -= sizeof(timestamp);
 
   // Handle padding bytes.
+  if (size < sizeof(int32_t)) {
+    LOG(ERROR) << "Invalid audio buffer size " << size << " from " << this;
+    delegate_->OnConnectionError();
+    return false;
+  }
   UNSAFE_TODO(data += sizeof(int32_t));
   size -= sizeof(int32_t);
 
Loading diff…

Original Bug Report

reported by rj...@google.com

Potential Integer Underflow and OOB Write in AudioSocket::ParseAudio

Flapjack (go/flapjack), an LLM-powered static analysis tool, has identified the following potential security issue.

Overview: An integer underflow in AudioSocket::ParseAudio can lead to a highly controllable out-of-bounds write in MixerInputConnection::HandleAudioData. This occurs when processing crafted interleaved audio packets, causing an undersized buffer allocation and subsequent OOB memcpy into the adjacent heap chunk, potentially leading to remote code execution in the mixer service.

Affected files:

  • chromecast/media/audio/net/audio_socket.cc
  • chromecast/media/cma/backend/mixer/mixer_input_connection.cc

Estimated timestamp from git blame: 2025-11-18

Summary

A potential integer underflow vulnerability exists in the Chromecast AudioSocket implementation when parsing audio packets. This vulnerability can be triggered by a compromised renderer or any process capable of sending audio data to the Chromecast mixer service, potentially leading to a highly reliable out-of-bounds write on the heap. This could be leveraged to achieve a sandbox escape and arbitrary code execution in a more privileged process (e.g., the browser or mixer service).

Vulnerability Details

In chromecast/media/audio/net/audio_socket.cc, the functions ParseAudio and ParseAudioBuffer handle incoming audio data. Both functions perform insufficient bounds checking on the size parameter before subtracting the header and padding sizes.

In AudioSocket::ParseAudio:

349: bool AudioSocket::ParseAudio(char* data, size_t size) {
350:   int64_t timestamp;
351:   if (size < sizeof(timestamp)) {
... // Checks that size is at least 8 bytes
354:     return false;
355:   }
356: 
357:   UNSAFE_TODO(memcpy(&timestamp, data, sizeof(timestamp)));
358:   UNSAFE_TODO(data += sizeof(timestamp));
359:   size -= sizeof(timestamp); // size is at least 0 here
360: 
361:   // Handle padding bytes.
362:   UNSAFE_TODO(data += sizeof(int32_t));
363:   size -= sizeof(int32_t); // Vulnerability: size can be less than 4 here, causing an integer underflow
364: 
365:   return delegate_->HandleAudioData(data, size, timestamp);
366: }

If the size passed to ParseAudio is between 8 and 11 inclusive, the subtraction at line 363 will underflow the unsigned size_t variable, resulting in an extremely large value (e.g., 0xFFFFFFFFFFFFFFFC).

Impact and Exploitation Path

This large size is passed to the socket’s delegate, MixerInputConnection::HandleAudioData.

To exploit this, an attacker could establish a connection with an interleaved audio format (e.g., SAMPLE_FORMAT_INT16_I). This format requires conversion, so CreateBufferPool skips calling socket_->UseBufferPool(). As a result, incoming messages bypass HandleAudioBuffer and are routed through OnMessage -> ParseAudio -> HandleAudioData.

  1. Trigger the Underflow: The attacker sends a SmallMessageSocket payload of exactly 10 bytes (2 bytes packet type + 8 bytes timestamp). ParseAudio processes this, underflowing size to 0xFFFFFFFFFFFFFFFC.
  2. Calculate num_frames: In HandleAudioData, num_frames is calculated as size / frame_size. Assuming a 6-channel 16-bit stream, frame_size is 12. The result, 0x1555555555555555, is truncated to a positive int32_t value: 0x55555555 (1,431,655,765).
  3. Buffer Pool Reallocation: Since num_frames exceeds the default pool size, CreateBufferPool(num_frames * 2) is called. The argument num_frames * 2 overflows a signed 32-bit integer, resulting in a negative frame_count (-1431655766).
  4. Undersized Allocation: CreateBufferPool calculates the new buffer size: kAudioMessageHeaderSize + num_channels_ * sizeof(float) * frame_count. Due to the negative frame_count, this evaluates to a small negative number that, when passed to IOBufferPool, truncates to a very small allocation size (e.g., 0 or a few bytes).
  5. Out-of-Bounds Write: IOBufferPool allocates a small chunk (e.g., 32 or 48 bytes) to hold its internal Storage union and the requested data area. Because the requested size is tiny, buffer->data() points precisely to the end of the allocated chunk (the start of the adjacent heap chunk).
  6. Memory Corruption: HandleAudioData performs the following writes:
    UNSAFE_TODO(memcpy(buffer->data(), &num_frames, sizeof(int32_t)));
    UNSAFE_TODO(memcpy(buffer->data() + sizeof(int32_t), &timestamp, sizeof(timestamp)));
    
    Since buffer->data() points to the adjacent heap chunk, this writes num_frames (0x55555555) and the attacker-controlled 8-byte timestamp cleanly out of bounds, directly corrupting the adjacent object.
  7. Clean Exit: HandleAudioData then calls the audio conversion function (e.g., ConvertInterleavedData). Crucially, this function takes size as a 32-bit int. The massive size_t value (0xFFFFFFFFFFFFFFFC) is truncated to -4. The conversion loops evaluate num_frames = data_size / ... = -4 / 12 = 0, causing the function to skip processing and return cleanly without crashing.

By carefully grooming the heap, an attacker could place another object with a vtable (such as an adjacent IOBuffer wrapper) in the next chunk. The OOB write would overwrite its vtable pointer with the attacker-controlled timestamp, providing a reliable primitive for arbitrary code execution.

Proposed Mitigation

Add a bounds check in both AudioSocket::ParseAudio and AudioSocket::ParseAudioBuffer to ensure the remaining size is at least sizeof(int32_t) before attempting to skip the padding bytes.

Evaluated with Chrome root at commit: 843d0814f9a6e06cb8c6dd3ea7d5613ff9ffda45


Results from Flapjack so far have been promising, but it can be wrong in its deductions. At this time, it does not produce proof of concepts or fuzzer tests. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve Flapjack’s 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