diff options
Diffstat (limited to 'third_party/libwebrtc/test/fuzzers/neteq_rtp_fuzzer.cc')
-rw-r--r-- | third_party/libwebrtc/test/fuzzers/neteq_rtp_fuzzer.cc | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/fuzzers/neteq_rtp_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/neteq_rtp_fuzzer.cc new file mode 100644 index 0000000000..348c84f040 --- /dev/null +++ b/third_party/libwebrtc/test/fuzzers/neteq_rtp_fuzzer.cc @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016 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 <algorithm> +#include <cmath> +#include <cstring> +#include <memory> +#include <vector> + +#include "api/array_view.h" +#include "api/audio_codecs/builtin_audio_decoder_factory.h" +#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h" +#include "modules/audio_coding/neteq/tools/audio_checksum.h" +#include "modules/audio_coding/neteq/tools/encode_neteq_input.h" +#include "modules/audio_coding/neteq/tools/neteq_test.h" +#include "modules/rtp_rtcp/source/byte_io.h" + +namespace webrtc { +namespace test { +namespace { +constexpr int kPayloadType = 95; + +class SineGenerator : public EncodeNetEqInput::Generator { + public: + explicit SineGenerator(int sample_rate_hz) + : sample_rate_hz_(sample_rate_hz) {} + + rtc::ArrayView<const int16_t> Generate(size_t num_samples) override { + if (samples_.size() < num_samples) { + samples_.resize(num_samples); + } + + rtc::ArrayView<int16_t> output(samples_.data(), num_samples); + for (auto& x : output) { + x = static_cast<int16_t>(2000.0 * std::sin(phase_)); + phase_ += 2 * kPi * kFreqHz / sample_rate_hz_; + } + return output; + } + + private: + static constexpr int kFreqHz = 300; // The sinewave frequency. + const int sample_rate_hz_; + const double kPi = std::acos(-1); + std::vector<int16_t> samples_; + double phase_ = 0.0; +}; + +class FuzzRtpInput : public NetEqInput { + public: + explicit FuzzRtpInput(rtc::ArrayView<const uint8_t> data) : data_(data) { + AudioEncoderPcm16B::Config config; + config.payload_type = kPayloadType; + config.sample_rate_hz = 32000; + std::unique_ptr<AudioEncoder> encoder(new AudioEncoderPcm16B(config)); + std::unique_ptr<EncodeNetEqInput::Generator> generator( + new SineGenerator(config.sample_rate_hz)); + input_.reset(new EncodeNetEqInput(std::move(generator), std::move(encoder), + std::numeric_limits<int64_t>::max())); + packet_ = input_->PopPacket(); + FuzzHeader(); + MaybeFuzzPayload(); + } + + absl::optional<int64_t> NextPacketTime() const override { + return packet_->time_ms; + } + + absl::optional<int64_t> NextOutputEventTime() const override { + return input_->NextOutputEventTime(); + } + + std::unique_ptr<PacketData> PopPacket() override { + RTC_DCHECK(packet_); + std::unique_ptr<PacketData> packet_to_return = std::move(packet_); + packet_ = input_->PopPacket(); + FuzzHeader(); + MaybeFuzzPayload(); + return packet_to_return; + } + + void AdvanceOutputEvent() override { return input_->AdvanceOutputEvent(); } + + bool ended() const override { return ended_; } + + absl::optional<RTPHeader> NextHeader() const override { + RTC_DCHECK(packet_); + return packet_->header; + } + + private: + void FuzzHeader() { + constexpr size_t kNumBytesToFuzz = 11; + if (data_ix_ + kNumBytesToFuzz > data_.size()) { + ended_ = true; + return; + } + RTC_DCHECK(packet_); + const size_t start_ix = data_ix_; + packet_->header.payloadType = + ByteReader<uint8_t>::ReadLittleEndian(&data_[data_ix_]); + packet_->header.payloadType &= 0x7F; + data_ix_ += sizeof(uint8_t); + packet_->header.sequenceNumber = + ByteReader<uint16_t>::ReadLittleEndian(&data_[data_ix_]); + data_ix_ += sizeof(uint16_t); + packet_->header.timestamp = + ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]); + data_ix_ += sizeof(uint32_t); + packet_->header.ssrc = + ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]); + data_ix_ += sizeof(uint32_t); + RTC_CHECK_EQ(data_ix_ - start_ix, kNumBytesToFuzz); + } + + void MaybeFuzzPayload() { + // Read one byte of fuzz data to determine how many payload bytes to fuzz. + if (data_ix_ + 1 > data_.size()) { + ended_ = true; + return; + } + size_t bytes_to_fuzz = data_[data_ix_++]; + + // Restrict number of bytes to fuzz to 16; a reasonably low number enough to + // cover a few RED headers. Also don't write outside the payload length. + bytes_to_fuzz = std::min(bytes_to_fuzz % 16, packet_->payload.size()); + + if (bytes_to_fuzz == 0) + return; + + if (data_ix_ + bytes_to_fuzz > data_.size()) { + ended_ = true; + return; + } + + std::memcpy(packet_->payload.data(), &data_[data_ix_], bytes_to_fuzz); + data_ix_ += bytes_to_fuzz; + } + + bool ended_ = false; + rtc::ArrayView<const uint8_t> data_; + size_t data_ix_ = 0; + std::unique_ptr<EncodeNetEqInput> input_; + std::unique_ptr<PacketData> packet_; +}; +} // namespace + +void FuzzOneInputTest(const uint8_t* data, size_t size) { + std::unique_ptr<FuzzRtpInput> input( + new FuzzRtpInput(rtc::ArrayView<const uint8_t>(data, size))); + std::unique_ptr<AudioChecksum> output(new AudioChecksum); + NetEqTest::Callbacks callbacks; + NetEq::Config config; + auto codecs = NetEqTest::StandardDecoderMap(); + // kPayloadType is the payload type that will be used for encoding. Verify + // that it is included in the standard decoder map, and that it points to the + // expected decoder type. + const auto it = codecs.find(kPayloadType); + RTC_CHECK(it != codecs.end()); + RTC_CHECK(it->second == SdpAudioFormat("L16", 32000, 1)); + + NetEqTest test(config, CreateBuiltinAudioDecoderFactory(), codecs, + /*text_log=*/nullptr, /*neteq_factory=*/nullptr, + std::move(input), std::move(output), callbacks); + test.Run(); +} + +} // namespace test + +void FuzzOneInput(const uint8_t* data, size_t size) { + if (size > 70000) { + return; + } + test::FuzzOneInputTest(data, size); +} + +} // namespace webrtc |