diff options
Diffstat (limited to 'libavcodec/g2meet.c')
-rw-r--r-- | libavcodec/g2meet.c | 58 |
1 files changed, 32 insertions, 26 deletions
diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 33934f1..67bb1fd 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -2,20 +2,20 @@ * Go2Webinar decoder * Copyright (c) 2012 Konstantin Shishkov * - * 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 */ @@ -384,6 +384,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) { @@ -400,7 +402,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); @@ -422,6 +424,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; } @@ -455,17 +459,17 @@ 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); } if (!c->synth_tile || !c->jpeg_tile || 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; aligned_height = FFALIGN(c->tile_height, 16); av_free(c->synth_tile); av_free(c->jpeg_tile); @@ -501,7 +505,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) { @@ -551,7 +555,6 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, bits <<= 1; } } - dst += c->cursor_stride - c->cursor_w * 4; } dst = c->cursor; @@ -583,7 +586,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 @@ -597,7 +599,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: @@ -682,12 +683,12 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, magic = bytestream2_get_be32(&bc); if ((magic & ~0xF) != MKBETAG('G', '2', 'M', '0') || - (magic & 0xF) < 2 || (magic & 0xF) > 4) { + (magic & 0xF) < 2 || (magic & 0xF) > 5) { av_log(avctx, AV_LOG_ERROR, "Wrong magic %08X\n", magic); return AVERROR_INVALIDDATA; } - if ((magic & 0xF) != 4) { + if ((magic & 0xF) < 4) { av_log(avctx, AV_LOG_ERROR, "G2M2 and G2M3 are not yet supported\n"); return AVERROR(ENOSYS); } @@ -703,6 +704,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", @@ -722,19 +724,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); @@ -749,7 +754,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); @@ -758,11 +764,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); @@ -838,11 +846,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; |