| @@ -40,6 +40,14 @@ typedef struct UltimotionDecodeContext { | |||
| const uint8_t *ulti_codebook; | |||
| } UltimotionDecodeContext; | |||
| #define CHECK_OVERREAD_SIZE(size) \ | |||
| do { \ | |||
| if (buf_end - buf < (size)) { \ | |||
| av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); \ | |||
| return AVERROR_INVALIDDATA; \ | |||
| } \ | |||
| } while(0) | |||
| static av_cold int ulti_decode_init(AVCodecContext *avctx) | |||
| { | |||
| UltimotionDecodeContext *s = avctx->priv_data; | |||
| @@ -223,6 +231,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| int i; | |||
| int skip; | |||
| int tmp; | |||
| const uint8_t *buf_end = buf + buf_size; | |||
| s->frame.reference = 1; | |||
| s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |||
| @@ -236,10 +245,12 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| if(blocks >= s->blocks || y >= s->height) | |||
| break;//all blocks decoded | |||
| CHECK_OVERREAD_SIZE(1); | |||
| idx = *buf++; | |||
| if((idx & 0xF8) == 0x70) { | |||
| switch(idx) { | |||
| case 0x70: //change modifier | |||
| CHECK_OVERREAD_SIZE(1); | |||
| modifier = *buf++; | |||
| if(modifier>1) | |||
| av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); | |||
| @@ -254,6 +265,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| done = 1; | |||
| break; | |||
| case 0x74: //skip some blocks | |||
| CHECK_OVERREAD_SIZE(1); | |||
| skip = *buf++; | |||
| if ((blocks + skip) >= s->blocks) | |||
| break; | |||
| @@ -280,19 +292,24 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| chroma = 0; | |||
| } else { | |||
| cf = 0; | |||
| if (idx) | |||
| if (idx) { | |||
| CHECK_OVERREAD_SIZE(1); | |||
| chroma = *buf++; | |||
| } | |||
| } | |||
| for (i = 0; i < 4; i++) { // for every subblock | |||
| code = (idx >> (6 - i*2)) & 3; //extract 2 bits | |||
| if(!code) //skip subblock | |||
| continue; | |||
| if(cf) | |||
| if(cf) { | |||
| CHECK_OVERREAD_SIZE(1); | |||
| chroma = *buf++; | |||
| } | |||
| tx = x + block_coords[i * 2]; | |||
| ty = y + block_coords[(i * 2) + 1]; | |||
| switch(code) { | |||
| case 1: | |||
| CHECK_OVERREAD_SIZE(1); | |||
| tmp = *buf++; | |||
| angle = angle_by_index[(tmp >> 6) & 0x3]; | |||
| @@ -313,6 +330,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| case 2: | |||
| if (modifier) { // unpack four luma samples | |||
| CHECK_OVERREAD_SIZE(3); | |||
| tmp = bytestream_get_be24(&buf); | |||
| Y[0] = (tmp >> 18) & 0x3F; | |||
| @@ -321,6 +339,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| Y[3] = tmp & 0x3F; | |||
| angle = 16; | |||
| } else { // retrieve luma samples from codebook | |||
| CHECK_OVERREAD_SIZE(2); | |||
| tmp = bytestream_get_be16(&buf); | |||
| angle = (tmp >> 12) & 0xF; | |||
| @@ -337,6 +356,8 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| if (modifier) { // all 16 luma samples | |||
| uint8_t Luma[16]; | |||
| CHECK_OVERREAD_SIZE(12); | |||
| tmp = bytestream_get_be24(&buf); | |||
| Luma[0] = (tmp >> 18) & 0x3F; | |||
| Luma[1] = (tmp >> 12) & 0x3F; | |||
| @@ -363,6 +384,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||
| ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); | |||
| } else { | |||
| CHECK_OVERREAD_SIZE(4); | |||
| tmp = *buf++; | |||
| if(tmp & 0x80) { | |||
| angle = (tmp >> 4) & 0x7; | |||