Index: webrtc/test/fuzzers/audio_processing_fuzzer.cc |
diff --git a/webrtc/test/fuzzers/audio_processing_fuzzer.cc b/webrtc/test/fuzzers/audio_processing_fuzzer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a8853fafb21aed8a4f5d2b9ccc2afd0733004435 |
--- /dev/null |
+++ b/webrtc/test/fuzzers/audio_processing_fuzzer.cc |
@@ -0,0 +1,148 @@ |
+/* |
+ * Copyright (c) 2017 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 "webrtc/test/fuzzers/audio_processing_fuzzer.h" |
+ |
+#include <algorithm> |
+#include <array> |
+#include <cmath> |
+ |
+#include "webrtc/base/checks.h" |
+#include "webrtc/modules/audio_processing/include/audio_processing.h" |
+#include "webrtc/modules/include/module_common_types.h" |
+ |
+namespace webrtc { |
+namespace { |
+size_t ByteToNativeRate(uint8_t data) { |
+ using Rate = AudioProcessing::NativeRate; |
+ switch (data % 4) { |
+ case 0: |
+ // Breaks AEC3. |
+ // return static_cast<size_t>(Rate::kSampleRate8kHz); |
+ case 1: |
+ return static_cast<size_t>(Rate::kSampleRate16kHz); |
+ case 2: |
+ return static_cast<size_t>(Rate::kSampleRate32kHz); |
+ default: |
+ return static_cast<size_t>(Rate::kSampleRate48kHz); |
+ } |
+} |
+} // namespace |
+ |
+rtc::Optional<bool> ParseBool(const uint8_t** data, size_t* remaining_size) { |
+ if (1 > *remaining_size) { |
+ return rtc::Optional<bool>(); |
+ } |
+ auto res = rtc::Optional<bool>((**data) % 2); |
+ *data += 1; |
+ *remaining_size -= 1; |
+ return res; |
+} |
+ |
+rtc::Optional<uint8_t> ParseByte(const uint8_t** data, size_t* remaining_size) { |
+ if (1 > *remaining_size) { |
+ return rtc::Optional<uint8_t>(); |
+ } |
+ auto res = rtc::Optional<uint8_t>((**data)); |
+ *data += 1; |
+ *remaining_size -= 1; |
+ return res; |
+} |
+ |
+template <class T> |
+bool ParseSequence(size_t size, |
hlundin-webrtc
2017/06/16 14:48:27
ParseSequence and FuzzAudioProcessingFixed are onl
aleloi
2017/06/19 11:31:42
Done.
|
+ const uint8_t** data, |
+ size_t* remaining_size, |
+ T* result_data) { |
+ const size_t data_size = sizeof(float) * size; |
hlundin-webrtc
2017/06/16 14:48:27
Shouldn't it be sizeof(T)?
hlundin-webrtc
2017/06/16 14:48:27
data_size_bytes
aleloi
2017/06/19 11:31:42
Thanks, missed that!
aleloi
2017/06/19 11:31:42
Done.
|
+ if (data_size > *remaining_size) { |
+ return false; |
+ } |
+ |
+ std::copy(*data, *data + data_size, reinterpret_cast<uint8_t*>(result_data)); |
+ |
+ *data += data_size; |
+ *remaining_size -= data_size; |
+ return true; |
+} |
+ |
+void FuzzAudioProcessingFixed(const uint8_t* data, |
hlundin-webrtc
2017/06/16 14:48:26
Why is it called Fixed?
aleloi
2017/06/19 11:31:43
In another version, I had FuzzFixed and FuzzFloati
|
+ size_t size, |
+ bool is_float, |
+ AudioProcessing* apm) { |
+ AudioFrame fixed_frame; |
+ std::array<float, 480> float_frame; |
+ float* const first_channel = float_frame.begin(); |
+ |
+ while (size > 0) { |
+ // Decide input/output rate for this iteration. |
+ const auto input_rate_byte = ParseByte(&data, &size); |
+ const auto output_rate_byte = ParseByte(&data, &size); |
+ if (!input_rate_byte || !output_rate_byte) { |
+ return; |
+ } |
+ const auto input_rate = ByteToNativeRate(*input_rate_byte); |
hlundin-webrtc
2017/06/16 14:48:27
{input, output}_rate_hz
aleloi
2017/06/19 11:31:42
Done.
|
+ const auto output_rate = ByteToNativeRate(*output_rate_byte); |
+ |
+ const size_t samples_per_input_channel = |
hlundin-webrtc
2017/06/16 14:48:27
This is the number of samples per millisecond. Is
aleloi
2017/06/19 11:31:42
Wow, that actually led to the fix-point interface
|
+ rtc::CheckedDivExact(input_rate, 1000ul); |
+ fixed_frame.samples_per_channel_ = samples_per_input_channel; |
+ fixed_frame.sample_rate_hz_ = input_rate; |
+ |
+ // Two channels breaks AEC3. |
+ fixed_frame.num_channels_ = 1; |
+ |
+ // Fill the arrays with audio samples from the data. |
+ if (is_float) { |
+ if (!ParseSequence(samples_per_input_channel, &data, &size, |
+ float_frame.begin())) { |
hlundin-webrtc
2017/06/16 14:48:27
I would have expected &float_frame[0], but I assum
aleloi
2017/06/19 11:31:42
I started thinking about whether this is safe and
|
+ break; |
hlundin-webrtc
2017/06/16 14:48:26
Why not simply return?
aleloi
2017/06/19 11:31:42
Done.
|
+ } |
+ } else if (!ParseSequence(samples_per_input_channel, &data, &size, |
+ fixed_frame.mutable_data())) { |
+ break; |
hlundin-webrtc
2017/06/16 14:48:27
return?
aleloi
2017/06/19 11:31:42
Done.
|
+ } |
+ |
+ // Filter obviously wrong values like inf/nan and values that will |
+ // lead to inf/nan in calculations. 1e6 leads to DCHECKS failing. |
+ for (auto& x : float_frame) { |
+ if (!std::isnormal(x) || std::abs(x) > 1e5) { |
+ x = 0; |
+ } |
+ } |
+ |
+ // Make the APM call depending on capture/render mode and float / |
+ // fix interface. |
+ const auto is_capture = ParseBool(&data, &size); |
+ if (!is_capture) { |
+ break; |
hlundin-webrtc
2017/06/16 14:48:27
return?
aleloi
2017/06/19 11:31:42
Done.
|
+ } |
+ if (*is_capture) { |
+ is_float |
+ ? (apm->ProcessStream(&first_channel, StreamConfig(input_rate, 1), |
+ StreamConfig(output_rate, 1), &first_channel)) |
+ : (apm->ProcessStream(&fixed_frame)); |
+ |
+ } else { |
+ is_float ? (apm->ProcessReverseStream( |
+ &first_channel, StreamConfig(input_rate, 1), |
+ StreamConfig(output_rate, 1), &first_channel)) |
+ : (apm->ProcessReverseStream(&fixed_frame)); |
+ } |
+ } |
+} |
+ |
+void FuzzAudioProcessing(const uint8_t* data, |
+ size_t size, |
+ std::unique_ptr<AudioProcessing> apm) { |
+ FuzzAudioProcessingFixed(data, size, false, apm.get()); |
hlundin-webrtc
2017/06/16 14:48:27
Why not let fixed/float also depend on the fuzzer
aleloi
2017/06/19 11:31:42
Done.
|
+ FuzzAudioProcessingFixed(data, size, true, apm.get()); |
+} |
+} // namespace webrtc |