*/
#include "libavutil/common.h"
+#include "libavutil/mem_internal.h"
#include "libavutil/opt.h"
#include "avcodec.h"
#include "internal.h"
static const uint8_t fic_header[7] = { 0, 0, 1, 'F', 'I', 'C', 'V' };
#define FIC_HEADER_SIZE 27
+#define CURSOR_OFFSET 59
static av_always_inline void fic_idct(int16_t *blk, int step, int shift, int rnd)
{
{
int i, num_coeff;
+ if (get_bits_left(gb) < 8)
+ return AVERROR_INVALIDDATA;
+
/* Is it a skip block? */
if (get_bits1(gb)) {
*is_p = 1;
int slice_h = tctx->slice_h;
int src_size = tctx->src_size;
int y_off = tctx->y_off;
- int x, y, p;
+ int x, y, p, ret;
- init_get_bits(&gb, src, src_size * 8);
+ ret = init_get_bits8(&gb, src, src_size);
+ if (ret < 0)
+ return ret;
for (p = 0; p < 3; p++) {
int stride = ctx->frame->linesize[p];
int skip_cursor = ctx->skip_cursor;
uint8_t *sdata;
- if ((ret = ff_reget_buffer(avctx, ctx->frame)) < 0)
+ if ((ret = ff_reget_buffer(avctx, ctx->frame, 0)) < 0)
return ret;
/* Header + at least one slice (4) */
skip_cursor = 1;
}
+ if (!skip_cursor && avpkt->size < CURSOR_OFFSET + sizeof(ctx->cursor_buf)) {
+ skip_cursor = 1;
+ }
+
/* Slice height for all but the last slice. */
ctx->slice_h = 16 * (ctx->aligned_height >> 4) / nslices;
if (ctx->slice_h % 16)
sdata = src + tsize + FIC_HEADER_SIZE + 4 * nslices;
msize = avpkt->size - nslices * 4 - tsize - FIC_HEADER_SIZE;
- if (msize <= 0) {
+ if (msize <= ctx->aligned_width/8 * (ctx->aligned_height/8) / 8) {
av_log(avctx, AV_LOG_ERROR, "Not enough frame data to decode.\n");
return AVERROR_INVALIDDATA;
}
slice_h = FFALIGN(avctx->height - ctx->slice_h * (nslices - 1), 16);
} else {
slice_size = AV_RB32(src + tsize + FIC_HEADER_SIZE + slice * 4 + 4);
+ if (slice_size < slice_off)
+ return AVERROR_INVALIDDATA;
}
if (slice_size < slice_off || slice_size > msize)
}
/* Make sure we use a user-supplied buffer. */
- if ((ret = ff_reget_buffer(avctx, ctx->final_frame)) < 0) {
+ if ((ret = ff_reget_buffer(avctx, ctx->final_frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Could not make frame writable.\n");
return ret;
}
/* Draw cursor. */
if (!skip_cursor) {
- memcpy(ctx->cursor_buf, src + 59, 32 * 32 * 4);
+ memcpy(ctx->cursor_buf, src + CURSOR_OFFSET, sizeof(ctx->cursor_buf));
fic_draw_cursor(avctx, cur_x, cur_y);
}
};
static const AVClass fic_decoder_class = {
- .class_name = "FIC encoder",
+ .class_name = "FIC decoder",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
-AVCodec ff_fic_decoder = {
+const AVCodec ff_fic_decoder = {
.name = "fic",
.long_name = NULL_IF_CONFIG_SMALL("Mirillis FIC"),
.type = AVMEDIA_TYPE_VIDEO,