Do up-front validation of multistream packets
Prevents the decoder from being out-of-sync on an invalid packet. Also returns OPUS_INVALID_PACKET on a corrupted FEC packet.
This commit is contained in:
parent
aee4d80576
commit
ed4632345e
3 changed files with 59 additions and 10 deletions
|
@ -355,7 +355,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
|
||||||
pcm_ptr[i] = 0;
|
pcm_ptr[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
RESTORE_STACK;
|
RESTORE_STACK;
|
||||||
return OPUS_INVALID_PACKET;
|
return OPUS_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pcm_ptr += silk_frame_size * st->channels;
|
pcm_ptr += silk_frame_size * st->channels;
|
||||||
|
@ -581,7 +581,7 @@ static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *siz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
|
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
|
||||||
int self_delimited, unsigned char *out_toc,
|
int self_delimited, unsigned char *out_toc,
|
||||||
const unsigned char *frames[48], opus_int16 size[48], int *payload_offset)
|
const unsigned char *frames[48], opus_int16 size[48], int *payload_offset)
|
||||||
{
|
{
|
||||||
|
@ -710,6 +710,9 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
|
||||||
size[count-1] = (opus_int16)last_size;
|
size[count-1] = (opus_int16)last_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (payload_offset)
|
||||||
|
*payload_offset = (int)(data-data0);
|
||||||
|
|
||||||
if (frames)
|
if (frames)
|
||||||
{
|
{
|
||||||
for (i=0;i<count;i++)
|
for (i=0;i<count;i++)
|
||||||
|
@ -722,9 +725,6 @@ static int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
|
||||||
if (out_toc)
|
if (out_toc)
|
||||||
*out_toc = toc;
|
*out_toc = toc;
|
||||||
|
|
||||||
if (payload_offset)
|
|
||||||
*payload_offset = (int)(data-data0);
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,6 +777,9 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
|
||||||
|
|
||||||
count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset);
|
count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset);
|
||||||
|
|
||||||
|
if (count<0)
|
||||||
|
return count;
|
||||||
|
|
||||||
data += offset;
|
data += offset;
|
||||||
|
|
||||||
if (decode_fec)
|
if (decode_fec)
|
||||||
|
@ -814,11 +817,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
|
||||||
return frame_size;
|
return frame_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tot_offset = 0;
|
tot_offset = offset;
|
||||||
if (count < 0)
|
|
||||||
return count;
|
|
||||||
|
|
||||||
tot_offset += offset;
|
|
||||||
|
|
||||||
if (count*packet_frame_size > frame_size)
|
if (count*packet_frame_size > frame_size)
|
||||||
return OPUS_BUFFER_TOO_SMALL;
|
return OPUS_BUFFER_TOO_SMALL;
|
||||||
|
|
|
@ -152,6 +152,37 @@ typedef void (*opus_copy_channel_out_func)(
|
||||||
int frame_size
|
int frame_size
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static int opus_multistream_packet_validate(const unsigned char *data,
|
||||||
|
opus_int32 len, int nb_streams)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
int i;
|
||||||
|
int count;
|
||||||
|
unsigned char toc;
|
||||||
|
opus_int16 size[48];
|
||||||
|
int offset;
|
||||||
|
int samples=0;
|
||||||
|
|
||||||
|
for (s=0;s<nb_streams;s++)
|
||||||
|
{
|
||||||
|
int tmp_samples;
|
||||||
|
if (len<=0)
|
||||||
|
return OPUS_INVALID_PACKET;
|
||||||
|
count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL, size, &offset);
|
||||||
|
if (count<0)
|
||||||
|
return count;
|
||||||
|
for (i=0;i<count;i++)
|
||||||
|
offset += size[i];
|
||||||
|
tmp_samples = opus_packet_get_nb_samples(data, offset, 48000);
|
||||||
|
if (s!=0 && samples != tmp_samples)
|
||||||
|
return OPUS_INVALID_PACKET;
|
||||||
|
samples = tmp_samples;
|
||||||
|
data += offset;
|
||||||
|
len -= offset;
|
||||||
|
}
|
||||||
|
return OPUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int opus_multistream_decode_native(
|
static int opus_multistream_decode_native(
|
||||||
OpusMSDecoder *st,
|
OpusMSDecoder *st,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
|
@ -183,9 +214,24 @@ static int opus_multistream_decode_native(
|
||||||
if (len==0)
|
if (len==0)
|
||||||
do_plc = 1;
|
do_plc = 1;
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
|
{
|
||||||
|
RESTORE_STACK;
|
||||||
return OPUS_BAD_ARG;
|
return OPUS_BAD_ARG;
|
||||||
|
}
|
||||||
if (!do_plc && len < 2*st->layout.nb_streams-1)
|
if (!do_plc && len < 2*st->layout.nb_streams-1)
|
||||||
|
{
|
||||||
|
RESTORE_STACK;
|
||||||
return OPUS_INVALID_PACKET;
|
return OPUS_INVALID_PACKET;
|
||||||
|
}
|
||||||
|
if (!do_plc)
|
||||||
|
{
|
||||||
|
int ret = opus_multistream_packet_validate(data, len, st->layout.nb_coupled_streams);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
RESTORE_STACK;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (s=0;s<st->layout.nb_streams;s++)
|
for (s=0;s<st->layout.nb_streams;s++)
|
||||||
{
|
{
|
||||||
OpusDecoder *dec;
|
OpusDecoder *dec;
|
||||||
|
|
|
@ -112,6 +112,10 @@ static inline int align(int i)
|
||||||
return (i+(int)sizeof(void *)-1)&-(int)sizeof(void *);
|
return (i+(int)sizeof(void *)-1)&-(int)sizeof(void *);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
|
||||||
|
int self_delimited, unsigned char *out_toc,
|
||||||
|
const unsigned char *frames[48], opus_int16 size[48], int *payload_offset);
|
||||||
|
|
||||||
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited);
|
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited);
|
||||||
|
|
||||||
#endif /* OPUS_PRIVATE_H */
|
#endif /* OPUS_PRIVATE_H */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue