1*09537850SAkhilesh Sanikop // Copyright 2020 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop // http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop
15*09537850SAkhilesh Sanikop #include <cstddef>
16*09537850SAkhilesh Sanikop #include <cstdint>
17*09537850SAkhilesh Sanikop #include <memory>
18*09537850SAkhilesh Sanikop #include <vector>
19*09537850SAkhilesh Sanikop
20*09537850SAkhilesh Sanikop #include "examples/file_reader.h"
21*09537850SAkhilesh Sanikop #include "examples/file_reader_constants.h"
22*09537850SAkhilesh Sanikop #include "examples/file_reader_interface.h"
23*09537850SAkhilesh Sanikop #include "src/buffer_pool.h"
24*09537850SAkhilesh Sanikop #include "src/decoder_impl.h"
25*09537850SAkhilesh Sanikop #include "src/decoder_state.h"
26*09537850SAkhilesh Sanikop #include "src/internal_frame_buffer_list.h"
27*09537850SAkhilesh Sanikop #include "src/obu_parser.h"
28*09537850SAkhilesh Sanikop #include "tests/fuzzer/fuzzer_temp_file.h"
29*09537850SAkhilesh Sanikop
30*09537850SAkhilesh Sanikop namespace {
31*09537850SAkhilesh Sanikop
32*09537850SAkhilesh Sanikop #if defined(LIBGAV1_EXHAUSTIVE_FUZZING)
33*09537850SAkhilesh Sanikop // Set a large upper bound to give more coverage of a single input; this value
34*09537850SAkhilesh Sanikop // should be larger than most of the frame counts in the corpus.
35*09537850SAkhilesh Sanikop constexpr int kMaxFrames = 100;
36*09537850SAkhilesh Sanikop constexpr size_t kMaxDataSize = 400 * 1024;
37*09537850SAkhilesh Sanikop #else
38*09537850SAkhilesh Sanikop // Restrict the number of frames and obus to improve fuzzer throughput.
39*09537850SAkhilesh Sanikop constexpr int kMaxFrames = 5;
40*09537850SAkhilesh Sanikop constexpr size_t kMaxDataSize = 200 * 1024;
41*09537850SAkhilesh Sanikop #endif
42*09537850SAkhilesh Sanikop
ParseObu(const uint8_t * const data,size_t size)43*09537850SAkhilesh Sanikop inline void ParseObu(const uint8_t* const data, size_t size) {
44*09537850SAkhilesh Sanikop size_t av1c_size;
45*09537850SAkhilesh Sanikop const std::unique_ptr<uint8_t[]> av1c_box =
46*09537850SAkhilesh Sanikop libgav1::ObuParser::GetAV1CodecConfigurationBox(data, size, &av1c_size);
47*09537850SAkhilesh Sanikop static_cast<void>(av1c_box);
48*09537850SAkhilesh Sanikop
49*09537850SAkhilesh Sanikop libgav1::InternalFrameBufferList buffer_list;
50*09537850SAkhilesh Sanikop libgav1::BufferPool buffer_pool(libgav1::OnInternalFrameBufferSizeChanged,
51*09537850SAkhilesh Sanikop libgav1::GetInternalFrameBuffer,
52*09537850SAkhilesh Sanikop libgav1::ReleaseInternalFrameBuffer,
53*09537850SAkhilesh Sanikop &buffer_list);
54*09537850SAkhilesh Sanikop libgav1::DecoderState decoder_state;
55*09537850SAkhilesh Sanikop libgav1::ObuParser parser(data, size, 0, &buffer_pool, &decoder_state);
56*09537850SAkhilesh Sanikop libgav1::RefCountedBufferPtr current_frame;
57*09537850SAkhilesh Sanikop int parsed_frames = 0;
58*09537850SAkhilesh Sanikop while (parser.HasData()) {
59*09537850SAkhilesh Sanikop if (parser.ParseOneFrame(¤t_frame) != libgav1::kStatusOk) break;
60*09537850SAkhilesh Sanikop if (++parsed_frames >= kMaxFrames) break;
61*09537850SAkhilesh Sanikop }
62*09537850SAkhilesh Sanikop }
63*09537850SAkhilesh Sanikop
64*09537850SAkhilesh Sanikop } // namespace
65*09537850SAkhilesh Sanikop
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)66*09537850SAkhilesh Sanikop extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
67*09537850SAkhilesh Sanikop // Reject large chunks of data to improve fuzzer throughput.
68*09537850SAkhilesh Sanikop if (size > kMaxDataSize) return 0;
69*09537850SAkhilesh Sanikop
70*09537850SAkhilesh Sanikop // Treat the input as a raw OBU stream.
71*09537850SAkhilesh Sanikop ParseObu(data, size);
72*09537850SAkhilesh Sanikop
73*09537850SAkhilesh Sanikop // Use the first frame from an IVF to bypass any read errors from the parser.
74*09537850SAkhilesh Sanikop static constexpr size_t kIvfHeaderSize =
75*09537850SAkhilesh Sanikop libgav1::kIvfFileHeaderSize + libgav1::kIvfFrameHeaderSize;
76*09537850SAkhilesh Sanikop if (size >= kIvfHeaderSize) {
77*09537850SAkhilesh Sanikop ParseObu(data + kIvfHeaderSize, size - kIvfHeaderSize);
78*09537850SAkhilesh Sanikop }
79*09537850SAkhilesh Sanikop
80*09537850SAkhilesh Sanikop FuzzerTemporaryFile tempfile(data, size);
81*09537850SAkhilesh Sanikop auto file_reader =
82*09537850SAkhilesh Sanikop libgav1::FileReader::Open(tempfile.filename(), /*error_tolerant=*/true);
83*09537850SAkhilesh Sanikop if (file_reader == nullptr) return 0;
84*09537850SAkhilesh Sanikop
85*09537850SAkhilesh Sanikop std::vector<uint8_t> buffer;
86*09537850SAkhilesh Sanikop int parsed_frames = 0;
87*09537850SAkhilesh Sanikop do {
88*09537850SAkhilesh Sanikop if (!file_reader->ReadTemporalUnit(&buffer, nullptr)) break;
89*09537850SAkhilesh Sanikop ParseObu(buffer.data(), buffer.size());
90*09537850SAkhilesh Sanikop if (++parsed_frames >= kMaxFrames) break;
91*09537850SAkhilesh Sanikop } while (!file_reader->IsEndOfFile());
92*09537850SAkhilesh Sanikop
93*09537850SAkhilesh Sanikop return 0;
94*09537850SAkhilesh Sanikop }
95