mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
dfa: convert to bytestream2 API
Protects from overreads. Signed-off-by: Paul B Mahol <onemda@gmail.com> Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
This commit is contained in:
parent
015da6e394
commit
29b0d94b43
163
libavcodec/dfa.c
163
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)
|
||||
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*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;
|
||||
|
Loading…
Reference in New Issue
Block a user