summaryrefslogtreecommitdiff
path: root/libavcodec/xan.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/xan.c')
-rw-r--r--libavcodec/xan.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/libavcodec/xan.c b/libavcodec/xan.c
index ca2e8e0e2c..41925aa346 100644
--- a/libavcodec/xan.c
+++ b/libavcodec/xan.c
@@ -2,20 +2,20 @@
* Wing Commander/Xan Video Decoder
* Copyright (C) 2003 the ffmpeg project
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -52,7 +52,7 @@
typedef struct XanContext {
AVCodecContext *avctx;
- AVFrame last_frame;
+ AVFrame *last_frame;
const unsigned char *buf;
int size;
@@ -71,6 +71,8 @@ typedef struct XanContext {
} XanContext;
+static av_cold int xan_decode_end(AVCodecContext *avctx);
+
static av_cold int xan_decode_init(AVCodecContext *avctx)
{
XanContext *s = avctx->priv_data;
@@ -90,6 +92,11 @@ static av_cold int xan_decode_init(AVCodecContext *avctx)
av_freep(&s->buffer1);
return AVERROR(ENOMEM);
}
+ s->last_frame = av_frame_alloc();
+ if (!s->last_frame) {
+ xan_decode_end(avctx);
+ return AVERROR(ENOMEM);
+ }
return 0;
}
@@ -233,7 +240,7 @@ static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame,
return;
palette_plane = frame->data[0];
- prev_palette_plane = s->last_frame.data[0];
+ prev_palette_plane = s->last_frame->data[0];
if (!prev_palette_plane)
prev_palette_plane = palette_plane;
stride = frame->linesize[0];
@@ -242,6 +249,12 @@ static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame,
curframe_x = x;
prevframe_index = (y + motion_y) * stride + x + motion_x;
prevframe_x = x + motion_x;
+
+ if (prev_palette_plane == palette_plane && FFABS(curframe_index - prevframe_index) < pixel_count) {
+ avpriv_request_sample(s->avctx, "Overlapping copy\n");
+ return ;
+ }
+
while (pixel_count &&
curframe_index < s->frame_size &&
prevframe_index < s->frame_size) {
@@ -290,6 +303,7 @@ static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame)
const unsigned char *size_segment;
const unsigned char *vector_segment;
const unsigned char *imagedata_segment;
+ const unsigned char *buf_end = s->buf + s->size;
int huffman_offset, size_offset, vector_offset, imagedata_offset,
imagedata_size;
@@ -361,17 +375,29 @@ static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame)
case 9:
case 19:
+ if (buf_end - size_segment < 1) {
+ av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
+ return AVERROR_INVALIDDATA;
+ }
size = *size_segment++;
break;
case 10:
case 20:
+ if (buf_end - size_segment < 2) {
+ av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
+ return AVERROR_INVALIDDATA;
+ }
size = AV_RB16(&size_segment[0]);
size_segment += 2;
break;
case 11:
case 21:
+ if (buf_end - size_segment < 3) {
+ av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
+ return AVERROR_INVALIDDATA;
+ }
size = AV_RB24(size_segment);
size_segment += 3;
break;
@@ -394,6 +420,10 @@ static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame)
imagedata_size -= size;
}
} else {
+ if (vector_segment >= buf_end) {
+ av_log(s->avctx, AV_LOG_ERROR, "vector_segment overread\n");
+ return AVERROR_INVALIDDATA;
+ }
/* run-based motion compensation from last frame */
motion_x = sign_extend(*vector_segment >> 4, 4);
motion_y = sign_extend(*vector_segment & 0xF, 4);
@@ -515,6 +545,10 @@ static int xan_decode_frame(AVCodecContext *avctx,
int i;
tag = bytestream2_get_le32(&ctx);
size = bytestream2_get_be32(&ctx);
+ if(size < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid tag size %d\n", size);
+ return AVERROR_INVALIDDATA;
+ }
size = FFMIN(size, bytestream2_get_bytes_left(&ctx));
switch (tag) {
case PALT_TAG:
@@ -538,7 +572,7 @@ static int xan_decode_frame(AVCodecContext *avctx,
int g = gamma_lookup[bytestream2_get_byteu(&ctx)];
int b = gamma_lookup[bytestream2_get_byteu(&ctx)];
#endif
- *tmpptr++ = (r << 16) | (g << 8) | b;
+ *tmpptr++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
}
s->palettes_count++;
break;
@@ -565,10 +599,8 @@ static int xan_decode_frame(AVCodecContext *avctx,
return AVERROR_INVALIDDATA;
}
- if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF))) {
- av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
return ret;
- }
if (!s->frame_size)
s->frame_size = frame->linesize[0] * s->avctx->height;
@@ -582,8 +614,8 @@ static int xan_decode_frame(AVCodecContext *avctx,
if (xan_wc3_decode_frame(s, frame) < 0)
return AVERROR_INVALIDDATA;
- av_frame_unref(&s->last_frame);
- if ((ret = av_frame_ref(&s->last_frame, frame)) < 0)
+ av_frame_unref(s->last_frame);
+ if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
return ret;
*got_frame = 1;
@@ -596,7 +628,7 @@ static av_cold int xan_decode_end(AVCodecContext *avctx)
{
XanContext *s = avctx->priv_data;
- av_frame_unref(&s->last_frame);
+ av_frame_free(&s->last_frame);
av_freep(&s->buffer1);
av_freep(&s->buffer2);