diff options
Diffstat (limited to 'third_party/libwebrtc/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc')
-rw-r--r-- | third_party/libwebrtc/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc new file mode 100644 index 0000000000..fdb4aa5f3c --- /dev/null +++ b/third_party/libwebrtc/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <memory> + +#include "api/rtp_packet_infos.h" +#include "modules/video_coding/frame_object.h" +#include "modules/video_coding/rtp_frame_reference_finder.h" + +namespace webrtc { + +namespace { +class DataReader { + public: + DataReader(const uint8_t* data, size_t size) : data_(data), size_(size) {} + + template <typename T> + void CopyTo(T* object) { + static_assert(std::is_pod<T>(), ""); + uint8_t* destination = reinterpret_cast<uint8_t*>(object); + size_t object_size = sizeof(T); + size_t num_bytes = std::min(size_ - offset_, object_size); + memcpy(destination, data_ + offset_, num_bytes); + offset_ += num_bytes; + + // If we did not have enough data, fill the rest with 0. + object_size -= num_bytes; + memset(destination + num_bytes, 0, object_size); + } + + template <typename T> + T GetNum() { + T res; + if (offset_ + sizeof(res) < size_) { + memcpy(&res, data_ + offset_, sizeof(res)); + offset_ += sizeof(res); + return res; + } + + offset_ = size_; + return T(0); + } + + bool MoreToRead() { return offset_ < size_; } + + private: + const uint8_t* data_; + size_t size_; + size_t offset_ = 0; +}; + +absl::optional<RTPVideoHeader::GenericDescriptorInfo> +GenerateGenericFrameDependencies(DataReader* reader) { + absl::optional<RTPVideoHeader::GenericDescriptorInfo> result; + uint8_t flags = reader->GetNum<uint8_t>(); + if (flags & 0b1000'0000) { + // i.e. with 50% chance there are no generic dependencies. + // in such case codec-specfic code path of the RtpFrameReferenceFinder will + // be validated. + return result; + } + + result.emplace(); + result->frame_id = reader->GetNum<int32_t>(); + result->spatial_index = (flags & 0b0111'0000) >> 4; + result->temporal_index = (flags & 0b0000'1110) >> 1; + + // Larger than supported by the RtpFrameReferenceFinder. + int num_diffs = (reader->GetNum<uint8_t>() % 16); + for (int i = 0; i < num_diffs; ++i) { + result->dependencies.push_back(result->frame_id - + (reader->GetNum<uint16_t>() % (1 << 14))); + } + + return result; +} +} // namespace + +void FuzzOneInput(const uint8_t* data, size_t size) { + DataReader reader(data, size); + RtpFrameReferenceFinder reference_finder; + + auto codec = static_cast<VideoCodecType>(reader.GetNum<uint8_t>() % 5); + + while (reader.MoreToRead()) { + uint16_t first_seq_num = reader.GetNum<uint16_t>(); + uint16_t last_seq_num = reader.GetNum<uint16_t>(); + bool marker_bit = reader.GetNum<uint8_t>(); + + RTPVideoHeader video_header; + switch (reader.GetNum<uint8_t>() % 3) { + case 0: + video_header.frame_type = VideoFrameType::kEmptyFrame; + break; + case 1: + video_header.frame_type = VideoFrameType::kVideoFrameKey; + break; + case 2: + video_header.frame_type = VideoFrameType::kVideoFrameDelta; + break; + } + + switch (codec) { + case kVideoCodecVP8: + reader.CopyTo( + &video_header.video_type_header.emplace<RTPVideoHeaderVP8>()); + break; + case kVideoCodecVP9: + reader.CopyTo( + &video_header.video_type_header.emplace<RTPVideoHeaderVP9>()); + break; + case kVideoCodecH264: + reader.CopyTo( + &video_header.video_type_header.emplace<RTPVideoHeaderH264>()); + break; + default: + break; + } + + video_header.generic = GenerateGenericFrameDependencies(&reader); + + // clang-format off + auto frame = std::make_unique<RtpFrameObject>( + first_seq_num, + last_seq_num, + marker_bit, + /*times_nacked=*/0, + /*first_packet_received_time=*/0, + /*last_packet_received_time=*/0, + /*rtp_timestamp=*/0, + /*ntp_time_ms=*/0, + VideoSendTiming(), + /*payload_type=*/0, + codec, + kVideoRotation_0, + VideoContentType::UNSPECIFIED, + video_header, + /*color_space=*/absl::nullopt, + RtpPacketInfos(), + EncodedImageBuffer::Create(/*size=*/0)); + // clang-format on + + reference_finder.ManageFrame(std::move(frame)); + } +} + +} // namespace webrtc |