diff options
Diffstat (limited to 'libavcodec/g2meet.c')
-rw-r--r-- | libavcodec/g2meet.c | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index d0b36f0ea8..2a7124a378 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -3,20 +3,20 @@ * Copyright (c) 2012 Konstantin Shishkov * Copyright (c) 2013 Maxim Poliakovski * - * 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 */ @@ -298,7 +298,8 @@ static int jpg_decode_data(JPGContext *c, int width, int height, return ret; jpg_unescape(src, src_size, c->buf, &unesc_size); memset(c->buf + unesc_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - init_get_bits(&gb, c->buf, unesc_size * 8); + if((ret = init_get_bits8(&gb, c->buf, unesc_size)) < 0) + return ret; width = FFALIGN(width, 16); mb_w = width >> 4; @@ -1015,7 +1016,7 @@ static int epic_jb_decode_tile(G2MContext *c, int tile_x, int tile_y, return 0; } -static void kempf_restore_buf(const uint8_t *src, int len, +static int kempf_restore_buf(const uint8_t *src, int len, uint8_t *dst, int stride, const uint8_t *jpeg_tile, int tile_stride, int width, int height, @@ -1023,9 +1024,11 @@ static void kempf_restore_buf(const uint8_t *src, int len, { GetBitContext gb; int i, j, nb, col; + int ret; int align_width = FFALIGN(width, 16); - init_get_bits(&gb, src, len * 8); + if ((ret = init_get_bits8(&gb, src, len)) < 0) + return ret; if (npal <= 2) nb = 1; else if (npal <= 4) nb = 2; @@ -1044,6 +1047,8 @@ static void kempf_restore_buf(const uint8_t *src, int len, } skip_bits_long(&gb, nb * (align_width - width)); } + + return 0; } static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y, @@ -1087,6 +1092,8 @@ static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y, src += 3; } npal = *src++ + 1; + if (src_end - src < npal * 3) + return AVERROR_INVALIDDATA; memcpy(pal, src, npal * 3); src += npal * 3; if (sub_type != 2) { @@ -1103,7 +1110,7 @@ static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y, zsize = (src[0] << 8) | src[1]; src += 2; - if (src_end - src < zsize) + if (src_end - src < zsize + (sub_type != 2)) return AVERROR_INVALIDDATA; ret = uncompress(c->kempf_buf, &dlen, src, zsize); @@ -1125,6 +1132,8 @@ static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y, for (i = 0; i < (FFALIGN(height, 16) >> 4); i++) { for (j = 0; j < (FFALIGN(width, 16) >> 4); j++) { if (!bits) { + if (src >= src_end) + return AVERROR_INVALIDDATA; bitbuf = *src++; bits = 8; } @@ -1158,10 +1167,10 @@ static int g2m_init_buffers(G2MContext *c) int aligned_height; if (!c->framebuf || c->old_width < c->width || c->old_height < c->height) { - c->framebuf_stride = FFALIGN(c->width * 3, 16); - aligned_height = FFALIGN(c->height, 16); + c->framebuf_stride = FFALIGN(c->width + 15, 16) * 3; + aligned_height = c->height + 15; av_free(c->framebuf); - c->framebuf = av_mallocz(c->framebuf_stride * aligned_height); + c->framebuf = av_mallocz_array(c->framebuf_stride, aligned_height); if (!c->framebuf) return AVERROR(ENOMEM); } @@ -1169,7 +1178,7 @@ static int g2m_init_buffers(G2MContext *c) (c->compression == 2 && !c->epic_buf_base) || c->old_tile_w < c->tile_width || c->old_tile_h < c->tile_height) { - c->tile_stride = FFALIGN(c->tile_width * 3, 16); + c->tile_stride = FFALIGN(c->tile_width, 16) * 3; c->epic_buf_stride = FFALIGN(c->tile_width * 4, 16); aligned_height = FFALIGN(c->tile_height, 16); av_free(c->synth_tile); @@ -1213,7 +1222,7 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, cursor_hot_y = bytestream2_get_byte(gb); cursor_fmt = bytestream2_get_byte(gb); - cursor_stride = FFALIGN(cursor_w, 32) * 4; + cursor_stride = FFALIGN(cursor_w, cursor_fmt==1 ? 32 : 1) * 4; if (cursor_w < 1 || cursor_w > 256 || cursor_h < 1 || cursor_h > 256) { @@ -1263,7 +1272,6 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, bits <<= 1; } } - dst += c->cursor_stride - c->cursor_w * 4; } dst = c->cursor; @@ -1295,7 +1303,6 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, bits <<= 1; } } - dst += c->cursor_stride - c->cursor_w * 4; } break; case 32: // full colour @@ -1309,7 +1316,6 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, *dst++ = val >> 16; *dst++ = val >> 24; } - dst += c->cursor_stride - c->cursor_w * 4; } break; default: @@ -1412,6 +1418,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, } switch (chunk_type) { case DISPLAY_INFO: + got_header = c->got_header = 0; if (chunk_size < 21) { av_log(avctx, AV_LOG_ERROR, "Invalid display info size %"PRIu32"\n", @@ -1431,19 +1438,22 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, if (c->width != avctx->width || c->height != avctx->height) { ret = ff_set_dimensions(avctx, c->width, c->height); if (ret < 0) - return ret; + goto header_fail; } c->compression = bytestream2_get_be32(&bc); if (c->compression != 2 && c->compression != 3) { av_log(avctx, AV_LOG_ERROR, "Unknown compression method %d\n", c->compression); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto header_fail; } c->tile_width = bytestream2_get_be32(&bc); c->tile_height = bytestream2_get_be32(&bc); - if (!c->tile_width || !c->tile_height || - ((c->tile_width | c->tile_height) & 0xF)) { + if (c->tile_width <= 0 || c->tile_height <= 0 || + ((c->tile_width | c->tile_height) & 0xF) || + c->tile_width * 4LL * c->tile_height >= INT_MAX + ) { av_log(avctx, AV_LOG_ERROR, "Invalid tile dimensions %dx%d\n", c->tile_width, c->tile_height); @@ -1458,7 +1468,8 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, (chunk_size - 21) < 16) { av_log(avctx, AV_LOG_ERROR, "Display info: missing bitmasks!\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto header_fail; } r_mask = bytestream2_get_be32(&bc); g_mask = bytestream2_get_be32(&bc); @@ -1467,11 +1478,13 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "Invalid or unsupported bitmasks: R=%"PRIX32", G=%"PRIX32", B=%"PRIX32"\n", r_mask, g_mask, b_mask); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto header_fail; } } else { avpriv_request_sample(avctx, "bpp=%d", c->bpp); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto header_fail; } if (g2m_init_buffers(c)) { ret = AVERROR(ENOMEM); @@ -1548,11 +1561,9 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, if (got_header) c->got_header = 1; - if (c->width && c->height) { - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + if (c->width && c->height && c->framebuf) { + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) return ret; - } pic->key_frame = got_header; pic->pict_type = got_header ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; |