diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn index 7e81d56452..ce559359a6 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -526,6 +526,24 @@ webrtc_fuzzer_test("aec3_config_json_fuzzer") { seed_corpus = "corpora/aec3-config-json-corpus" } +webrtc_fuzzer_test("aec3_fuzzer") { + defines = [] + if (apm_debug_dump) { + defines += [ "WEBRTC_APM_DEBUG_DUMP=1" ] + } else { + defines += [ "WEBRTC_APM_DEBUG_DUMP=0" ] + } + sources = [ + "aec3_fuzzer.cc", + ] + deps = [ + ":fuzz_data_helper", + "../../modules/audio_processing:audio_buffer", + "../../modules/audio_processing/aec3", + "//modules/audio_processing:api", + ] +} + webrtc_fuzzer_test("comfort_noise_decoder_fuzzer") { sources = [ "comfort_noise_decoder_fuzzer.cc", diff --git a/test/fuzzers/aec3_fuzzer.cc b/test/fuzzers/aec3_fuzzer.cc new file mode 100644 index 0000000000..a9b4a9ea94 --- /dev/null +++ b/test/fuzzers/aec3_fuzzer.cc @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 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 "modules/audio_processing/aec3/echo_canceller3.h" +#include "modules/audio_processing/audio_buffer.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "test/fuzzers/fuzz_data_helper.h" + +namespace webrtc { +namespace { +using SampleRate = ::webrtc::AudioProcessing::NativeRate; + +void PrepareAudioBuffer(int sample_rate_hz, + test::FuzzDataHelper* fuzz_data, + AudioBuffer* buffer) { + float* const* channels = buffer->channels_f(); + for (size_t i = 0; i < buffer->num_channels(); ++i) { + for (size_t j = 0; j < buffer->num_frames(); ++j) { + channels[i][j] = + static_cast(fuzz_data->ReadOrDefaultValue(0)); + } + } + if (sample_rate_hz == 32000 || sample_rate_hz == 48000) { + buffer->SplitIntoFrequencyBands(); + } +} + +} // namespace + +void FuzzOneInput(const uint8_t* data, size_t size) { + if (size > 200000) { + return; + } + + test::FuzzDataHelper fuzz_data(rtc::ArrayView(data, size)); + + constexpr int kSampleRates[] = {16000, 32000, 48000}; + const int sample_rate_hz = + static_cast(fuzz_data.SelectOneOf(kSampleRates)); + + constexpr int kMaxNumChannels = 9; + const size_t num_render_channels = + 1 + fuzz_data.ReadOrDefaultValue(0) % (kMaxNumChannels - 1); + const size_t num_capture_channels = + 1 + fuzz_data.ReadOrDefaultValue(0) % (kMaxNumChannels - 1); + + EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz, + num_render_channels, num_capture_channels); + + AudioBuffer capture_audio(sample_rate_hz, num_capture_channels, + sample_rate_hz, num_capture_channels, + sample_rate_hz, num_capture_channels); + AudioBuffer render_audio(sample_rate_hz, num_render_channels, sample_rate_hz, + num_render_channels, sample_rate_hz, + num_render_channels); + + // Fuzz frames while there is still fuzzer data. + while (fuzz_data.BytesLeft() > 0) { + bool is_capture = fuzz_data.ReadOrDefaultValue(true); + bool level_changed = fuzz_data.ReadOrDefaultValue(true); + if (is_capture) { + PrepareAudioBuffer(sample_rate_hz, &fuzz_data, &capture_audio); + aec3.ProcessCapture(&capture_audio, level_changed); + } else { + PrepareAudioBuffer(sample_rate_hz, &fuzz_data, &render_audio); + aec3.AnalyzeRender(&render_audio); + } + } +} +} // namespace webrtc