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}
This commit is contained in:
committed by
Commit bot
parent
7ae5e52d0a
commit
fd2be2718d
@ -10,23 +10,39 @@
|
||||
|
||||
#include "webrtc/test/fuzzers/audio_decoder_fuzzer.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#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<size_t>((data[0] << 8) + data[1]);
|
||||
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.
|
||||
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<size_t, 2>(&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<size_t, 2>(&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
|
||||
|
||||
Reference in New Issue
Block a user