From a29b148557b0f04a5f4c5d0cfe7b005909c411d9 Mon Sep 17 00:00:00 2001 From: Henrik Lundin Date: Wed, 9 May 2018 14:56:08 +0200 Subject: [PATCH] Create a fuzzer for the Opus encoder The fuzzer is very simple. It only considers the default encoder configuration at this point. Bug: chromium:826914 Change-Id: Ifa248a1dba80efb231807750e40082ec5580636a Reviewed-on: https://webrtc-review.googlesource.com/75261 Commit-Queue: Henrik Lundin Reviewed-by: Karl Wiberg Cr-Commit-Position: refs/heads/master@{#23192} --- test/fuzzers/BUILD.gn | 13 +++++ test/fuzzers/audio_encoder_opus_fuzzer.cc | 64 +++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 test/fuzzers/audio_encoder_opus_fuzzer.cc diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn index 6160dfcb65..9059f2e14b 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -315,6 +315,19 @@ webrtc_fuzzer_test("audio_decoder_opus_redundant_fuzzer") { ] } +webrtc_fuzzer_test("audio_encoder_opus_fuzzer") { + sources = [ + "audio_encoder_opus_fuzzer.cc", + ] + deps = [ + ":fuzz_data_helper", + "../../api:array_view", + "../../api/audio_codecs/opus:audio_encoder_opus", + "../../rtc_base:checks", + "../../rtc_base:rtc_base_approved", + ] +} + webrtc_fuzzer_test("turn_unwrap_fuzzer") { sources = [ "turn_unwrap_fuzzer.cc", diff --git a/test/fuzzers/audio_encoder_opus_fuzzer.cc b/test/fuzzers/audio_encoder_opus_fuzzer.cc new file mode 100644 index 0000000000..50c285616b --- /dev/null +++ b/test/fuzzers/audio_encoder_opus_fuzzer.cc @@ -0,0 +1,64 @@ +/* + * 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 "api/array_view.h" +#include "api/audio_codecs/opus/audio_encoder_opus.h" +#include "rtc_base/buffer.h" +#include "rtc_base/checks.h" +#include "test/fuzzers/fuzz_data_helper.h" + +namespace webrtc { +namespace { + +// This function reads bytes from |data_view|, interprets them +// as RTP timestamp and input samples, and sends them for encoding. The process +// continues until no more data is available. +void FuzzAudioEncoder(rtc::ArrayView data_view, + AudioEncoder* encoder) { + test::FuzzDataHelper data(data_view); + const size_t block_size_samples = + encoder->SampleRateHz() / 100 * encoder->NumChannels(); + const size_t block_size_bytes = block_size_samples * sizeof(int16_t); + if (data_view.size() / block_size_bytes > 1000) { + // If the size of the fuzzer data is more than 1000 input blocks (i.e., more + // than 10 seconds), then don't fuzz at all for the fear of timing out. + return; + } + + rtc::BufferT input_aligned(block_size_samples); + rtc::Buffer encoded; + + // Each round in the loop below will need one block of samples + a 32-bit + // timestamp from the fuzzer input. + const size_t bytes_to_read = block_size_bytes + sizeof(uint32_t); + while (data.CanReadBytes(bytes_to_read)) { + const uint32_t timestamp = data.Read(); + auto byte_array = data.ReadByteArray(block_size_bytes); + // Align the data by copying to another array. + RTC_DCHECK_EQ(input_aligned.size() * sizeof(int16_t), + byte_array.size() * sizeof(uint8_t)); + memcpy(input_aligned.data(), byte_array.data(), byte_array.size()); + auto info = encoder->Encode(timestamp, input_aligned, &encoded); + } +} + +} // namespace + +void FuzzOneInput(const uint8_t* data, size_t size) { + AudioEncoderOpus::Config config; + config.frame_size_ms = 20; + RTC_CHECK(config.IsOk()); + constexpr int kPayloadType = 100; + std::unique_ptr enc = + AudioEncoderOpus::MakeAudioEncoder(config, kPayloadType); + FuzzAudioEncoder(rtc::ArrayView(data, size), enc.get()); +} + +} // namespace webrtc