From fd2be2718d984792b949b186ff11ceaf256723d0 Mon Sep 17 00:00:00 2001 From: "henrik.lundin" Date: Tue, 9 Feb 2016 00:00:23 -0800 Subject: [PATCH] Fuzzer tests for AudioDecoder's DecodeRedundant and IncomingPacket This CL adds new fuzzer tests for the DecodeRedundant and IncomingPacket methods of AudioDecoder. In practice, only Opus has DecodeRedundant, and only iSAC has IncomingPacket. Did some minor work to generalize the helper function reading values from the fuzzed input. BUG=webrtc:5306 R=pbos@webrtc.org NOTRY=true Review URL: https://codereview.webrtc.org/1607173003 Cr-Commit-Position: refs/heads/master@{#11533} --- webrtc/test/fuzzers/BUILD.gn | 20 +++++ webrtc/test/fuzzers/audio_decoder_fuzzer.cc | 76 +++++++++++++++---- webrtc/test/fuzzers/audio_decoder_fuzzer.h | 11 ++- .../test/fuzzers/audio_decoder_ilbc_fuzzer.cc | 3 +- .../test/fuzzers/audio_decoder_isac_fuzzer.cc | 3 +- ...dio_decoder_isac_incoming_packet_fuzzer.cc | 19 +++++ .../fuzzers/audio_decoder_isacfix_fuzzer.cc | 3 +- .../test/fuzzers/audio_decoder_opus_fuzzer.cc | 3 +- .../audio_decoder_opus_redundant_fuzzer.cc | 24 ++++++ 9 files changed, 144 insertions(+), 18 deletions(-) create mode 100644 webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc create mode 100644 webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc diff --git a/webrtc/test/fuzzers/BUILD.gn b/webrtc/test/fuzzers/BUILD.gn index 6a43548ec9..6591f6417f 100644 --- a/webrtc/test/fuzzers/BUILD.gn +++ b/webrtc/test/fuzzers/BUILD.gn @@ -94,6 +94,16 @@ webrtc_fuzzer_test("audio_decoder_isac_fuzzer") { ] } +webrtc_fuzzer_test("audio_decoder_isac_incoming_packet_fuzzer") { + sources = [ + "audio_decoder_isac_incoming_packet_fuzzer.cc", + ] + deps = [ + ":audio_decoder_fuzzer", + "../../modules/audio_coding:isac", + ] +} + webrtc_fuzzer_test("audio_decoder_isacfix_fuzzer") { sources = [ "audio_decoder_isacfix_fuzzer.cc", @@ -113,3 +123,13 @@ webrtc_fuzzer_test("audio_decoder_opus_fuzzer") { "../../modules/audio_coding:webrtc_opus", ] } + +webrtc_fuzzer_test("audio_decoder_opus_redundant_fuzzer") { + sources = [ + "audio_decoder_opus_redundant_fuzzer.cc", + ] + deps = [ + ":audio_decoder_fuzzer", + "../../modules/audio_coding:webrtc_opus", + ] +} diff --git a/webrtc/test/fuzzers/audio_decoder_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_fuzzer.cc index fb5adb6cd8..54c56ad62a 100644 --- a/webrtc/test/fuzzers/audio_decoder_fuzzer.cc +++ b/webrtc/test/fuzzers/audio_decoder_fuzzer.cc @@ -10,23 +10,39 @@ #include "webrtc/test/fuzzers/audio_decoder_fuzzer.h" +#include + #include "webrtc/base/checks.h" +#include "webrtc/base/optional.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" namespace webrtc { namespace { -size_t PacketSizeFromTwoBytes(const uint8_t* data, size_t size) { - if (size < 2) - return 0; - return static_cast((data[0] << 8) + data[1]); +template +bool ParseInt(const uint8_t** data, size_t* remaining_size, T* value) { + static_assert(std::numeric_limits::is_integer, "Type must be an integer."); + static_assert(sizeof(T) <= sizeof(uint64_t), + "Cannot read wider than uint64_t."); + static_assert(B <= sizeof(T), "T must be at least B bytes wide."); + if (B > *remaining_size) + return false; + uint64_t val = ByteReader::ReadBigEndian(*data); + *data += B; + *remaining_size -= B; + *value = static_cast(val); + return true; } } // namespace // This function reads two bytes from the beginning of |data|, interprets them // as the first packet length, and reads this many bytes if available. The // payload is inserted into the decoder, and the process continues until no more -// data is available. -void FuzzAudioDecoder(const uint8_t* data, +// data is available. Either AudioDecoder::Decode or +// AudioDecoder::DecodeRedundant is used, depending on the value of +// |decode_type|. +void FuzzAudioDecoder(DecoderFunctionType decode_type, + const uint8_t* data, size_t size, AudioDecoder* decoder, int sample_rate_hz, @@ -34,16 +50,50 @@ void FuzzAudioDecoder(const uint8_t* data, int16_t* decoded) { const uint8_t* data_ptr = data; size_t remaining_size = size; - size_t packet_len = PacketSizeFromTwoBytes(data_ptr, remaining_size); - while (packet_len != 0 && packet_len <= remaining_size - 2) { - data_ptr += 2; - remaining_size -= 2; + size_t packet_len; + while (ParseInt(&data_ptr, &remaining_size, &packet_len) && + packet_len <= remaining_size) { AudioDecoder::SpeechType speech_type; - decoder->Decode(data_ptr, packet_len, sample_rate_hz, max_decoded_bytes, - decoded, &speech_type); + switch (decode_type) { + case DecoderFunctionType::kNormalDecode: + decoder->Decode(data_ptr, packet_len, sample_rate_hz, max_decoded_bytes, + decoded, &speech_type); + break; + case DecoderFunctionType::kRedundantDecode: + decoder->DecodeRedundant(data_ptr, packet_len, sample_rate_hz, + max_decoded_bytes, decoded, &speech_type); + break; + } + data_ptr += packet_len; + remaining_size -= packet_len; + } +} + +// This function is similar to FuzzAudioDecoder, but also reads fuzzed data into +// RTP header values. The fuzzed data and values are sent to the decoder's +// IncomingPacket method. +void FuzzAudioDecoderIncomingPacket(const uint8_t* data, + size_t size, + AudioDecoder* decoder) { + const uint8_t* data_ptr = data; + size_t remaining_size = size; + size_t packet_len; + while (ParseInt(&data_ptr, &remaining_size, &packet_len)) { + uint16_t rtp_sequence_number; + if (!ParseInt(&data_ptr, &remaining_size, &rtp_sequence_number)) + break; + uint32_t rtp_timestamp; + if (!ParseInt(&data_ptr, &remaining_size, &rtp_timestamp)) + break; + uint32_t arrival_timestamp; + if (!ParseInt(&data_ptr, &remaining_size, &arrival_timestamp)) + break; + if (remaining_size < packet_len) + break; + decoder->IncomingPacket(data_ptr, packet_len, rtp_sequence_number, + rtp_timestamp, arrival_timestamp); data_ptr += packet_len; remaining_size -= packet_len; - packet_len = PacketSizeFromTwoBytes(data_ptr, remaining_size); } } } // namespace webrtc diff --git a/webrtc/test/fuzzers/audio_decoder_fuzzer.h b/webrtc/test/fuzzers/audio_decoder_fuzzer.h index cdd8574300..29179eb9f9 100644 --- a/webrtc/test/fuzzers/audio_decoder_fuzzer.h +++ b/webrtc/test/fuzzers/audio_decoder_fuzzer.h @@ -19,13 +19,22 @@ namespace webrtc { class AudioDecoder; -void FuzzAudioDecoder(const uint8_t* data, +enum class DecoderFunctionType { + kNormalDecode, + kRedundantDecode, +}; + +void FuzzAudioDecoder(DecoderFunctionType decode_type, + const uint8_t* data, size_t size, AudioDecoder* decoder, int sample_rate_hz, size_t max_decoded_bytes, int16_t* decoded); +void FuzzAudioDecoderIncomingPacket(const uint8_t* data, + size_t size, + AudioDecoder* decoder); } // namespace webrtc #endif // WEBRTC_TEST_FUZZERS_AUDIO_DECODER_FUZZER_H_ diff --git a/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc index d2a87f0cb6..b3bc4349d1 100644 --- a/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc +++ b/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc @@ -17,6 +17,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) { static const int kSampleRateHz = 8000; static const size_t kAllocatedOuputSizeSamples = kSampleRateHz / 10; int16_t output[kAllocatedOuputSizeSamples]; - FuzzAudioDecoder(data, size, &dec, kSampleRateHz, sizeof(output), output); + FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec, + kSampleRateHz, sizeof(output), output); } } // namespace webrtc diff --git a/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc index 984cfda398..ba6e7f0cb8 100644 --- a/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc +++ b/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc @@ -17,6 +17,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) { const int sample_rate_hz = size % 2 == 0 ? 16000 : 32000; // 16 or 32 kHz. static const size_t kAllocatedOuputSizeSamples = 32000 / 10; // 100 ms. int16_t output[kAllocatedOuputSizeSamples]; - FuzzAudioDecoder(data, size, &dec, sample_rate_hz, sizeof(output), output); + FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec, + sample_rate_hz, sizeof(output), output); } } // namespace webrtc diff --git a/webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc new file mode 100644 index 0000000000..7a239f0361 --- /dev/null +++ b/webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc @@ -0,0 +1,19 @@ +/* + * 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 "webrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h" +#include "webrtc/test/fuzzers/audio_decoder_fuzzer.h" + +namespace webrtc { +void FuzzOneInput(const uint8_t* data, size_t size) { + AudioDecoderIsac dec(nullptr); + FuzzAudioDecoderIncomingPacket(data, size, &dec); +} +} // namespace webrtc diff --git a/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc index 83fb8c2d62..c930aa8fba 100644 --- a/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc +++ b/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc @@ -17,6 +17,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) { static const int kSampleRateHz = 16000; static const size_t kAllocatedOuputSizeSamples = 16000 / 10; // 100 ms. int16_t output[kAllocatedOuputSizeSamples]; - FuzzAudioDecoder(data, size, &dec, kSampleRateHz, sizeof(output), output); + FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec, + kSampleRateHz, sizeof(output), output); } } // namespace webrtc diff --git a/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc index 3d70ec507d..ee9f591aca 100644 --- a/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc +++ b/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc @@ -18,6 +18,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) { const int kSampleRateHz = 48000; const size_t kAllocatedOuputSizeSamples = kSampleRateHz / 10; // 100 ms. int16_t output[kAllocatedOuputSizeSamples]; - FuzzAudioDecoder(data, size, &dec, kSampleRateHz, sizeof(output), output); + FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec, + kSampleRateHz, sizeof(output), output); } } // namespace webrtc diff --git a/webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc new file mode 100644 index 0000000000..48b8b25da3 --- /dev/null +++ b/webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc @@ -0,0 +1,24 @@ +/* + * 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 "webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h" +#include "webrtc/test/fuzzers/audio_decoder_fuzzer.h" + +namespace webrtc { +void FuzzOneInput(const uint8_t* data, size_t size) { + const size_t channels = (size % 2) + 1; // 1 or 2 channels. + AudioDecoderOpus dec(channels); + const int kSampleRateHz = 48000; + const size_t kAllocatedOuputSizeSamples = kSampleRateHz / 10; // 100 ms. + int16_t output[kAllocatedOuputSizeSamples]; + FuzzAudioDecoder(DecoderFunctionType::kRedundantDecode, data, size, &dec, + kSampleRateHz, sizeof(output), output); +} +} // namespace webrtc