| /* | |
| * Copyright (c) 2015 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 "test/fuzzers/audio_decoder_fuzzer.h" | |
| #include <limits> | |
| #include "absl/types/optional.h" | |
| #include "api/audio_codecs/audio_decoder.h" | |
| #include "modules/rtp_rtcp/source/byte_io.h" | |
| #include "rtc_base/checks.h" | |
| namespace webrtc { | |
| namespace { | |
| template <typename T, unsigned int B = sizeof(T)> | |
| bool ParseInt(const uint8_t** data, size_t* remaining_size, T* value) { | |
| static_assert(std::numeric_limits<T>::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<uint64_t, B>::ReadBigEndian(*data); | |
| *data += B; | |
| *remaining_size -= B; | |
| *value = static_cast<T>(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. 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, | |
| size_t max_decoded_bytes, | |
| int16_t* decoded) { | |
| const uint8_t* data_ptr = data; | |
| size_t remaining_size = size; | |
| size_t packet_len; | |
| constexpr size_t kMaxNumFuzzedPackets = 200; | |
| for (size_t num_packets = 0; num_packets < kMaxNumFuzzedPackets; | |
| ++num_packets) { | |
| if (!(ParseInt<size_t, 2>(&data_ptr, &remaining_size, &packet_len) && | |
| packet_len <= remaining_size)) { | |
| break; | |
| } | |
| AudioDecoder::SpeechType 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; | |
| } | |
| } | |
| } // namespace webrtc |