From c4ed5f0b1a848b18cef751b967dd3c61a8e14ff9 Mon Sep 17 00:00:00 2001 From: Henrik Lundin Date: Wed, 16 Feb 2022 16:03:47 +0000 Subject: [PATCH] Adding fuzzer for G711/PCM u/A decoders and fixing a fuzzer problem Bug: chromium:1279775 Change-Id: I8cc3f5fe25b9e707e9d171251026bd5a8bad5da5 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/251844 Reviewed-by: Minyue Li Commit-Queue: Henrik Lundin Cr-Commit-Position: refs/heads/main@{#36036} --- .../codecs/g711/audio_decoder_pcm.cc | 16 ++++++- test/fuzzers/BUILD.gn | 8 ++++ test/fuzzers/audio_decoder_pcm_fuzzer.cc | 45 +++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 test/fuzzers/audio_decoder_pcm_fuzzer.cc diff --git a/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc b/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc index d580a0509b..46ac671b30 100644 --- a/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc +++ b/modules/audio_coding/codecs/g711/audio_decoder_pcm.cc @@ -40,8 +40,14 @@ int AudioDecoderPcmU::DecodeInternal(const uint8_t* encoded, int16_t* decoded, SpeechType* speech_type) { RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz); + // Adjust the encoded length down to ensure the same number of samples in each + // channel. + const size_t encoded_len_adjusted = + PacketDuration(encoded, encoded_len) * + Channels(); // 1 byte per sample per channel int16_t temp_type = 1; // Default is speech. - size_t ret = WebRtcG711_DecodeU(encoded, encoded_len, decoded, &temp_type); + size_t ret = + WebRtcG711_DecodeU(encoded, encoded_len_adjusted, decoded, &temp_type); *speech_type = ConvertSpeechType(temp_type); return static_cast(ret); } @@ -75,8 +81,14 @@ int AudioDecoderPcmA::DecodeInternal(const uint8_t* encoded, int16_t* decoded, SpeechType* speech_type) { RTC_DCHECK_EQ(SampleRateHz(), sample_rate_hz); + // Adjust the encoded length down to ensure the same number of samples in each + // channel. + const size_t encoded_len_adjusted = + PacketDuration(encoded, encoded_len) * + Channels(); // 1 byte per sample per channel int16_t temp_type = 1; // Default is speech. - size_t ret = WebRtcG711_DecodeA(encoded, encoded_len, decoded, &temp_type); + size_t ret = + WebRtcG711_DecodeA(encoded, encoded_len_adjusted, decoded, &temp_type); *speech_type = ConvertSpeechType(temp_type); return static_cast(ret); } diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn index cc8b312ab3..c71231453c 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -316,6 +316,14 @@ webrtc_fuzzer_test("audio_decoder_multiopus_fuzzer") { ] } +webrtc_fuzzer_test("audio_decoder_pcm_fuzzer") { + sources = [ "audio_decoder_pcm_fuzzer.cc" ] + deps = [ + ":audio_decoder_fuzzer", + "../../modules/audio_coding:g711", + ] +} + webrtc_fuzzer_test("audio_decoder_pcm16b_fuzzer") { sources = [ "audio_decoder_pcm16b_fuzzer.cc" ] deps = [ diff --git a/test/fuzzers/audio_decoder_pcm_fuzzer.cc b/test/fuzzers/audio_decoder_pcm_fuzzer.cc new file mode 100644 index 0000000000..dbfcaf9976 --- /dev/null +++ b/test/fuzzers/audio_decoder_pcm_fuzzer.cc @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 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 + +#include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h" +#include "test/fuzzers/audio_decoder_fuzzer.h" + +namespace webrtc { +void FuzzOneInput(const uint8_t* data, size_t size) { + if (size > 10000 || size < 2) { + return; + } + + const size_t num_channels = data[0] % 16 + 1; + + std::unique_ptr dec; + if (data[1] % 2) { + dec = std::make_unique(num_channels); + } else { + dec = std::make_unique(num_channels); + } + + // Two first bytes of the data are used. Move forward. + data += 2; + size -= 2; + + // Allocate a maximum output size of 100 ms. + const size_t allocated_ouput_size_samples = + dec->SampleRateHz() * num_channels / 10; + std::unique_ptr output = + std::make_unique(allocated_ouput_size_samples); + FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, dec.get(), + dec->SampleRateHz(), + allocated_ouput_size_samples * sizeof(int16_t), + output.get()); +} +} // namespace webrtc