xref: /aosp_15_r20/external/libwebm/testing/mkvparser_fuzzer.cc (revision 103e46e4cd4b6efcf6001f23fa8665fb110abf8d)
1*103e46e4SHarish Mahendrakar // Copyright (c) 2022 The WebM project authors. All Rights Reserved.
2*103e46e4SHarish Mahendrakar //
3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license
4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source
5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found
6*103e46e4SHarish Mahendrakar // in the file PATENTS.  All contributing project authors may
7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree.
8*103e46e4SHarish Mahendrakar #include <cstddef>
9*103e46e4SHarish Mahendrakar #include <cstdint>
10*103e46e4SHarish Mahendrakar #include <cstdlib>
11*103e46e4SHarish Mahendrakar #include <cstring>
12*103e46e4SHarish Mahendrakar #include <functional>
13*103e46e4SHarish Mahendrakar #include <memory>
14*103e46e4SHarish Mahendrakar #include <new>
15*103e46e4SHarish Mahendrakar 
16*103e46e4SHarish Mahendrakar #include "mkvparser/mkvparser.h"
17*103e46e4SHarish Mahendrakar #include "mkvparser/mkvreader.h"
18*103e46e4SHarish Mahendrakar 
19*103e46e4SHarish Mahendrakar namespace {
20*103e46e4SHarish Mahendrakar 
21*103e46e4SHarish Mahendrakar class MemoryReader : public mkvparser::IMkvReader {
22*103e46e4SHarish Mahendrakar  public:
MemoryReader(const uint8_t * data,size_t size)23*103e46e4SHarish Mahendrakar   MemoryReader(const uint8_t* data, size_t size) : data_(data), size_(size) {}
24*103e46e4SHarish Mahendrakar 
Read(long long pos,long len,unsigned char * buf)25*103e46e4SHarish Mahendrakar   int Read(long long pos, long len, unsigned char* buf) override {
26*103e46e4SHarish Mahendrakar     if (pos < 0 || len < 0) {
27*103e46e4SHarish Mahendrakar       abort();
28*103e46e4SHarish Mahendrakar     }
29*103e46e4SHarish Mahendrakar     if (pos >= size_ || size_ - pos < len) {
30*103e46e4SHarish Mahendrakar       return -1;
31*103e46e4SHarish Mahendrakar     }
32*103e46e4SHarish Mahendrakar     memcpy(buf, data_ + pos, len);
33*103e46e4SHarish Mahendrakar     return 0;
34*103e46e4SHarish Mahendrakar   }
35*103e46e4SHarish Mahendrakar 
Length(long long * total,long long * available)36*103e46e4SHarish Mahendrakar   int Length(long long* total, long long* available) override {
37*103e46e4SHarish Mahendrakar     if (total != nullptr) {
38*103e46e4SHarish Mahendrakar       *total = size_;
39*103e46e4SHarish Mahendrakar     }
40*103e46e4SHarish Mahendrakar     if (available != nullptr) {
41*103e46e4SHarish Mahendrakar       *available = size_;
42*103e46e4SHarish Mahendrakar     }
43*103e46e4SHarish Mahendrakar     return 0;
44*103e46e4SHarish Mahendrakar   }
45*103e46e4SHarish Mahendrakar 
46*103e46e4SHarish Mahendrakar  private:
47*103e46e4SHarish Mahendrakar   const uint8_t* data_;
48*103e46e4SHarish Mahendrakar   size_t size_;
49*103e46e4SHarish Mahendrakar };
50*103e46e4SHarish Mahendrakar 
ParseCues(const mkvparser::Segment & segment)51*103e46e4SHarish Mahendrakar void ParseCues(const mkvparser::Segment& segment) {
52*103e46e4SHarish Mahendrakar   const mkvparser::Cues* const cues = segment.GetCues();
53*103e46e4SHarish Mahendrakar   if (cues == nullptr) {
54*103e46e4SHarish Mahendrakar     return;
55*103e46e4SHarish Mahendrakar   }
56*103e46e4SHarish Mahendrakar 
57*103e46e4SHarish Mahendrakar   while (!cues->DoneParsing()) {
58*103e46e4SHarish Mahendrakar     cues->LoadCuePoint();
59*103e46e4SHarish Mahendrakar   }
60*103e46e4SHarish Mahendrakar }
61*103e46e4SHarish Mahendrakar 
GetBlockEntryFromCues(const void * ctx,const mkvparser::CuePoint * cue,const mkvparser::CuePoint::TrackPosition * track_pos)62*103e46e4SHarish Mahendrakar const mkvparser::BlockEntry* GetBlockEntryFromCues(
63*103e46e4SHarish Mahendrakar     const void* ctx, const mkvparser::CuePoint* cue,
64*103e46e4SHarish Mahendrakar     const mkvparser::CuePoint::TrackPosition* track_pos) {
65*103e46e4SHarish Mahendrakar   const auto* const cues = static_cast<const mkvparser::Cues*>(ctx);
66*103e46e4SHarish Mahendrakar   return cues->GetBlock(cue, track_pos);
67*103e46e4SHarish Mahendrakar }
68*103e46e4SHarish Mahendrakar 
GetBlockEntryFromCluster(const void * ctx,const mkvparser::CuePoint * cue,const mkvparser::CuePoint::TrackPosition * track_pos)69*103e46e4SHarish Mahendrakar const mkvparser::BlockEntry* GetBlockEntryFromCluster(
70*103e46e4SHarish Mahendrakar     const void* ctx, const mkvparser::CuePoint* cue,
71*103e46e4SHarish Mahendrakar     const mkvparser::CuePoint::TrackPosition* track_pos) {
72*103e46e4SHarish Mahendrakar   if (track_pos == nullptr) {
73*103e46e4SHarish Mahendrakar     return nullptr;
74*103e46e4SHarish Mahendrakar   }
75*103e46e4SHarish Mahendrakar   const auto* const cluster = static_cast<const mkvparser::Cluster*>(ctx);
76*103e46e4SHarish Mahendrakar   const mkvparser::BlockEntry* block_entry =
77*103e46e4SHarish Mahendrakar       cluster->GetEntry(*cue, *track_pos);
78*103e46e4SHarish Mahendrakar   return block_entry;
79*103e46e4SHarish Mahendrakar }
80*103e46e4SHarish Mahendrakar 
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)81*103e46e4SHarish Mahendrakar void WalkCues(const mkvparser::Segment& segment,
82*103e46e4SHarish Mahendrakar               std::function<const mkvparser::BlockEntry*(
83*103e46e4SHarish Mahendrakar                   const void*, const mkvparser::CuePoint*,
84*103e46e4SHarish Mahendrakar                   const mkvparser::CuePoint::TrackPosition*)>
85*103e46e4SHarish Mahendrakar                   get_block_entry,
86*103e46e4SHarish Mahendrakar               const void* ctx) {
87*103e46e4SHarish Mahendrakar   const mkvparser::Cues* const cues = segment.GetCues();
88*103e46e4SHarish Mahendrakar   const mkvparser::Tracks* tracks = segment.GetTracks();
89*103e46e4SHarish Mahendrakar   if (cues == nullptr || tracks == nullptr) {
90*103e46e4SHarish Mahendrakar     return;
91*103e46e4SHarish Mahendrakar   }
92*103e46e4SHarish Mahendrakar   const unsigned long num_tracks = tracks->GetTracksCount();
93*103e46e4SHarish Mahendrakar 
94*103e46e4SHarish Mahendrakar   for (const mkvparser::CuePoint* cue = cues->GetFirst(); cue != nullptr;
95*103e46e4SHarish Mahendrakar        cue = cues->GetNext(cue)) {
96*103e46e4SHarish Mahendrakar     for (unsigned long track_num = 0; track_num < num_tracks; ++track_num) {
97*103e46e4SHarish Mahendrakar       const mkvparser::Track* const track = tracks->GetTrackByIndex(track_num);
98*103e46e4SHarish Mahendrakar       const mkvparser::CuePoint::TrackPosition* const track_pos =
99*103e46e4SHarish Mahendrakar           cue->Find(track);
100*103e46e4SHarish Mahendrakar       const mkvparser::BlockEntry* block_entry =
101*103e46e4SHarish Mahendrakar           get_block_entry(ctx, cue, track_pos);
102*103e46e4SHarish Mahendrakar       static_cast<void>(block_entry);
103*103e46e4SHarish Mahendrakar     }
104*103e46e4SHarish Mahendrakar   }
105*103e46e4SHarish Mahendrakar }
106*103e46e4SHarish Mahendrakar 
ParseCluster(const mkvparser::Cluster & cluster)107*103e46e4SHarish Mahendrakar void ParseCluster(const mkvparser::Cluster& cluster) {
108*103e46e4SHarish Mahendrakar   const mkvparser::BlockEntry* block_entry;
109*103e46e4SHarish Mahendrakar   long status = cluster.GetFirst(block_entry);
110*103e46e4SHarish Mahendrakar   if (status != 0) {
111*103e46e4SHarish Mahendrakar     return;
112*103e46e4SHarish Mahendrakar   }
113*103e46e4SHarish Mahendrakar 
114*103e46e4SHarish Mahendrakar   while (block_entry != nullptr && !block_entry->EOS()) {
115*103e46e4SHarish Mahendrakar     const mkvparser::Block* const block = block_entry->GetBlock();
116*103e46e4SHarish Mahendrakar     if (block == nullptr) {
117*103e46e4SHarish Mahendrakar       return;
118*103e46e4SHarish Mahendrakar     }
119*103e46e4SHarish Mahendrakar 
120*103e46e4SHarish Mahendrakar     status = cluster.GetNext(block_entry, block_entry);
121*103e46e4SHarish Mahendrakar     if (status != 0) {
122*103e46e4SHarish Mahendrakar       return;
123*103e46e4SHarish Mahendrakar     }
124*103e46e4SHarish Mahendrakar   }
125*103e46e4SHarish Mahendrakar }
126*103e46e4SHarish Mahendrakar 
127*103e46e4SHarish Mahendrakar }  // namespace
128*103e46e4SHarish Mahendrakar 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)129*103e46e4SHarish Mahendrakar extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
130*103e46e4SHarish Mahendrakar   MemoryReader reader(data, size);
131*103e46e4SHarish Mahendrakar 
132*103e46e4SHarish Mahendrakar   long long int pos = 0;
133*103e46e4SHarish Mahendrakar   std::unique_ptr<mkvparser::EBMLHeader> ebml_header(
134*103e46e4SHarish Mahendrakar       new (std::nothrow) mkvparser::EBMLHeader());  // NOLINT
135*103e46e4SHarish Mahendrakar   if (ebml_header->Parse(&reader, pos) < 0) {
136*103e46e4SHarish Mahendrakar     return 0;
137*103e46e4SHarish Mahendrakar   }
138*103e46e4SHarish Mahendrakar 
139*103e46e4SHarish Mahendrakar   mkvparser::Segment* temp_segment;
140*103e46e4SHarish Mahendrakar   if (mkvparser::Segment::CreateInstance(&reader, pos, temp_segment) != 0) {
141*103e46e4SHarish Mahendrakar     return 0;
142*103e46e4SHarish Mahendrakar   }
143*103e46e4SHarish Mahendrakar   std::unique_ptr<mkvparser::Segment> segment(temp_segment);
144*103e46e4SHarish Mahendrakar 
145*103e46e4SHarish Mahendrakar   if (segment->Load() < 0) {
146*103e46e4SHarish Mahendrakar     return 0;
147*103e46e4SHarish Mahendrakar   }
148*103e46e4SHarish Mahendrakar 
149*103e46e4SHarish Mahendrakar   ParseCues(*segment);
150*103e46e4SHarish Mahendrakar   WalkCues(*segment, GetBlockEntryFromCues, segment->GetCues());
151*103e46e4SHarish Mahendrakar 
152*103e46e4SHarish Mahendrakar   const mkvparser::Cluster* cluster = segment->GetFirst();
153*103e46e4SHarish Mahendrakar   while (cluster != nullptr && !cluster->EOS()) {
154*103e46e4SHarish Mahendrakar     ParseCluster(*cluster);
155*103e46e4SHarish Mahendrakar     WalkCues(*segment, GetBlockEntryFromCluster, cluster);
156*103e46e4SHarish Mahendrakar     cluster = segment->GetNext(cluster);
157*103e46e4SHarish Mahendrakar   }
158*103e46e4SHarish Mahendrakar 
159*103e46e4SHarish Mahendrakar   return 0;
160*103e46e4SHarish Mahendrakar }
161