| @@ -45,43 +45,43 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, | |||||
| uint32_t pixformat, pixdepth, bunit, bitorder, bpad; | uint32_t pixformat, pixdepth, bunit, bitorder, bpad; | ||||
| uint32_t rgb[3]; | uint32_t rgb[3]; | ||||
| uint8_t *ptr; | uint8_t *ptr; | ||||
| GetByteContext gb; | |||||
| if (buf_size < XWD_HEADER_SIZE) | if (buf_size < XWD_HEADER_SIZE) | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| header_size = bytestream_get_be32(&buf); | |||||
| if (buf_size < header_size) | |||||
| return AVERROR_INVALIDDATA; | |||||
| bytestream2_init(&gb, buf, buf_size); | |||||
| header_size = bytestream2_get_be32u(&gb); | |||||
| version = bytestream_get_be32(&buf); | |||||
| version = bytestream2_get_be32u(&gb); | |||||
| if (version != XWD_VERSION) { | if (version != XWD_VERSION) { | ||||
| av_log(avctx, AV_LOG_ERROR, "unsupported version\n"); | av_log(avctx, AV_LOG_ERROR, "unsupported version\n"); | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| if (header_size < XWD_HEADER_SIZE) { | |||||
| if (buf_size < header_size || header_size < XWD_HEADER_SIZE) { | |||||
| av_log(avctx, AV_LOG_ERROR, "invalid header size\n"); | av_log(avctx, AV_LOG_ERROR, "invalid header size\n"); | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| pixformat = bytestream_get_be32(&buf); | |||||
| pixdepth = bytestream_get_be32(&buf); | |||||
| avctx->width = bytestream_get_be32(&buf); | |||||
| avctx->height = bytestream_get_be32(&buf); | |||||
| xoffset = bytestream_get_be32(&buf); | |||||
| be = bytestream_get_be32(&buf); | |||||
| bunit = bytestream_get_be32(&buf); | |||||
| bitorder = bytestream_get_be32(&buf); | |||||
| bpad = bytestream_get_be32(&buf); | |||||
| bpp = bytestream_get_be32(&buf); | |||||
| lsize = bytestream_get_be32(&buf); | |||||
| vclass = bytestream_get_be32(&buf); | |||||
| rgb[0] = bytestream_get_be32(&buf); | |||||
| rgb[1] = bytestream_get_be32(&buf); | |||||
| rgb[2] = bytestream_get_be32(&buf); | |||||
| buf += 8; | |||||
| ncolors = bytestream_get_be32(&buf); | |||||
| buf += header_size - (XWD_HEADER_SIZE - 20); | |||||
| pixformat = bytestream2_get_be32u(&gb); | |||||
| pixdepth = bytestream2_get_be32u(&gb); | |||||
| avctx->width = bytestream2_get_be32u(&gb); | |||||
| avctx->height = bytestream2_get_be32u(&gb); | |||||
| xoffset = bytestream2_get_be32u(&gb); | |||||
| be = bytestream2_get_be32u(&gb); | |||||
| bunit = bytestream2_get_be32u(&gb); | |||||
| bitorder = bytestream2_get_be32u(&gb); | |||||
| bpad = bytestream2_get_be32u(&gb); | |||||
| bpp = bytestream2_get_be32u(&gb); | |||||
| lsize = bytestream2_get_be32u(&gb); | |||||
| vclass = bytestream2_get_be32u(&gb); | |||||
| rgb[0] = bytestream2_get_be32u(&gb); | |||||
| rgb[1] = bytestream2_get_be32u(&gb); | |||||
| rgb[2] = bytestream2_get_be32u(&gb); | |||||
| bytestream2_skipu(&gb, 8); | |||||
| ncolors = bytestream2_get_be32u(&gb); | |||||
| bytestream2_skipu(&gb, header_size - (XWD_HEADER_SIZE - 20)); | |||||
| av_log(avctx, AV_LOG_DEBUG, "pixformat %d, pixdepth %d, bunit %d, bitorder %d, bpad %d\n", | av_log(avctx, AV_LOG_DEBUG, "pixformat %d, pixdepth %d, bunit %d, bitorder %d, bpad %d\n", | ||||
| pixformat, pixdepth, bunit, bitorder, bpad); | pixformat, pixdepth, bunit, bitorder, bpad); | ||||
| @@ -143,7 +143,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, | |||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| if (buf_size < header_size + ncolors * XWD_CMAP_SIZE + avctx->height * lsize) { | |||||
| if (bytestream2_get_bytes_left(&gb) < ncolors * XWD_CMAP_SIZE + avctx->height * lsize) { | |||||
| av_log(avctx, AV_LOG_ERROR, "input buffer too small\n"); | av_log(avctx, AV_LOG_ERROR, "input buffer too small\n"); | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| @@ -192,7 +192,7 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, | |||||
| else if (rgb[0] == 0xFF && rgb[1] == 0xFF00 && rgb[2] == 0xFF0000) | else if (rgb[0] == 0xFF && rgb[1] == 0xFF00 && rgb[2] == 0xFF0000) | ||||
| avctx->pix_fmt = be ? PIX_FMT_ABGR : PIX_FMT_RGBA; | avctx->pix_fmt = be ? PIX_FMT_ABGR : PIX_FMT_RGBA; | ||||
| } | } | ||||
| buf += ncolors * XWD_CMAP_SIZE; | |||||
| bytestream2_skipu(&gb, ncolors * XWD_CMAP_SIZE); | |||||
| break; | break; | ||||
| default: | default: | ||||
| av_log(avctx, AV_LOG_ERROR, "invalid visual class\n"); | av_log(avctx, AV_LOG_ERROR, "invalid visual class\n"); | ||||
| @@ -222,11 +222,13 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, | |||||
| for (i = 0; i < ncolors; i++) { | for (i = 0; i < ncolors; i++) { | ||||
| buf += 4; // skip colormap entry number | |||||
| red = *buf; buf += 2; | |||||
| green = *buf; buf += 2; | |||||
| blue = *buf; buf += 2; | |||||
| buf += 2; // skip bitmask flag and padding | |||||
| bytestream2_skipu(&gb, 4); // skip colormap entry number | |||||
| red = bytestream2_get_byteu(&gb); | |||||
| bytestream2_skipu(&gb, 1); | |||||
| green = bytestream2_get_byteu(&gb); | |||||
| bytestream2_skipu(&gb, 1); | |||||
| blue = bytestream2_get_byteu(&gb); | |||||
| bytestream2_skipu(&gb, 3); // skip bitmask flag and padding | |||||
| dst[i] = red << 16 | green << 8 | blue; | dst[i] = red << 16 | green << 8 | blue; | ||||
| } | } | ||||
| @@ -234,8 +236,8 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, | |||||
| ptr = p->data[0]; | ptr = p->data[0]; | ||||
| for (i = 0; i < avctx->height; i++) { | for (i = 0; i < avctx->height; i++) { | ||||
| bytestream_get_buffer(&buf, ptr, rsize); | |||||
| buf += lsize - rsize; | |||||
| bytestream2_get_bufferu(&gb, ptr, rsize); | |||||
| bytestream2_skipu(&gb, lsize - rsize); | |||||
| ptr += p->linesize[0]; | ptr += p->linesize[0]; | ||||
| } | } | ||||