From 29b0d94b43ac960cb442049a5d737a3386ff0337 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 13 Mar 2012 01:58:12 +0000 Subject: dfa: convert to bytestream2 API Protects from overreads. Signed-off-by: Paul B Mahol Signed-off-by: Ronald S. Bultje --- libavcodec/dfa.c | 163 +++++++++++++++++++++++++------------------------------ 1 file changed, 74 insertions(+), 89 deletions(-) (limited to 'libavcodec/dfa.c') diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 08bb2a4934..05bc92f1d8 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -21,7 +21,6 @@ */ #include "avcodec.h" -#include "libavutil/intreadwrite.h" #include "bytestream.h" #include "libavutil/lzo.h" // for av_memcpy_backptr @@ -45,19 +44,16 @@ static av_cold int dfa_decode_init(AVCodecContext *avctx) return 0; } -static int decode_copy(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height) { const int size = width * height; - if (src_end - src < size) + if (bytestream2_get_buffer(gb, frame, size) != size) return -1; - bytestream_get_buffer(&src, frame, size); return 0; } -static int decode_tsw1(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_start = frame; const uint8_t *frame_end = frame + width * height; @@ -65,22 +61,22 @@ static int decode_tsw1(uint8_t *frame, int width, int height, int v, count, segments; unsigned offset; - segments = bytestream_get_le32(&src); - offset = bytestream_get_le32(&src); + segments = bytestream2_get_le32(gb); + offset = bytestream2_get_le32(gb); if (frame_end - frame <= offset) return -1; frame += offset; while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return -1; if (mask == 0x10000) { - if (src >= src_end) - return -1; - bitbuf = bytestream_get_le16(&src); + bitbuf = bytestream2_get_le16u(gb); mask = 1; } - if (src_end - src < 2 || frame_end - frame < 2) + if (frame_end - frame < 2) return -1; if (bitbuf & mask) { - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); offset = (v & 0x1FFF) << 1; count = ((v >> 13) + 2) << 1; if (frame - frame_start < offset || frame_end - frame < count) @@ -88,8 +84,8 @@ static int decode_tsw1(uint8_t *frame, int width, int height, av_memcpy_backptr(frame, offset, count); frame += count; } else { - *frame++ = *src++; - *frame++ = *src++; + *frame++ = bytestream2_get_byte(gb); + *frame++ = bytestream2_get_byte(gb); } mask <<= 1; } @@ -97,26 +93,25 @@ static int decode_tsw1(uint8_t *frame, int width, int height, return 0; } -static int decode_dsw1(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_start = frame; const uint8_t *frame_end = frame + width * height; int mask = 0x10000, bitbuf = 0; int v, offset, count, segments; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return -1; if (mask == 0x10000) { - if (src >= src_end) - return -1; - bitbuf = bytestream_get_le16(&src); + bitbuf = bytestream2_get_le16u(gb); mask = 1; } - if (src_end - src < 2 || frame_end - frame < 2) + if (frame_end - frame < 2) return -1; if (bitbuf & mask) { - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); offset = (v & 0x1FFF) << 1; count = ((v >> 13) + 2) << 1; if (frame - frame_start < offset || frame_end - frame < count) @@ -126,10 +121,10 @@ static int decode_dsw1(uint8_t *frame, int width, int height, frame[v] = frame[v - offset]; frame += count; } else if (bitbuf & (mask << 1)) { - frame += bytestream_get_le16(&src); + frame += bytestream2_get_le16(gb); } else { - *frame++ = *src++; - *frame++ = *src++; + *frame++ = bytestream2_get_byte(gb); + *frame++ = bytestream2_get_byte(gb); } mask <<= 2; } @@ -137,26 +132,25 @@ static int decode_dsw1(uint8_t *frame, int width, int height, return 0; } -static int decode_dds1(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_start = frame; const uint8_t *frame_end = frame + width * height; int mask = 0x10000, bitbuf = 0; int i, v, offset, count, segments; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return -1; if (mask == 0x10000) { - if (src >= src_end) - return -1; - bitbuf = bytestream_get_le16(&src); + bitbuf = bytestream2_get_le16u(gb); mask = 1; } - if (src_end - src < 2 || frame_end - frame < 2) + if (frame_end - frame < 2) return -1; if (bitbuf & mask) { - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); offset = (v & 0x1FFF) << 2; count = ((v >> 13) + 2) << 1; if (frame - frame_start < offset || frame_end - frame < count*2 + width) @@ -168,13 +162,13 @@ static int decode_dds1(uint8_t *frame, int width, int height, frame += 2; } } else if (bitbuf & (mask << 1)) { - frame += bytestream_get_le16(&src) * 2; + frame += bytestream2_get_le16(gb) * 2; } else { frame[0] = frame[1] = - frame[width] = frame[width + 1] = *src++; + frame[width] = frame[width + 1] = bytestream2_get_byte(gb); frame += 2; frame[0] = frame[1] = - frame[width] = frame[width + 1] = *src++; + frame[width] = frame[width + 1] = bytestream2_get_byte(gb); frame += 2; } mask <<= 2; @@ -183,40 +177,40 @@ static int decode_dds1(uint8_t *frame, int width, int height, return 0; } -static int decode_bdlt(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height) { uint8_t *line_ptr; int count, lines, segments; - count = bytestream_get_le16(&src); + count = bytestream2_get_le16(gb); if (count >= height) return -1; frame += width * count; - lines = bytestream_get_le16(&src); - if (count + lines > height || src >= src_end) + lines = bytestream2_get_le16(gb); + if (count + lines > height) return -1; while (lines--) { + if (bytestream2_get_bytes_left(gb) < 1) + return -1; line_ptr = frame; frame += width; - segments = *src++; + segments = bytestream2_get_byteu(gb); while (segments--) { - if (src_end - src < 3) + if (frame - line_ptr <= bytestream2_peek_byte(gb)) return -1; - if (frame - line_ptr <= *src) - return -1; - line_ptr += *src++; - count = (int8_t)*src++; + line_ptr += bytestream2_get_byte(gb); + count = (int8_t)bytestream2_get_byte(gb); if (count >= 0) { - if (frame - line_ptr < count || src_end - src < count) + if (frame - line_ptr < count) + return -1; + if (bytestream2_get_buffer(gb, line_ptr, count) != count) return -1; - bytestream_get_buffer(&src, line_ptr, count); } else { count = -count; - if (frame - line_ptr < count || src >= src_end) + if (frame - line_ptr < count) return -1; - memset(line_ptr, *src++, count); + memset(line_ptr, bytestream2_get_byte(gb), count); } line_ptr += count; } @@ -225,49 +219,49 @@ static int decode_bdlt(uint8_t *frame, int width, int height, return 0; } -static int decode_wdlt(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_end = frame + width * height; uint8_t *line_ptr; int count, i, v, lines, segments; - lines = bytestream_get_le16(&src); - if (lines > height || src >= src_end) + lines = bytestream2_get_le16(gb); + if (lines > height) return -1; while (lines--) { - segments = bytestream_get_le16(&src); + if (bytestream2_get_bytes_left(gb) < 2) + return -1; + segments = bytestream2_get_le16u(gb); while ((segments & 0xC000) == 0xC000) { unsigned delta = -((int16_t)segments * width); if (frame_end - frame <= delta) return -1; frame += delta; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); } if (segments & 0x8000) { frame[width - 1] = segments & 0xFF; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); } line_ptr = frame; frame += width; while (segments--) { - if (src_end - src < 2) - return -1; - if (frame - line_ptr <= *src) + if (frame - line_ptr <= bytestream2_peek_byte(gb)) return -1; - line_ptr += *src++; - count = (int8_t)*src++; + line_ptr += bytestream2_get_byte(gb); + count = (int8_t)bytestream2_get_byte(gb); if (count >= 0) { - if (frame - line_ptr < count*2 || src_end - src < count*2) + if (frame - line_ptr < count * 2) + return -1; + if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2) return -1; - bytestream_get_buffer(&src, line_ptr, count*2); line_ptr += count * 2; } else { count = -count; - if (frame - line_ptr < count*2 || src_end - src < 2) + if (frame - line_ptr < count * 2) return -1; - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); for (i = 0; i < count; i++) bytestream_put_le16(&line_ptr, v); } @@ -277,22 +271,19 @@ static int decode_wdlt(uint8_t *frame, int width, int height, return 0; } -static int decode_unk6(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_unk6(GetByteContext *gb, uint8_t *frame, int width, int height) { return -1; } -static int decode_blck(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height) { memset(frame, 0, width * height); return 0; } -typedef int (*chunk_decoder)(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end); +typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height); static const chunk_decoder decoder[8] = { decode_copy, decode_tsw1, decode_bdlt, decode_wdlt, @@ -308,9 +299,8 @@ static int dfa_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { DfaContext *s = avctx->priv_data; + GetByteContext gb; const uint8_t *buf = avpkt->data; - const uint8_t *buf_end = avpkt->data + avpkt->size; - const uint8_t *tmp_buf; uint32_t chunk_type, chunk_size; uint8_t *dst; int ret; @@ -324,27 +314,22 @@ static int dfa_decode_frame(AVCodecContext *avctx, return ret; } - while (buf < buf_end) { - chunk_size = AV_RL32(buf + 4); - chunk_type = AV_RL32(buf + 8); - buf += 12; - if (buf_end - buf < chunk_size) { - av_log(avctx, AV_LOG_ERROR, "Chunk size is too big (%d bytes)\n", chunk_size); - return -1; - } + bytestream2_init(&gb, avpkt->data, avpkt->size); + while (bytestream2_get_bytes_left(&gb) > 0) { + bytestream2_skip(&gb, 4); + chunk_size = bytestream2_get_le32(&gb); + chunk_type = bytestream2_get_le32(&gb); if (!chunk_type) break; if (chunk_type == 1) { pal_elems = FFMIN(chunk_size / 3, 256); - tmp_buf = buf; for (i = 0; i < pal_elems; i++) { - s->pal[i] = bytestream_get_be24(&tmp_buf) << 2; + s->pal[i] = bytestream2_get_be24(&gb) << 2; s->pal[i] |= (s->pal[i] >> 6) & 0x333; } s->pic.palette_has_changed = 1; } else if (chunk_type <= 9) { - if (decoder[chunk_type - 2](s->frame_buf, avctx->width, avctx->height, - buf, buf + chunk_size)) { + if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n", chunk_name[chunk_type - 2]); return -1; -- cgit v1.2.3