CVE-2026-87440
Overview
Background
- `media::IntervalMap`
- A
mediacontainer inmedia/base/interval_map.hthat maps contiguous key ranges to values by storing transition points in an orderedstd::map. - `DCHECK`
- A Chromium assertion compiled out of release (non-debug) builds, so a violated
DCHECKbecomes silent undefined behavior in shipping Chrome. - `CHECK`
- A Chromium assertion that is retained in all build configurations and terminates the process safely when its condition is false.
- `std::map::upper_bound`
- A lookup returning an iterator to the first element whose key is strictly greater than the query, and returning
begin()when every key already exceeds the query.
Root Cause Analysis
The lookup paths operator[], find, and the iterator’s operator-- all call upper_bound (or step an existing iterator) and then unconditionally do --iter, relying on the invariant that the resulting iterator is never map_.begin() so that the decrement lands on a valid preceding element. That invariant was enforced only by a DCHECK, which compiles to nothing in release builds, so if the map’s expected sentinel/minimum entry is absent or a caller queries below the lowest stored key, upper_bound returns begin() and --i steps the iterator before the first element. Dereferencing that decremented iterator (i->second) is an out-of-bounds read of container-internal memory in the Media component.
The fix promotes each DCHECK to a CHECK, so the precondition is now verified in every build and a violation aborts the process deterministically instead of reading out of bounds.
upper_bound must not be begin() before decrementing) with a debug-only DCHECK that vanishes in production; replacing it with CHECK turns an exploitable OOB read into a controlled, always-on abort.Attack Path
- Reach the map
Drive a
media-pipeline code path (for example a demuxer or track-buffer structure) that stores state in amedia::IntervalMapand exposes lookups to attacker-influenced media input. - Violate the invariant
Supply crafted media such that a query key falls at or below the map’s lowest transition, making
upper_boundreturnmap_.begin(). - Trigger the decrement
Cause
operator[],find, oroperator--to run, where--iter/--isteps the iterator before the first element. - Read out of bounds
The subsequent dereference (
i->second) reads memory preceding the container’s first node, an out-of-bounds read in theMediacomponent.
Impact Assessment
std::map-internal storage within whichever process hosts the media pipeline (typically a renderer or the GPU/utility media process), which can leak internal state or aid further exploitation. It requires reaching a media::IntervalMap lookup with a key that undercuts the map’s minimum entry via malformed or attacker-controlled media, and it only manifests in release builds where the prior DCHECK was compiled out.Files Changed
media/base/interval_map.h
Audit Directions
- `DCHECK` guarding memory safetyFlag any
DCHECKwhose failure would permit an out-of-bounds access, iterator underflow, or bad dereference in release builds, and promote it toCHECK. - `upper_bound`/`lower_bound` then `--`Audit every site that decrements the iterator returned by
upper_boundorlower_bound, since abegin()result makes the decrement undefined and should be checked unconditionally. - Sentinel-dependent invariantsReview containers like
media::IntervalMapwhose safety depends on an always-present minimum/sentinel entry, and verify that invariant is enforced at every lookup rather than assumed.
Patch
From f3c09a109718794172b7f43356927c8aa8600790 Mon Sep 17 00:00:00 2001
From: Christopher Cameron <ccameron@chromium.org>
Date: Mon, 17 Aug 2026 15:06:19 -0700
Subject: [PATCH] media::IntervalMap: Use CHECK instead of DCHECK for fatal conditions
Almost all of the DCHECKs in this header were migrated to CHECKs last
year. Move the remaining ones.
Bug: 513458719
Change-Id: Ib08f2fe4bac642246616a2b0314740b9915859ea
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8265244
Commit-Queue: ccameron chromium <ccameron@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1680851}
---
diff --git a/media/base/interval_map.h b/media/base/interval_map.h
index 259dc08..4916b276 100644
--- a/media/base/interval_map.h
+++ b/media/base/interval_map.h
@@ -142,7 +142,7 @@
// current interval. (But should always have a different value.)
// Not allowed if we're already at map_->begin().
void operator--() {
- DCHECK(iter_ != map_->begin());
+ CHECK(iter_ != map_->begin());
--iter_;
}
@@ -173,7 +173,7 @@
// Defaults to ValueType().
ValueType operator[](const KeyType& k) const {
typename MapType::const_iterator i = map_.upper_bound(k);
- DCHECK(i != map_.begin());
+ CHECK(i != map_.begin());
--i;
return i->second;
}
@@ -226,7 +226,7 @@
// Always returns a valid iterator.
const_iterator find(KeyType k) const {
typename MapType::const_iterator iter = map_.upper_bound(k);
- DCHECK(iter != map_.begin());
+ CHECK(iter != map_.begin());
--iter;
return const_iterator(&map(), iter);
}