init_get_bits(&gb, ptr, ptr_len * 8);
- while ( val != 0x16 ) {
- val = src[val - 0x17 + get_bits1(&gb) * byte];
+ while (val != 0x16) {
+ unsigned idx = val - 0x17 + get_bits1(&gb) * byte;
+ if (idx >= 2 * byte)
+ return -1;
+ val = src[idx];
- if ( val < 0x16 ) {
+ if (val < 0x16) {
if (dest >= dest_end)
return 0;
*dest++ = val;
*
* @param dest destination buffer of dest_len, must be padded with at least 130 bytes
*/
-static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_len)
+static void xan_unpack(unsigned char *dest, int dest_len,
+ const unsigned char *src, int src_len)
{
unsigned char opcode;
int size;
+ unsigned char *dest_org = dest;
unsigned char *dest_end = dest + dest_len;
+ const unsigned char *src_end = src + src_len;
- while (dest < dest_end) {
+ while (dest < dest_end && src < src_end) {
opcode = *src++;
if (opcode < 0xe0) {
int size2, back;
- if ( (opcode & 0x80) == 0 ) {
-
+ if ((opcode & 0x80) == 0) {
size = opcode & 3;
back = ((opcode & 0x60) << 3) + *src++ + 1;
size2 = ((opcode & 0x1c) >> 2) + 3;
-
- } else if ( (opcode & 0x40) == 0 ) {
-
+ } else if ((opcode & 0x40) == 0) {
size = *src >> 6;
back = (bytestream_get_be16(&src) & 0x3fff) + 1;
size2 = (opcode & 0x3f) + 4;
-
} else {
-
size = opcode & 3;
back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1;
size2 = ((opcode & 0x0c) << 6) + *src++ + 5;
- if (size + size2 > dest_end - dest)
- return;
}
+
+ if (dest_end - dest < size + size2 ||
+ dest + size - dest_org < back ||
+ src_end - src < size)
+ return;
memcpy(dest, src, size); dest += size; src += size;
av_memcpy_backptr(dest, back, size2);
dest += size2;
int finish = opcode >= 0xfc;
size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
+ if (dest_end - dest < size || src_end - src < size)
+ return;
memcpy(dest, src, size); dest += size; src += size;
if (finish)
return;
line_inc = stride - width;
index = y * stride + x;
current_x = x;
- while(pixel_count && (index < s->frame_size)) {
+ while (pixel_count && index < s->frame_size) {
int count = FFMIN(pixel_count, width - current_x);
memcpy(palette_plane + index, pixel_buffer, count);
pixel_count -= count;
}
}
-static inline void xan_wc3_copy_pixel_run(XanContext *s,
- int x, int y, int pixel_count, int motion_x, int motion_y)
+static inline void xan_wc3_copy_pixel_run(XanContext *s, int x, int y,
+ int pixel_count, int motion_x,
+ int motion_y)
{
int stride;
int line_inc;
int width = s->avctx->width;
unsigned char *palette_plane, *prev_palette_plane;
+ if (y + motion_y < 0 || y + motion_y >= s->avctx->height ||
+ x + motion_x < 0 || x + motion_x >= s->avctx->width)
+ return;
+
palette_plane = s->current_frame.data[0];
prev_palette_plane = s->last_frame.data[0];
+ if (!prev_palette_plane)
+ prev_palette_plane = palette_plane;
stride = s->current_frame.linesize[0];
line_inc = stride - width;
curframe_index = y * stride + x;
curframe_x = x;
prevframe_index = (y + motion_y) * stride + x + motion_x;
prevframe_x = x + motion_x;
- while(pixel_count && (curframe_index < s->frame_size)) {
- int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x);
-
- memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count);
+ while (pixel_count &&
+ curframe_index < s->frame_size &&
+ prevframe_index < s->frame_size) {
+ int count = FFMIN3(pixel_count, width - curframe_x,
+ width - prevframe_x);
+
+ memcpy(palette_plane + curframe_index,
+ prev_palette_plane + prevframe_index, count);
pixel_count -= count;
curframe_index += count;
prevframe_index += count;
static int xan_wc3_decode_frame(XanContext *s) {
- int width = s->avctx->width;
+ int width = s->avctx->width;
int height = s->avctx->height;
int total_pixels = width * height;
unsigned char opcode;
int x, y;
unsigned char *opcode_buffer = s->buffer1;
+ unsigned char *opcode_buffer_end = s->buffer1 + s->buffer1_size;
int opcode_buffer_size = s->buffer1_size;
const unsigned char *imagedata_buffer = s->buffer2;
const unsigned char *size_segment;
const unsigned char *vector_segment;
const unsigned char *imagedata_segment;
- int huffman_offset, size_offset, vector_offset, imagedata_offset;
+ int huffman_offset, size_offset, vector_offset, imagedata_offset,
+ imagedata_size;
if (s->size < 8)
return AVERROR_INVALIDDATA;
huffman_segment, s->size - huffman_offset) < 0)
return AVERROR_INVALIDDATA;
- if (imagedata_segment[0] == 2)
- xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size);
- else
+ if (imagedata_segment[0] == 2) {
+ xan_unpack(s->buffer2, s->buffer2_size,
+ &imagedata_segment[1], s->size - imagedata_offset - 1);
+ imagedata_size = s->buffer2_size;
+ } else {
+ imagedata_size = s->size - imagedata_offset - 1;
imagedata_buffer = &imagedata_segment[1];
+ }
/* use the decoded data segments to build the frame */
x = y = 0;
- while (total_pixels) {
+ while (total_pixels && opcode_buffer < opcode_buffer_end) {
opcode = *opcode_buffer++;
size = 0;
break;
}
+ if (size > total_pixels)
+ break;
+
if (opcode < 12) {
flag ^= 1;
if (flag) {
xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
} else {
/* output a run of pixels from imagedata_buffer */
+ if (imagedata_size < size)
+ break;
xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
imagedata_buffer += size;
+ imagedata_size -= size;
}
} else {
/* run-based motion compensation from last frame */
return AVERROR_INVALIDDATA;
if (s->palettes_count >= PALETTES_MAX)
return AVERROR_INVALIDDATA;
- tmpptr = av_realloc(s->palettes, (s->palettes_count + 1) * AVPALETTE_SIZE);
+ tmpptr = av_realloc(s->palettes,
+ (s->palettes_count + 1) * AVPALETTE_SIZE);
if (!tmpptr)
return AVERROR(ENOMEM);
s->palettes = tmpptr;
}
buf_size = buf_end - buf;
}
+ if (s->palettes_count <= 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "No palette found\n");
+ return AVERROR_INVALIDDATA;
+ }
+
if ((ret = avctx->get_buffer(avctx, &s->current_frame))) {
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
if (!s->frame_size)
s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
- memcpy(s->current_frame.data[1], s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
+ memcpy(s->current_frame.data[1],
+ s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
s->buf = buf;
s->size = buf_size;
.close = xan_decode_end,
.decode = xan_decode_frame,
.capabilities = CODEC_CAP_DR1,
- .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
+ .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
};