diff options
Diffstat (limited to 'libavcodec/g2meet.c')
-rw-r--r-- | libavcodec/g2meet.c | 84 |
1 files changed, 52 insertions, 32 deletions
diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index a89610d6c3..2815704997 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, AV_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; @@ -554,6 +555,11 @@ static uint32_t epic_decode_pixel_pred(ePICContext *dc, int x, int y, B = ((pred >> B_shift) & 0xFF) - TOSIGNED(delta); } + if (R<0 || G<0 || B<0) { + av_log(NULL, AV_LOG_ERROR, "RGB %d %d %d is out of range\n", R, G, B); + return 0; + } + return (R << R_shift) | (G << G_shift) | (B << B_shift); } @@ -1005,7 +1011,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, @@ -1013,9 +1019,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; @@ -1034,6 +1042,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, @@ -1077,6 +1087,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) { @@ -1093,7 +1105,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); @@ -1115,6 +1127,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; } @@ -1148,10 +1162,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); } @@ -1159,14 +1173,15 @@ 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); - av_free(c->jpeg_tile); - av_free(c->kempf_buf); - av_free(c->kempf_flags); - av_free(c->epic_buf_base); + av_freep(&c->synth_tile); + av_freep(&c->jpeg_tile); + av_freep(&c->kempf_buf); + av_freep(&c->kempf_flags); + av_freep(&c->epic_buf_base); + c->epic_buf = NULL; c->synth_tile = av_mallocz(c->tile_stride * aligned_height); c->jpeg_tile = av_mallocz(c->tile_stride * aligned_height); c->kempf_buf = av_mallocz((c->tile_width + 1) * aligned_height + @@ -1203,7 +1218,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) { @@ -1253,7 +1268,6 @@ static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, bits <<= 1; } } - dst += c->cursor_stride - c->cursor_w * 4; } dst = c->cursor; @@ -1285,7 +1299,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 @@ -1299,7 +1312,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: @@ -1402,6 +1414,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", @@ -1420,19 +1433,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 * (uint64_t)c->tile_height >= INT_MAX / 4 + ) { av_log(avctx, AV_LOG_ERROR, "Invalid tile dimensions %dx%d\n", c->tile_width, c->tile_height); @@ -1447,7 +1463,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); @@ -1456,11 +1473,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); @@ -1537,11 +1556,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; @@ -1562,6 +1579,8 @@ header_fail: c->height = 0; c->tiles_x = c->tiles_y = 0; + c->tile_width = + c->tile_height = 0; return ret; } @@ -1592,6 +1611,7 @@ static av_cold int g2m_decode_end(AVCodecContext *avctx) jpg_free_context(&c->jc); av_freep(&c->epic_buf_base); + c->epic_buf = NULL; av_freep(&c->kempf_buf); av_freep(&c->kempf_flags); av_freep(&c->synth_tile); |