const uint8_t *next_cell_data;
const uint8_t *last_byte;
const int8_t *mc_vectors;
+ unsigned num_vectors; ///< number of motion vectors in mc_vectors
int16_t width, height;
uint32_t frame_num; ///< current frame number (zero-based)
/* set buffer pointers = buf_ptr + pitch and thus skip the INTRA prediction line */
ctx->planes[p].pixels[0] = ctx->planes[p].buffers[0] + ctx->planes[p].pitch;
ctx->planes[p].pixels[1] = ctx->planes[p].buffers[1] + ctx->planes[p].pitch;
+ memset(ctx->planes[p].pixels[0], 0, ctx->planes[p].pitch * ctx->planes[p].height);
+ memset(ctx->planes[p].pixels[1], 0, ctx->planes[p].pitch * ctx->planes[p].height);
}
return 0;
for (p = 0; p < 3; p++) {
av_freep(&ctx->planes[p].buffers[0]);
av_freep(&ctx->planes[p].buffers[1]);
+ ctx->planes[p].pixels[0] = ctx->planes[p].pixels[1] = 0;
}
}
fill_64(dst, pix64, num_lines << 1, row_offset)
#define APPLY_DELTA_4 \
- AV_WN16A(dst + line_offset , AV_RN16A(ref ) + delta_tab->deltas[dyad1]);\
- AV_WN16A(dst + line_offset + 2, AV_RN16A(ref + 2) + delta_tab->deltas[dyad2]);\
+ AV_WN16A(dst + line_offset ,\
+ (AV_RN16A(ref ) + delta_tab->deltas[dyad1]) & 0x7F7F);\
+ AV_WN16A(dst + line_offset + 2,\
+ (AV_RN16A(ref + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\
if (mode >= 3) {\
if (is_top_of_cell && !cell->ypos) {\
AV_COPY32(dst, dst + row_offset);\
/* apply two 32-bit VQ deltas to next even line */\
if (is_top_of_cell) { \
AV_WN32A(dst + row_offset , \
- replicate32(AV_RN32A(ref )) + delta_tab->deltas_m10[dyad1]);\
+ (replicate32(AV_RN32A(ref )) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\
AV_WN32A(dst + row_offset + 4, \
- replicate32(AV_RN32A(ref + 4)) + delta_tab->deltas_m10[dyad2]);\
+ (replicate32(AV_RN32A(ref + 4)) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\
} else { \
AV_WN32A(dst + row_offset , \
- AV_RN32A(ref ) + delta_tab->deltas_m10[dyad1]);\
+ (AV_RN32A(ref ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\
AV_WN32A(dst + row_offset + 4, \
- AV_RN32A(ref + 4) + delta_tab->deltas_m10[dyad2]);\
+ (AV_RN32A(ref + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\
} \
/* odd lines are not coded but rather interpolated/replicated */\
/* first line of the cell on the top of image? - replicate */\
#define APPLY_DELTA_1011_INTER \
if (mode == 10) { \
AV_WN32A(dst , \
- AV_RN32A(dst ) + delta_tab->deltas_m10[dyad1]);\
+ (AV_RN32A(dst ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\
AV_WN32A(dst + 4 , \
- AV_RN32A(dst + 4 ) + delta_tab->deltas_m10[dyad2]);\
+ (AV_RN32A(dst + 4 ) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\
AV_WN32A(dst + row_offset , \
- AV_RN32A(dst + row_offset ) + delta_tab->deltas_m10[dyad1]);\
+ (AV_RN32A(dst + row_offset ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\
AV_WN32A(dst + row_offset + 4, \
- AV_RN32A(dst + row_offset + 4) + delta_tab->deltas_m10[dyad2]);\
+ (AV_RN32A(dst + row_offset + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\
} else { \
AV_WN16A(dst , \
- AV_RN16A(dst ) + delta_tab->deltas[dyad1]);\
+ (AV_RN16A(dst ) + delta_tab->deltas[dyad1]) & 0x7F7F);\
AV_WN16A(dst + 2 , \
- AV_RN16A(dst + 2 ) + delta_tab->deltas[dyad2]);\
+ (AV_RN16A(dst + 2 ) + delta_tab->deltas[dyad2]) & 0x7F7F);\
AV_WN16A(dst + row_offset , \
- AV_RN16A(dst + row_offset ) + delta_tab->deltas[dyad1]);\
+ (AV_RN16A(dst + row_offset ) + delta_tab->deltas[dyad1]) & 0x7F7F);\
AV_WN16A(dst + row_offset + 2, \
- AV_RN16A(dst + row_offset + 2) + delta_tab->deltas[dyad2]);\
+ (AV_RN16A(dst + row_offset + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\
}
SPLIT_CELL(ref_cell->height, curr_cell.height);
ref_cell->ypos += curr_cell.height;
ref_cell->height -= curr_cell.height;
+ if (ref_cell->height <= 0 || curr_cell.height <= 0)
+ return AVERROR_INVALIDDATA;
} else if (code == V_SPLIT) {
if (curr_cell.width > strip_width) {
/* split strip */
SPLIT_CELL(ref_cell->width, curr_cell.width);
ref_cell->xpos += curr_cell.width;
ref_cell->width -= curr_cell.width;
+ if (ref_cell->width <= 0 || curr_cell.width <= 0)
+ return AVERROR_INVALIDDATA;
}
while (1) { /* loop until return */
av_log(avctx, AV_LOG_ERROR, "SkipCell procedure not implemented yet!\n");
CHECK_CELL
- if(!curr_cell.mv_ptr)
+ if (!curr_cell.mv_ptr)
return AVERROR_INVALIDDATA;
copy_cell(ctx, plane, &curr_cell);
return 0;
break;
case INTER_DATA:
if (!curr_cell.tree) { /* MC tree INTER code */
+ unsigned mv_idx;
/* get motion vector index and setup the pointer to the mv set */
if (!ctx->need_resync)
ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3];
- curr_cell.mv_ptr = &ctx->mc_vectors[*(ctx->next_cell_data++) << 1];
+ mv_idx = *(ctx->next_cell_data++);
+ if (mv_idx >= ctx->num_vectors) {
+ av_log(avctx, AV_LOG_ERROR, "motion vector index out of range\n");
+ return AVERROR_INVALIDDATA;
+ }
+ curr_cell.mv_ptr = &ctx->mc_vectors[mv_idx << 1];
curr_cell.tree = 1; /* enter the VQ tree */
UPDATE_BITPOS(8);
} else { /* VQ tree DATA code */
int32_t strip_width)
{
Cell curr_cell;
- int num_vectors;
+ unsigned num_vectors;
/* each plane data starts with mc_vector_count field, */
/* an optional array of motion vectors followed by the vq data */
num_vectors = bytestream_get_le32(&data);
+ if (num_vectors > 256) {
+ av_log(ctx->avctx, AV_LOG_ERROR,
+ "Read invalid number of motion vectors %d\n", num_vectors);
+ return AVERROR_INVALIDDATA;
+ }
+ if (num_vectors * 2 >= data_size)
+ return AVERROR_INVALIDDATA;
+
+ ctx->num_vectors = num_vectors;
ctx->mc_vectors = num_vectors ? data : 0;
/* init the bitreader */
- init_get_bits(&ctx->gb, &data[num_vectors * 2], data_size << 3);
+ init_get_bits(&ctx->gb, &data[num_vectors * 2], (data_size - num_vectors * 2) << 3);
ctx->skip_bits = 0;
ctx->need_resync = 0;
return AVERROR_INVALIDDATA;
if (width != ctx->width || height != ctx->height) {
+ int res;
+
av_dlog(avctx, "Frame dimensions changed!\n");
+ if (width < 16 || width > 640 ||
+ height < 16 || height > 480 ||
+ width & 3 || height & 3) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid picture dimensions: %d x %d!\n", width, height);
+ return AVERROR_INVALIDDATA;
+ }
+
ctx->width = width;
ctx->height = height;
free_frame_buffers(ctx);
- allocate_frame_buffers(ctx, avctx);
+ if ((res = allocate_frame_buffers(ctx, avctx)) < 0)
+ return res;
avcodec_set_dimensions(avctx, width, height);
}
build_requant_tab();
- dsputil_init(&ctx->dsp, avctx);
+ ff_dsputil_init(&ctx->dsp, avctx);
allocate_frame_buffers(ctx, avctx);
AVCodec ff_indeo3_decoder = {
.name = "indeo3",
.type = AVMEDIA_TYPE_VIDEO,
- .id = CODEC_ID_INDEO3,
+ .id = AV_CODEC_ID_INDEO3,
.priv_data_size = sizeof(Indeo3DecodeContext),
.init = decode_init,
.close = decode_close,