| Index: source/libvpx/vp9/vp9_dx_iface.c
|
| ===================================================================
|
| --- source/libvpx/vp9/vp9_dx_iface.c (revision 281795)
|
| +++ source/libvpx/vp9/vp9_dx_iface.c (working copy)
|
| @@ -317,10 +317,17 @@
|
| return *data;
|
| }
|
|
|
| -static void parse_superframe_index(const uint8_t *data, size_t data_sz,
|
| - uint32_t sizes[8], int *count,
|
| - vpx_decrypt_cb decrypt_cb,
|
| - void *decrypt_state) {
|
| +static vpx_codec_err_t parse_superframe_index(const uint8_t *data,
|
| + size_t data_sz,
|
| + uint32_t sizes[8], int *count,
|
| + vpx_decrypt_cb decrypt_cb,
|
| + void *decrypt_state) {
|
| + // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
|
| + // it is a super frame index. If the last byte of real video compression
|
| + // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
|
| + // not the associated matching marker byte at the front of the index we have
|
| + // an invalid bitstream and need to return an error.
|
| +
|
| uint8_t marker;
|
|
|
| assert(data_sz);
|
| @@ -332,35 +339,46 @@
|
| const uint32_t mag = ((marker >> 3) & 0x3) + 1;
|
| const size_t index_sz = 2 + mag * frames;
|
|
|
| - if (data_sz >= index_sz) {
|
| - uint8_t marker2 = read_marker(decrypt_cb, decrypt_state,
|
| - data + data_sz - index_sz);
|
| + // This chunk is marked as having a superframe index but doesn't have
|
| + // enough data for it, thus it's an invalid superframe index.
|
| + if (data_sz < index_sz)
|
| + return VPX_CODEC_CORRUPT_FRAME;
|
|
|
| - if (marker == marker2) {
|
| - // Found a valid superframe index.
|
| - uint32_t i, j;
|
| - const uint8_t *x = &data[data_sz - index_sz + 1];
|
| + {
|
| + const uint8_t marker2 = read_marker(decrypt_cb, decrypt_state,
|
| + data + data_sz - index_sz);
|
|
|
| - // Frames has a maximum of 8 and mag has a maximum of 4.
|
| - uint8_t clear_buffer[32];
|
| - assert(sizeof(clear_buffer) >= frames * mag);
|
| - if (decrypt_cb) {
|
| - decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
|
| - x = clear_buffer;
|
| - }
|
| + // This chunk is marked as having a superframe index but doesn't have
|
| + // the matching marker byte at the front of the index therefore it's an
|
| + // invalid chunk.
|
| + if (marker != marker2)
|
| + return VPX_CODEC_CORRUPT_FRAME;
|
| + }
|
|
|
| - for (i = 0; i < frames; ++i) {
|
| - uint32_t this_sz = 0;
|
| + {
|
| + // Found a valid superframe index.
|
| + uint32_t i, j;
|
| + const uint8_t *x = &data[data_sz - index_sz + 1];
|
|
|
| - for (j = 0; j < mag; ++j)
|
| - this_sz |= (*x++) << (j * 8);
|
| - sizes[i] = this_sz;
|
| - }
|
| + // Frames has a maximum of 8 and mag has a maximum of 4.
|
| + uint8_t clear_buffer[32];
|
| + assert(sizeof(clear_buffer) >= frames * mag);
|
| + if (decrypt_cb) {
|
| + decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
|
| + x = clear_buffer;
|
| + }
|
|
|
| - *count = frames;
|
| + for (i = 0; i < frames; ++i) {
|
| + uint32_t this_sz = 0;
|
| +
|
| + for (j = 0; j < mag; ++j)
|
| + this_sz |= (*x++) << (j * 8);
|
| + sizes[i] = this_sz;
|
| }
|
| + *count = frames;
|
| }
|
| }
|
| + return VPX_CODEC_OK;
|
| }
|
|
|
| static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
|
| @@ -375,8 +393,10 @@
|
| if (data == NULL || data_sz == 0)
|
| return VPX_CODEC_INVALID_PARAM;
|
|
|
| - parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
|
| - ctx->decrypt_cb, ctx->decrypt_state);
|
| + res = parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
|
| + ctx->decrypt_cb, ctx->decrypt_state);
|
| + if (res != VPX_CODEC_OK)
|
| + return res;
|
|
|
| if (ctx->frame_parallel_decode) {
|
| // Decode in frame parallel mode. When decoding in this mode, the frame
|
|
|