Prevent reading outside iSAC bitstream, if the stream is corrupted.

BUG=chrome_373312(#24)
R=henrik.lundin@webrtc.org, tina.legrand@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/20089004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7379 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
turaj@webrtc.org
2014-10-07 00:21:02 +00:00
parent 8234fa6f0e
commit 532ed43e85
5 changed files with 75 additions and 33 deletions

View File

@ -350,6 +350,7 @@ extern "C" {
*
* Input:
* - encoded : Encoded bitstream
* - encoded_len_bytes : Length of the bitstream in bytes.
*
* Output:
* - frameLength : Length of frame in packet (in samples)
@ -357,6 +358,7 @@ extern "C" {
*/
int16_t WebRtcIsacfix_ReadFrameLen(const int16_t* encoded,
int encoded_len_bytes,
int16_t* frameLength);
/****************************************************************************
@ -599,6 +601,7 @@ extern "C" {
*
* Input:
* - encoded : Encoded bitstream
* - encoded_len_bytes : Length of the bitstream in bytes.
*
* Output:
* - rateIndex : Bandwidth estimate in bitstream
@ -606,6 +609,7 @@ extern "C" {
*/
int16_t WebRtcIsacfix_ReadBwIndex(const int16_t* encoded,
int encoded_len_bytes,
int16_t* rateIndex);

View File

@ -35,6 +35,19 @@ Time2Spec WebRtcIsacfix_Time2Spec;
MatrixProduct1 WebRtcIsacfix_MatrixProduct1;
MatrixProduct2 WebRtcIsacfix_MatrixProduct2;
/* This method assumes that |stream_size_bytes| is in valid range,
* i.e. >= 0 && <= STREAM_MAXW16_60MS
*/
static void InitializeDecoderBitstream(int stream_size_bytes,
Bitstr_dec* bitstream) {
bitstream->W_upper = 0xFFFFFFFF;
bitstream->streamval = 0;
bitstream->stream_index = 0;
bitstream->full = 1;
bitstream->stream_size = (stream_size_bytes + 1) >> 1;
memset(bitstream->stream, 0, sizeof(bitstream->stream));
}
/**************************************************************************
* WebRtcIsacfix_AssignSize(...)
*
@ -388,6 +401,7 @@ int16_t WebRtcIsacfix_Encode(ISACFIX_MainStruct *ISAC_main_inst,
byte. */
stream_len_even = stream_len % 2 == 0 ? stream_len : stream_len + 1;
/* convert from bytes to int16_t */
#ifndef WEBRTC_ARCH_BIG_ENDIAN
/* The encoded data vector is supposesd to be big-endian, but our internal
representation is little-endian. So byteswap. */
@ -632,6 +646,7 @@ int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
int k;
#endif
int16_t err;
const int kRequiredEncodedLenBytes = 10;
/* typecast pointer to real structure */
ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
@ -653,17 +668,14 @@ int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
return (-1);
}
streamdata.W_upper = 0xFFFFFFFF;
streamdata.streamval = 0;
streamdata.stream_index = 0;
streamdata.full = 1;
InitializeDecoderBitstream(packet_size, &streamdata);
#ifndef WEBRTC_ARCH_BIG_ENDIAN
for (k=0; k<5; k++) {
for (k = 0; k < kRequiredEncodedLenBytes / 2; k++) {
streamdata.stream[k] = (uint16_t) (((uint16_t)encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
}
#else
memcpy(streamdata.stream, encoded, 5);
memcpy(streamdata.stream, encoded, kRequiredEncodedLenBytes);
#endif
err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
@ -716,6 +728,7 @@ int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
int k;
#endif
int16_t err;
const int kRequiredEncodedLenBytes = 10;
/* typecast pointer to real structure */
ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
@ -725,6 +738,9 @@ int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
/* return error code if the packet length is null or less */
ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
return -1;
} else if (packet_size < kRequiredEncodedLenBytes) {
ISAC_inst->errorcode = ISAC_PACKET_TOO_SHORT;
return -1;
} else if (packet_size > (STREAM_MAXW16<<1)) {
/* return error code if length of stream is too long */
ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
@ -737,17 +753,14 @@ int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
return (-1);
}
streamdata.W_upper = 0xFFFFFFFF;
streamdata.streamval = 0;
streamdata.stream_index = 0;
streamdata.full = 1;
InitializeDecoderBitstream(packet_size, &streamdata);
#ifndef WEBRTC_ARCH_BIG_ENDIAN
for (k=0; k<5; k++) {
for (k = 0; k < kRequiredEncodedLenBytes / 2; k++) {
streamdata.stream[k] = (uint16_t) ((encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
}
#else
memcpy(streamdata.stream, encoded, 5);
memcpy(streamdata.stream, encoded, kRequiredEncodedLenBytes);
#endif
err = WebRtcIsacfix_EstimateBandwidth(&ISAC_inst->bwestimator_obj,
@ -823,7 +836,7 @@ int16_t WebRtcIsacfix_Decode(ISACFIX_MainStruct *ISAC_main_inst,
return -1;
}
ISAC_inst->ISACdec_obj.bitstr_obj.stream_size = (len + 1) >> 1;
InitializeDecoderBitstream(len, &ISAC_inst->ISACdec_obj.bitstr_obj);
/* convert bitstream from int16_t to bytes */
#ifndef WEBRTC_ARCH_BIG_ENDIAN
@ -832,6 +845,8 @@ int16_t WebRtcIsacfix_Decode(ISACFIX_MainStruct *ISAC_main_inst,
}
if (len & 0x0001)
(ISAC_inst->ISACdec_obj.bitstr_obj).stream[k] = (uint16_t) ((encoded[k] & 0xFF)<<8);
#else
memcpy(ISAC_inst->ISACdec_obj.bitstr_obj.stream, encoded, len);
#endif
/* added for NetEq purposes (VAD/DTX related) */
@ -917,14 +932,17 @@ int16_t WebRtcIsacfix_DecodeNb(ISACFIX_MainStruct *ISAC_main_inst,
return (-1);
}
if (len == 0)
{ /* return error code if the packet length is null */
if (len <= 0) {
/* return error code if the packet length is null or less */
ISAC_inst->errorcode = ISAC_EMPTY_PACKET;
return -1;
} else if (len > (STREAM_MAXW16<<1)) {
/* return error code if length of stream is too long */
ISAC_inst->errorcode = ISAC_LENGTH_MISMATCH;
return -1;
}
ISAC_inst->ISACdec_obj.bitstr_obj.stream_size = (len + 1) >> 1;
InitializeDecoderBitstream(len, &ISAC_inst->ISACdec_obj.bitstr_obj);
/* convert bitstream from int16_t to bytes */
#ifndef WEBRTC_ARCH_BIG_ENDIAN
@ -933,6 +951,8 @@ int16_t WebRtcIsacfix_DecodeNb(ISACFIX_MainStruct *ISAC_main_inst,
}
if (len & 0x0001)
(ISAC_inst->ISACdec_obj.bitstr_obj).stream[k] = (uint16_t) ((encoded[k] & 0xFF)<<8);
#else
memcpy(ISAC_inst->ISACdec_obj.bitstr_obj.stream, encoded, len);
#endif
/* added for NetEq purposes (VAD/DTX related) */
@ -1296,6 +1316,7 @@ int16_t WebRtcIsacfix_UpdateUplinkBw(ISACFIX_MainStruct* ISAC_main_inst,
*/
int16_t WebRtcIsacfix_ReadFrameLen(const int16_t* encoded,
int encoded_len_bytes,
int16_t* frameLength)
{
Bitstr_dec streamdata;
@ -1303,18 +1324,20 @@ int16_t WebRtcIsacfix_ReadFrameLen(const int16_t* encoded,
int k;
#endif
int16_t err;
const int kRequiredEncodedLenBytes = 10;
streamdata.W_upper = 0xFFFFFFFF;
streamdata.streamval = 0;
streamdata.stream_index = 0;
streamdata.full = 1;
if (encoded_len_bytes < kRequiredEncodedLenBytes) {
return -1;
}
InitializeDecoderBitstream(encoded_len_bytes, &streamdata);
#ifndef WEBRTC_ARCH_BIG_ENDIAN
for (k=0; k<5; k++) {
for (k = 0; k < kRequiredEncodedLenBytes / 2; k++) {
streamdata.stream[k] = (uint16_t) (((uint16_t)encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
}
#else
memcpy(streamdata.stream, encoded, 5);
memcpy(streamdata.stream, encoded, kRequiredEncodedLenBytes);
#endif
/* decode frame length */
@ -1341,6 +1364,7 @@ int16_t WebRtcIsacfix_ReadFrameLen(const int16_t* encoded,
*/
int16_t WebRtcIsacfix_ReadBwIndex(const int16_t* encoded,
int encoded_len_bytes,
int16_t* rateIndex)
{
Bitstr_dec streamdata;
@ -1348,18 +1372,20 @@ int16_t WebRtcIsacfix_ReadBwIndex(const int16_t* encoded,
int k;
#endif
int16_t err;
const int kRequiredEncodedLenBytes = 10;
streamdata.W_upper = 0xFFFFFFFF;
streamdata.streamval = 0;
streamdata.stream_index = 0;
streamdata.full = 1;
if (encoded_len_bytes < kRequiredEncodedLenBytes) {
return -1;
}
InitializeDecoderBitstream(encoded_len_bytes, &streamdata);
#ifndef WEBRTC_ARCH_BIG_ENDIAN
for (k=0; k<5; k++) {
for (k = 0; k < kRequiredEncodedLenBytes / 2; k++) {
streamdata.stream[k] = (uint16_t) (((uint16_t)encoded[k] >> 8)|((encoded[k] & 0xFF)<<8));
}
#else
memcpy(streamdata.stream, encoded, 5);
memcpy(streamdata.stream, encoded, kRequiredEncodedLenBytes);
#endif
/* decode frame length, needed to get to the rateIndex in the bitstream */

View File

@ -96,7 +96,16 @@
#define STREAM_MAXW16 300 /* The old maximum size still needed for the decoding */
#define STREAM_MAXW16_30MS 100 /* 100 Word16 = 200 bytes = 53.4 kbit/s @ 30 ms.framelength */
#define STREAM_MAXW16_60MS 200 /* 200 Word16 = 400 bytes = 53.4 kbit/s @ 60 ms.framelength */
/* This is used only at the decoder bit-stream struct.
* - The encoder and decoder bitstream containers are of different size because
* old iSAC limited the encoded bitstream to 600 bytes. But newer versions
* restrict to shorter bitstream.
* - We add 10 bytes of guards to the internal bitstream container. The reason
* is that entropy decoder might read few bytes (3 according to our
* observations) more than the actual size of the bitstream. To avoid reading
* outside memory, in rare occasion of full-size bitstream we add 10 bytes
* of guard. */
#define INTERNAL_STREAM_SIZE_W16 (STREAM_MAXW16 + 5)
/* storage size for bit counts */
//#define BIT_COUNTER_SIZE 30
@ -190,6 +199,7 @@
/* 6600 Decoder */
#define ISAC_DECODER_NOT_INITIATED 6610
#define ISAC_EMPTY_PACKET 6620
#define ISAC_PACKET_TOO_SHORT 6625
#define ISAC_DISALLOWED_FRAME_MODE_DECODER 6630
#define ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH 6640
#define ISAC_RANGE_ERROR_DECODE_BANDWIDTH 6650

View File

@ -26,7 +26,7 @@
/* Bitstream struct for decoder */
typedef struct Bitstreamstruct_dec {
uint16_t stream[STREAM_MAXW16_60MS]; /* Array bytestream to decode */
uint16_t stream[INTERNAL_STREAM_SIZE_W16]; /* Array bytestream to decode */
uint32_t W_upper; /* Upper boundary of interval W */
uint32_t streamval;
uint16_t stream_index; /* Index to the current position in bytestream */

View File

@ -571,7 +571,8 @@ int main(int argc, char* argv[])
functions from the internal API. */
if (stream_len>0) {
if (testCE == 1) {
err = WebRtcIsacfix_ReadBwIndex((int16_t*)streamdata, &bwe);
err = WebRtcIsacfix_ReadBwIndex(
(int16_t*)streamdata, stream_len, &bwe);
stream_len = WebRtcIsacfix_GetNewBitStream(
ISAC_main_inst,
bwe,
@ -740,7 +741,8 @@ int main(int argc, char* argv[])
if (nbTest !=2 ) {
short FL;
/* Call getFramelen, only used here for function test */
err = WebRtcIsacfix_ReadFrameLen((int16_t*)streamdata, &FL);
err = WebRtcIsacfix_ReadFrameLen(
(int16_t*)streamdata, stream_len, &FL);
declen = WebRtcIsacfix_Decode( ISAC_main_inst, streamdata, stream_len,
decoded, speechType );
/* Error check */