summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Zern <jzern@google.com>2023-03-03 16:53:12 -0800
committerJames Zern <jzern@google.com>2023-03-06 10:26:17 -0800
commit6a8a6f4739e21d1f0f21a9af606e87f71d5bbec1 (patch)
tree6e31578d04f708d248b99f04d9e0f1ebdc07f5ad
parente14008c67f0b738cff49d731671abf9e7a2b942b (diff)
downloadlibwebm-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.cc2
-rw-r--r--testing/mkvparser_fuzzer.cc51
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;
}