diff options
author | Kostya Shishkov <kostya.shishkov@gmail.com> | 2013-06-11 19:07:38 +0200 |
---|---|---|
committer | Kostya Shishkov <kostya.shishkov@gmail.com> | 2013-06-12 09:54:45 +0200 |
commit | 4d960d7f60f96c24e0a9bb8224c83a7cfa4f26d4 (patch) | |
tree | af3e8bf6408f5cc7dc8e9285ac3246a273a5b34f /libavcodec/g2meet.c | |
parent | 767ae86ceeae9c29ed6e62066e9577f0b0598650 (diff) | |
download | ffmpeg-4d960d7f60f96c24e0a9bb8224c83a7cfa4f26d4.tar.gz |
g2meet: more graceful cursor loading
Diffstat (limited to 'libavcodec/g2meet.c')
-rw-r--r-- | libavcodec/g2meet.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index d0a4302fd7..f7a8501ca4 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -468,16 +468,63 @@ static int g2m_init_buffers(G2MContext *c) return 0; } -static int g2m_load_cursor(G2MContext *c, GetByteContext *gb) +static int g2m_load_cursor(AVCodecContext *avctx, G2MContext *c, + GetByteContext *gb) { int i, j, k; uint8_t *dst; uint32_t bits; + uint32_t cur_size, cursor_w, cursor_h, cursor_stride; + uint32_t cursor_hot_x, cursor_hot_y; + int cursor_fmt; + uint8_t *tmp; - c->cursor_stride = c->cursor_w * 4; - c->cursor = av_realloc(c->cursor, c->cursor_stride * c->cursor_h); - if (!c->cursor) + cur_size = bytestream2_get_be32(gb); + cursor_w = bytestream2_get_byte(gb); + cursor_h = bytestream2_get_byte(gb); + cursor_hot_x = bytestream2_get_byte(gb); + cursor_hot_y = bytestream2_get_byte(gb); + cursor_fmt = bytestream2_get_byte(gb); + + cursor_stride = cursor_w * 4; + + if (cursor_w < 1 || cursor_w > 256 || + cursor_h < 1 || cursor_h > 256) { + av_log(avctx, AV_LOG_ERROR, "Invalid cursor dimensions %dx%d\n", + cursor_w, cursor_h); + return AVERROR_INVALIDDATA; + } + if (cursor_hot_x > cursor_w || cursor_hot_y > cursor_h) { + av_log(avctx, AV_LOG_WARNING, "Invalid hotspot position %d,%d\n", + cursor_hot_x, cursor_hot_y); + cursor_hot_x = FFMIN(cursor_hot_x, cursor_w - 1); + cursor_hot_y = FFMIN(cursor_hot_y, cursor_h - 1); + } + if (cur_size - 9 > bytestream2_get_bytes_left(gb) || + c->cursor_w * c->cursor_h / 4 > cur_size) { + av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d/%d\n", + cur_size, bytestream2_get_bytes_left(gb)); + return AVERROR_INVALIDDATA; + } + if (cursor_fmt != 1 && cursor_fmt != 32) { + avpriv_report_missing_feature(avctx, "Cursor format %d", + cursor_fmt); + return AVERROR_PATCHWELCOME; + } + + tmp = av_realloc(c->cursor, cursor_stride * cursor_h); + if (!tmp) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate cursor buffer\n"); return AVERROR(ENOMEM); + } + + c->cursor = tmp; + c->cursor_w = cursor_w; + c->cursor_h = cursor_h; + c->cursor_hot_x = cursor_hot_x; + c->cursor_hot_y = cursor_hot_y; + c->cursor_fmt = cursor_fmt; + c->cursor_stride = cursor_stride; dst = c->cursor; switch (c->cursor_fmt) { @@ -597,7 +644,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, GetByteContext bc, tbc; int magic; int got_header = 0; - uint32_t chunk_size, cur_size; + uint32_t chunk_size; int chunk_type; int i; int ret; @@ -734,19 +781,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data, } bytestream2_init(&tbc, buf + bytestream2_tell(&bc), chunk_size - 4); - cur_size = bytestream2_get_be32(&tbc); - c->cursor_w = bytestream2_get_byte(&tbc); - c->cursor_h = bytestream2_get_byte(&tbc); - c->cursor_hot_x = bytestream2_get_byte(&tbc); - c->cursor_hot_y = bytestream2_get_byte(&tbc); - c->cursor_fmt = bytestream2_get_byte(&tbc); - if (cur_size >= chunk_size || - c->cursor_w * c->cursor_h / 4 > cur_size) { - av_log(avctx, AV_LOG_ERROR, "Invalid cursor data size %d\n", - chunk_size); - break; - } - g2m_load_cursor(c, &tbc); + g2m_load_cursor(avctx, c, &tbc); bytestream2_skip(&bc, chunk_size); break; case CHUNK_CC: |