xref: /aosp_15_r20/external/webrtc/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include <memory>
12 
13 #include "api/rtp_packet_infos.h"
14 #include "modules/video_coding/frame_object.h"
15 #include "modules/video_coding/rtp_frame_reference_finder.h"
16 
17 namespace webrtc {
18 
19 namespace {
20 class DataReader {
21  public:
DataReader(const uint8_t * data,size_t size)22   DataReader(const uint8_t* data, size_t size) : data_(data), size_(size) {}
23 
24   template <typename T>
CopyTo(T * object)25   void CopyTo(T* object) {
26     static_assert(std::is_pod<T>(), "");
27     uint8_t* destination = reinterpret_cast<uint8_t*>(object);
28     size_t object_size = sizeof(T);
29     size_t num_bytes = std::min(size_ - offset_, object_size);
30     memcpy(destination, data_ + offset_, num_bytes);
31     offset_ += num_bytes;
32 
33     // If we did not have enough data, fill the rest with 0.
34     object_size -= num_bytes;
35     memset(destination + num_bytes, 0, object_size);
36   }
37 
38   template <typename T>
GetNum()39   T GetNum() {
40     T res;
41     if (offset_ + sizeof(res) < size_) {
42       memcpy(&res, data_ + offset_, sizeof(res));
43       offset_ += sizeof(res);
44       return res;
45     }
46 
47     offset_ = size_;
48     return T(0);
49   }
50 
MoreToRead()51   bool MoreToRead() { return offset_ < size_; }
52 
53  private:
54   const uint8_t* data_;
55   size_t size_;
56   size_t offset_ = 0;
57 };
58 
59 absl::optional<RTPVideoHeader::GenericDescriptorInfo>
GenerateGenericFrameDependencies(DataReader * reader)60 GenerateGenericFrameDependencies(DataReader* reader) {
61   absl::optional<RTPVideoHeader::GenericDescriptorInfo> result;
62   uint8_t flags = reader->GetNum<uint8_t>();
63   if (flags & 0b1000'0000) {
64     // i.e. with 50% chance there are no generic dependencies.
65     // in such case codec-specfic code path of the RtpFrameReferenceFinder will
66     // be validated.
67     return result;
68   }
69 
70   result.emplace();
71   result->frame_id = reader->GetNum<int32_t>();
72   result->spatial_index = (flags & 0b0111'0000) >> 4;
73   result->temporal_index = (flags & 0b0000'1110) >> 1;
74 
75   // Larger than supported by the RtpFrameReferenceFinder.
76   int num_diffs = (reader->GetNum<uint8_t>() % 16);
77   for (int i = 0; i < num_diffs; ++i) {
78     result->dependencies.push_back(result->frame_id -
79                                    (reader->GetNum<uint16_t>() % (1 << 14)));
80   }
81 
82   return result;
83 }
84 }  // namespace
85 
FuzzOneInput(const uint8_t * data,size_t size)86 void FuzzOneInput(const uint8_t* data, size_t size) {
87   DataReader reader(data, size);
88   RtpFrameReferenceFinder reference_finder;
89 
90   auto codec = static_cast<VideoCodecType>(reader.GetNum<uint8_t>() % 5);
91 
92   while (reader.MoreToRead()) {
93     uint16_t first_seq_num = reader.GetNum<uint16_t>();
94     uint16_t last_seq_num = reader.GetNum<uint16_t>();
95     bool marker_bit = reader.GetNum<uint8_t>();
96 
97     RTPVideoHeader video_header;
98     switch (reader.GetNum<uint8_t>() % 3) {
99       case 0:
100         video_header.frame_type = VideoFrameType::kEmptyFrame;
101         break;
102       case 1:
103         video_header.frame_type = VideoFrameType::kVideoFrameKey;
104         break;
105       case 2:
106         video_header.frame_type = VideoFrameType::kVideoFrameDelta;
107         break;
108     }
109 
110     switch (codec) {
111       case kVideoCodecVP8:
112         reader.CopyTo(
113             &video_header.video_type_header.emplace<RTPVideoHeaderVP8>());
114         break;
115       case kVideoCodecVP9:
116         reader.CopyTo(
117             &video_header.video_type_header.emplace<RTPVideoHeaderVP9>());
118         break;
119       case kVideoCodecH264:
120         reader.CopyTo(
121             &video_header.video_type_header.emplace<RTPVideoHeaderH264>());
122         break;
123       default:
124         break;
125     }
126 
127     video_header.generic = GenerateGenericFrameDependencies(&reader);
128 
129     // clang-format off
130     auto frame = std::make_unique<RtpFrameObject>(
131         first_seq_num,
132         last_seq_num,
133         marker_bit,
134         /*times_nacked=*/0,
135         /*first_packet_received_time=*/0,
136         /*last_packet_received_time=*/0,
137         /*rtp_timestamp=*/0,
138         /*ntp_time_ms=*/0,
139         VideoSendTiming(),
140         /*payload_type=*/0,
141         codec,
142         kVideoRotation_0,
143         VideoContentType::UNSPECIFIED,
144         video_header,
145         /*color_space=*/absl::nullopt,
146         RtpPacketInfos(),
147         EncodedImageBuffer::Create(/*size=*/0));
148     // clang-format on
149 
150     reference_finder.ManageFrame(std::move(frame));
151   }
152 }
153 
154 }  // namespace webrtc
155