diff --git a/third_party/blink/renderer/platform/media/multi_buffer.cc b/third_party/blink/renderer/platform/media/multi_buffer.cc index a44fe6b962f28..0959d0f77e8a5 100644 --- a/third_party/blink/renderer/platform/media/multi_buffer.cc +++ b/third_party/blink/renderer/platform/media/multi_buffer.cc @@ -409,7 +409,9 @@ void MultiBuffer::OnDataProviderEvent(DataProvider* provider_tmp) { AddProvider(std::move(provider)); break; } - DCHECK_GE(pos, 0); + // SECURITY: BlockId must be non-negative; -1/-2 are HashMap sentinel + // keys and inserting them corrupts data_ (UAF on tombstone match). + CHECK_GE(pos, 0); scoped_refptr data = provider->Read(); data_.Set(pos, data); eof = data->end_of_stream(); diff --git a/third_party/blink/renderer/platform/wtf/hash_table.h b/third_party/blink/renderer/platform/wtf/hash_table.h index 1d86fd9d4d6eb..016d2612f0223 100644 --- a/third_party/blink/renderer/platform/wtf/hash_table.h +++ b/third_party/blink/renderer/platform/wtf/hash_table.h @@ -1034,6 +1034,11 @@ HashTable::Lookup( if (KeyTraits::kSafeToCompareToEmptyOrDeleted) { if (HashTranslator::Equal(Extractor::ExtractKey(*entry), key)) { + // SECURITY: a key that compares equal to the deleted-bucket sentinel + // means the caller passed the reserved deleted value as a key + // (forbidden). Returning a tombstone here would hand back destructed + // value storage and lead to UAF. + CHECK(!IsDeletedBucket(*entry)); return entry; } @@ -1236,6 +1241,11 @@ typename HashTable:: if (KeyTraits::kSafeToCompareToEmptyOrDeleted) { if (HashTranslator::Equal(Extractor::ExtractKey(*entry), key)) { + // SECURITY: a key that compares equal to the deleted-bucket sentinel + // means the caller passed the reserved deleted value as a key + // (forbidden). Returning a tombstone as is_new_entry=false would let + // HashMap::Set assign into a destructed value slot -> UAF. + CHECK(!IsDeletedBucket(*entry)); return AddResult(this, entry, false); }