diff options
author | James Zern <jzern@google.com> | 2023-03-03 16:53:12 -0800 |
---|---|---|
committer | James Zern <jzern@google.com> | 2023-03-06 10:26:17 -0800 |
commit | 6a8a6f4739e21d1f0f21a9af606e87f71d5bbec1 (patch) | |
tree | 6e31578d04f708d248b99f04d9e0f1ebdc07f5ad | |
parent | e14008c67f0b738cff49d731671abf9e7a2b942b (diff) | |
download | libwebm-6a8a6f4739e21d1f0f21a9af606e87f71d5bbec1.tar.gz |
CuePoint::TrackPosition::Parse: validate m_block
m_block is a long long, but later treated as a long in
Cluster::GetEntry() after being checked whether it's > 0. A value
larger than LONG_MAX may result in a negative value being used as an
index into m_entries[] when sizeof(long) < sizeof(long long).
Bug: webm:1792
Change-Id: Idf15fc4d7e6fd1fa74a022bca63217aad26ff962
-rw-r--r-- | mkvparser/mkvparser.cc | 2 | ||||
-rw-r--r-- | testing/mkvparser_fuzzer.cc | 51 |
2 files changed, 51 insertions, 2 deletions
diff --git a/mkvparser/mkvparser.cc b/mkvparser/mkvparser.cc index 5d583dc..868afcb 100644 --- a/mkvparser/mkvparser.cc +++ b/mkvparser/mkvparser.cc @@ -2432,7 +2432,7 @@ bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_, pos += size; // consume payload } - if ((m_pos < 0) || (m_track <= 0)) { + if ((m_pos < 0) || (m_track <= 0) || (m_block < 0) || (m_block > LONG_MAX)) { return false; } diff --git a/testing/mkvparser_fuzzer.cc b/testing/mkvparser_fuzzer.cc index a1a47b8..b3bb799 100644 --- a/testing/mkvparser_fuzzer.cc +++ b/testing/mkvparser_fuzzer.cc @@ -9,6 +9,7 @@ #include <cstdint> #include <cstdlib> #include <cstring> +#include <functional> #include <memory> #include <new> @@ -58,6 +59,51 @@ void ParseCues(const mkvparser::Segment& segment) { } } +const mkvparser::BlockEntry* GetBlockEntryFromCues( + const void* ctx, const mkvparser::CuePoint* cue, + const mkvparser::CuePoint::TrackPosition* track_pos) { + const auto* const cues = static_cast<const mkvparser::Cues*>(ctx); + return cues->GetBlock(cue, track_pos); +} + +const mkvparser::BlockEntry* GetBlockEntryFromCluster( + const void* ctx, const mkvparser::CuePoint* cue, + const mkvparser::CuePoint::TrackPosition* track_pos) { + if (track_pos == nullptr) { + return nullptr; + } + const auto* const cluster = static_cast<const mkvparser::Cluster*>(ctx); + const mkvparser::BlockEntry* block_entry = + cluster->GetEntry(*cue, *track_pos); + return block_entry; +} + +void WalkCues(const mkvparser::Segment& segment, + std::function<const mkvparser::BlockEntry*( + const void*, const mkvparser::CuePoint*, + const mkvparser::CuePoint::TrackPosition*)> + get_block_entry, + const void* ctx) { + const mkvparser::Cues* const cues = segment.GetCues(); + const mkvparser::Tracks* tracks = segment.GetTracks(); + if (cues == nullptr || tracks == nullptr) { + return; + } + const unsigned long num_tracks = tracks->GetTracksCount(); + + for (const mkvparser::CuePoint* cue = cues->GetFirst(); cue != nullptr; + cue = cues->GetNext(cue)) { + for (unsigned long track_num = 0; track_num < num_tracks; ++track_num) { + const mkvparser::Track* const track = tracks->GetTrackByIndex(track_num); + const mkvparser::CuePoint::TrackPosition* const track_pos = + cue->Find(track); + const mkvparser::BlockEntry* block_entry = + get_block_entry(ctx, cue, track_pos); + static_cast<void>(block_entry); + } + } +} + void ParseCluster(const mkvparser::Cluster& cluster) { const mkvparser::BlockEntry* block_entry; long status = cluster.GetFirst(block_entry); @@ -100,12 +146,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { return 0; } + ParseCues(*segment); + WalkCues(*segment, GetBlockEntryFromCues, segment->GetCues()); + const mkvparser::Cluster* cluster = segment->GetFirst(); while (cluster != nullptr && !cluster->EOS()) { ParseCluster(*cluster); + WalkCues(*segment, GetBlockEntryFromCluster, cluster); cluster = segment->GetNext(cluster); } - ParseCues(*segment); return 0; } |