lavc/pngdec: use a separate bytestream reader for each chunk
This makes sure that reading a truncated chunk will never overflow into the following chunk. It also allows to remove many repeated lines skipping over the trailing crc checksum.
This commit is contained in:
@@ -421,13 +421,12 @@ the_end:;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int png_decode_idat(PNGDecContext *s, int length,
|
static int png_decode_idat(PNGDecContext *s, GetByteContext *gb,
|
||||||
uint8_t *dst, ptrdiff_t dst_stride)
|
uint8_t *dst, ptrdiff_t dst_stride)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
|
s->zstream.avail_in = bytestream2_get_bytes_left(gb);
|
||||||
s->zstream.next_in = s->gb.buffer;
|
s->zstream.next_in = gb->buffer;
|
||||||
bytestream2_skip(&s->gb, length);
|
|
||||||
|
|
||||||
/* decode one line if possible */
|
/* decode one line if possible */
|
||||||
while (s->zstream.avail_in > 0) {
|
while (s->zstream.avail_in > 0) {
|
||||||
@@ -520,11 +519,11 @@ static uint8_t *iso88591_to_utf8(const uint8_t *in, size_t size_in)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed)
|
static int decode_text_chunk(PNGDecContext *s, GetByteContext *gb, int compressed)
|
||||||
{
|
{
|
||||||
int ret, method;
|
int ret, method;
|
||||||
const uint8_t *data = s->gb.buffer;
|
const uint8_t *data = gb->buffer;
|
||||||
const uint8_t *data_end = data + length;
|
const uint8_t *data_end = gb->buffer_end;
|
||||||
const uint8_t *keyword = data;
|
const uint8_t *keyword = data;
|
||||||
const uint8_t *keyword_end = memchr(keyword, 0, data_end - keyword);
|
const uint8_t *keyword_end = memchr(keyword, 0, data_end - keyword);
|
||||||
uint8_t *kw_utf8 = NULL, *text, *txt_utf8 = NULL;
|
uint8_t *kw_utf8 = NULL, *text, *txt_utf8 = NULL;
|
||||||
@@ -568,9 +567,9 @@ static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||||
uint32_t length)
|
GetByteContext *gb)
|
||||||
{
|
{
|
||||||
if (length != 13)
|
if (bytestream2_get_bytes_left(gb) != 13)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
if (s->pic_state & PNG_IDAT) {
|
if (s->pic_state & PNG_IDAT) {
|
||||||
@@ -583,28 +582,27 @@ static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->width = s->cur_w = bytestream2_get_be32(&s->gb);
|
s->width = s->cur_w = bytestream2_get_be32(gb);
|
||||||
s->height = s->cur_h = bytestream2_get_be32(&s->gb);
|
s->height = s->cur_h = bytestream2_get_be32(gb);
|
||||||
if (av_image_check_size(s->width, s->height, 0, avctx)) {
|
if (av_image_check_size(s->width, s->height, 0, avctx)) {
|
||||||
s->cur_w = s->cur_h = s->width = s->height = 0;
|
s->cur_w = s->cur_h = s->width = s->height = 0;
|
||||||
av_log(avctx, AV_LOG_ERROR, "Invalid image size\n");
|
av_log(avctx, AV_LOG_ERROR, "Invalid image size\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
s->bit_depth = bytestream2_get_byte(&s->gb);
|
s->bit_depth = bytestream2_get_byte(gb);
|
||||||
if (s->bit_depth != 1 && s->bit_depth != 2 && s->bit_depth != 4 &&
|
if (s->bit_depth != 1 && s->bit_depth != 2 && s->bit_depth != 4 &&
|
||||||
s->bit_depth != 8 && s->bit_depth != 16) {
|
s->bit_depth != 8 && s->bit_depth != 16) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Invalid bit depth\n");
|
av_log(avctx, AV_LOG_ERROR, "Invalid bit depth\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
s->color_type = bytestream2_get_byte(&s->gb);
|
s->color_type = bytestream2_get_byte(gb);
|
||||||
s->compression_type = bytestream2_get_byte(&s->gb);
|
s->compression_type = bytestream2_get_byte(gb);
|
||||||
if (s->compression_type) {
|
if (s->compression_type) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Invalid compression method %d\n", s->compression_type);
|
av_log(avctx, AV_LOG_ERROR, "Invalid compression method %d\n", s->compression_type);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
s->filter_type = bytestream2_get_byte(&s->gb);
|
s->filter_type = bytestream2_get_byte(gb);
|
||||||
s->interlace_type = bytestream2_get_byte(&s->gb);
|
s->interlace_type = bytestream2_get_byte(gb);
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
s->hdr_state |= PNG_IHDR;
|
s->hdr_state |= PNG_IHDR;
|
||||||
if (avctx->debug & FF_DEBUG_PICT_INFO)
|
if (avctx->debug & FF_DEBUG_PICT_INFO)
|
||||||
av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d "
|
av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d "
|
||||||
@@ -619,24 +617,24 @@ error:
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s)
|
static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||||
|
GetByteContext *gb)
|
||||||
{
|
{
|
||||||
if (s->pic_state & PNG_IDAT) {
|
if (s->pic_state & PNG_IDAT) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n");
|
av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
avctx->sample_aspect_ratio.num = bytestream2_get_be32(&s->gb);
|
avctx->sample_aspect_ratio.num = bytestream2_get_be32(gb);
|
||||||
avctx->sample_aspect_ratio.den = bytestream2_get_be32(&s->gb);
|
avctx->sample_aspect_ratio.den = bytestream2_get_be32(gb);
|
||||||
if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.den < 0)
|
if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.den < 0)
|
||||||
avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
|
avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
|
||||||
bytestream2_skip(&s->gb, 1); /* unit specifier */
|
bytestream2_skip(gb, 1); /* unit specifier */
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||||
uint32_t length, AVFrame *p)
|
GetByteContext *gb, AVFrame *p)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
size_t byte_depth = s->bit_depth > 8 ? 2 : 1;
|
size_t byte_depth = s->bit_depth > 8 ? 2 : 1;
|
||||||
@@ -773,7 +771,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
|
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||||
s->bpp -= byte_depth;
|
s->bpp -= byte_depth;
|
||||||
|
|
||||||
ret = png_decode_idat(s, length, p->data[0], p->linesize[0]);
|
ret = png_decode_idat(s, gb, p->data[0], p->linesize[0]);
|
||||||
|
|
||||||
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
|
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||||
s->bpp += byte_depth;
|
s->bpp += byte_depth;
|
||||||
@@ -781,14 +779,13 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_plte_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
static int decode_plte_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||||
uint32_t length)
|
GetByteContext *gb)
|
||||||
{
|
{
|
||||||
|
int length = bytestream2_get_bytes_left(gb);
|
||||||
int n, i, r, g, b;
|
int n, i, r, g, b;
|
||||||
|
|
||||||
if ((length % 3) != 0 || length > 256 * 3)
|
if ((length % 3) != 0 || length > 256 * 3)
|
||||||
@@ -796,22 +793,22 @@ static int decode_plte_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
/* read the palette */
|
/* read the palette */
|
||||||
n = length / 3;
|
n = length / 3;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
r = bytestream2_get_byte(&s->gb);
|
r = bytestream2_get_byte(gb);
|
||||||
g = bytestream2_get_byte(&s->gb);
|
g = bytestream2_get_byte(gb);
|
||||||
b = bytestream2_get_byte(&s->gb);
|
b = bytestream2_get_byte(gb);
|
||||||
s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b;
|
s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
for (; i < 256; i++)
|
for (; i < 256; i++)
|
||||||
s->palette[i] = (0xFFU << 24);
|
s->palette[i] = (0xFFU << 24);
|
||||||
s->hdr_state |= PNG_PLTE;
|
s->hdr_state |= PNG_PLTE;
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||||
uint32_t length)
|
GetByteContext *gb)
|
||||||
{
|
{
|
||||||
|
int length = bytestream2_get_bytes_left(gb);
|
||||||
int v, i;
|
int v, i;
|
||||||
|
|
||||||
if (!(s->hdr_state & PNG_IHDR)) {
|
if (!(s->hdr_state & PNG_IHDR)) {
|
||||||
@@ -829,7 +826,7 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
unsigned v = bytestream2_get_byte(&s->gb);
|
unsigned v = bytestream2_get_byte(gb);
|
||||||
s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
|
s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
|
||||||
}
|
}
|
||||||
} else if (s->color_type == PNG_COLOR_TYPE_GRAY || s->color_type == PNG_COLOR_TYPE_RGB) {
|
} else if (s->color_type == PNG_COLOR_TYPE_GRAY || s->color_type == PNG_COLOR_TYPE_RGB) {
|
||||||
@@ -840,7 +837,7 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
|
|
||||||
for (i = 0; i < length / 2; i++) {
|
for (i = 0; i < length / 2; i++) {
|
||||||
/* only use the least significant bits */
|
/* only use the least significant bits */
|
||||||
v = av_mod_uintp2(bytestream2_get_be16(&s->gb), s->bit_depth);
|
v = av_mod_uintp2(bytestream2_get_be16(gb), s->bit_depth);
|
||||||
|
|
||||||
if (s->bit_depth > 8)
|
if (s->bit_depth > 8)
|
||||||
AV_WB16(&s->transparent_color_be[2 * i], v);
|
AV_WB16(&s->transparent_color_be[2 * i], v);
|
||||||
@@ -851,35 +848,30 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
s->has_trns = 1;
|
s->has_trns = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f)
|
static int decode_iccp_chunk(PNGDecContext *s, GetByteContext *gb, AVFrame *f)
|
||||||
{
|
{
|
||||||
int ret, cnt = 0;
|
int ret, cnt = 0;
|
||||||
AVBPrint bp;
|
AVBPrint bp;
|
||||||
|
|
||||||
while ((s->iccp_name[cnt++] = bytestream2_get_byte(&s->gb)) && cnt < 81);
|
while ((s->iccp_name[cnt++] = bytestream2_get_byte(gb)) && cnt < 81);
|
||||||
if (cnt > 80) {
|
if (cnt > 80) {
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid name!\n");
|
av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid name!\n");
|
||||||
ret = AVERROR_INVALIDDATA;
|
ret = AVERROR_INVALIDDATA;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = FFMAX(length - cnt, 0);
|
if (bytestream2_get_byte(gb) != 0) {
|
||||||
|
|
||||||
if (bytestream2_get_byte(&s->gb) != 0) {
|
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid compression!\n");
|
av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid compression!\n");
|
||||||
ret = AVERROR_INVALIDDATA;
|
ret = AVERROR_INVALIDDATA;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = FFMAX(length - 1, 0);
|
if ((ret = decode_zbuf(&bp, gb->buffer, gb->buffer_end)) < 0)
|
||||||
|
|
||||||
if ((ret = decode_zbuf(&bp, s->gb.buffer, s->gb.buffer + length)) < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
av_freep(&s->iccp_data);
|
av_freep(&s->iccp_data);
|
||||||
@@ -888,9 +880,6 @@ static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f)
|
|||||||
return ret;
|
return ret;
|
||||||
s->iccp_data_len = bp.len;
|
s->iccp_data_len = bp.len;
|
||||||
|
|
||||||
/* ICC compressed data and CRC */
|
|
||||||
bytestream2_skip(&s->gb, length + 4);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
s->iccp_name[0] = 0;
|
s->iccp_name[0] = 0;
|
||||||
@@ -971,12 +960,12 @@ static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||||
uint32_t length)
|
GetByteContext *gb)
|
||||||
{
|
{
|
||||||
uint32_t sequence_number;
|
uint32_t sequence_number;
|
||||||
int cur_w, cur_h, x_offset, y_offset, dispose_op, blend_op;
|
int cur_w, cur_h, x_offset, y_offset, dispose_op, blend_op;
|
||||||
|
|
||||||
if (length != 26)
|
if (bytestream2_get_bytes_left(gb) != 26)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
if (!(s->hdr_state & PNG_IHDR)) {
|
if (!(s->hdr_state & PNG_IHDR)) {
|
||||||
@@ -995,15 +984,14 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
s->last_y_offset = s->y_offset;
|
s->last_y_offset = s->y_offset;
|
||||||
s->last_dispose_op = s->dispose_op;
|
s->last_dispose_op = s->dispose_op;
|
||||||
|
|
||||||
sequence_number = bytestream2_get_be32(&s->gb);
|
sequence_number = bytestream2_get_be32(gb);
|
||||||
cur_w = bytestream2_get_be32(&s->gb);
|
cur_w = bytestream2_get_be32(gb);
|
||||||
cur_h = bytestream2_get_be32(&s->gb);
|
cur_h = bytestream2_get_be32(gb);
|
||||||
x_offset = bytestream2_get_be32(&s->gb);
|
x_offset = bytestream2_get_be32(gb);
|
||||||
y_offset = bytestream2_get_be32(&s->gb);
|
y_offset = bytestream2_get_be32(gb);
|
||||||
bytestream2_skip(&s->gb, 4); /* delay_num (2), delay_den (2) */
|
bytestream2_skip(gb, 4); /* delay_num (2), delay_den (2) */
|
||||||
dispose_op = bytestream2_get_byte(&s->gb);
|
dispose_op = bytestream2_get_byte(gb);
|
||||||
blend_op = bytestream2_get_byte(&s->gb);
|
blend_op = bytestream2_get_byte(gb);
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
|
|
||||||
if (sequence_number == 0 &&
|
if (sequence_number == 0 &&
|
||||||
(cur_w != s->width ||
|
(cur_w != s->width ||
|
||||||
@@ -1194,6 +1182,8 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
GetByteContext gb_chunk;
|
||||||
|
|
||||||
length = bytestream2_get_bytes_left(&s->gb);
|
length = bytestream2_get_bytes_left(&s->gb);
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
|
|
||||||
@@ -1233,8 +1223,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
av_log(avctx, AV_LOG_ERROR, ", skipping\n");
|
av_log(avctx, AV_LOG_ERROR, ", skipping\n");
|
||||||
bytestream2_skip(&s->gb, 4); /* tag */
|
bytestream2_skip(&s->gb, length + 8); /* tag */
|
||||||
goto skip_tag;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tag = bytestream2_get_le32(&s->gb);
|
tag = bytestream2_get_le32(&s->gb);
|
||||||
@@ -1242,6 +1231,9 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
av_log(avctx, AV_LOG_DEBUG, "png: tag=%s length=%u\n",
|
av_log(avctx, AV_LOG_DEBUG, "png: tag=%s length=%u\n",
|
||||||
av_fourcc2str(tag), length);
|
av_fourcc2str(tag), length);
|
||||||
|
|
||||||
|
bytestream2_init(&gb_chunk, s->gb.buffer, length);
|
||||||
|
bytestream2_skip(&s->gb, length + 4);
|
||||||
|
|
||||||
if (avctx->codec_id == AV_CODEC_ID_PNG &&
|
if (avctx->codec_id == AV_CODEC_ID_PNG &&
|
||||||
avctx->skip_frame == AVDISCARD_ALL) {
|
avctx->skip_frame == AVDISCARD_ALL) {
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
@@ -1252,62 +1244,57 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
case MKTAG('t', 'R', 'N', 'S'):
|
case MKTAG('t', 'R', 'N', 'S'):
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto skip_tag;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case MKTAG('I', 'H', 'D', 'R'):
|
case MKTAG('I', 'H', 'D', 'R'):
|
||||||
if ((ret = decode_ihdr_chunk(avctx, s, length)) < 0)
|
if ((ret = decode_ihdr_chunk(avctx, s, &gb_chunk)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
case MKTAG('p', 'H', 'Y', 's'):
|
case MKTAG('p', 'H', 'Y', 's'):
|
||||||
if ((ret = decode_phys_chunk(avctx, s)) < 0)
|
if ((ret = decode_phys_chunk(avctx, s, &gb_chunk)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
case MKTAG('f', 'c', 'T', 'L'):
|
case MKTAG('f', 'c', 'T', 'L'):
|
||||||
if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
|
if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
|
||||||
goto skip_tag;
|
continue;
|
||||||
if ((ret = decode_fctl_chunk(avctx, s, length)) < 0)
|
if ((ret = decode_fctl_chunk(avctx, s, &gb_chunk)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
decode_next_dat = 1;
|
decode_next_dat = 1;
|
||||||
break;
|
break;
|
||||||
case MKTAG('f', 'd', 'A', 'T'):
|
case MKTAG('f', 'd', 'A', 'T'):
|
||||||
if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
|
if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
|
||||||
goto skip_tag;
|
continue;
|
||||||
if (!decode_next_dat || length < 4) {
|
if (!decode_next_dat || bytestream2_get_bytes_left(&gb_chunk) < 4) {
|
||||||
ret = AVERROR_INVALIDDATA;
|
ret = AVERROR_INVALIDDATA;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
bytestream2_get_be32(&s->gb);
|
bytestream2_get_be32(&gb_chunk);
|
||||||
length -= 4;
|
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case MKTAG('I', 'D', 'A', 'T'):
|
case MKTAG('I', 'D', 'A', 'T'):
|
||||||
if (CONFIG_APNG_DECODER && avctx->codec_id == AV_CODEC_ID_APNG && !decode_next_dat)
|
if (CONFIG_APNG_DECODER && avctx->codec_id == AV_CODEC_ID_APNG && !decode_next_dat)
|
||||||
goto skip_tag;
|
continue;
|
||||||
if ((ret = decode_idat_chunk(avctx, s, length, p)) < 0)
|
if ((ret = decode_idat_chunk(avctx, s, &gb_chunk, p)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
case MKTAG('P', 'L', 'T', 'E'):
|
case MKTAG('P', 'L', 'T', 'E'):
|
||||||
if (decode_plte_chunk(avctx, s, length) < 0)
|
decode_plte_chunk(avctx, s, &gb_chunk);
|
||||||
goto skip_tag;
|
|
||||||
break;
|
break;
|
||||||
case MKTAG('t', 'R', 'N', 'S'):
|
case MKTAG('t', 'R', 'N', 'S'):
|
||||||
if (decode_trns_chunk(avctx, s, length) < 0)
|
decode_trns_chunk(avctx, s, &gb_chunk);
|
||||||
goto skip_tag;
|
|
||||||
break;
|
break;
|
||||||
case MKTAG('t', 'E', 'X', 't'):
|
case MKTAG('t', 'E', 'X', 't'):
|
||||||
if (decode_text_chunk(s, length, 0) < 0)
|
if (decode_text_chunk(s, &gb_chunk, 0) < 0)
|
||||||
av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n");
|
av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n");
|
||||||
bytestream2_skip(&s->gb, length + 4);
|
|
||||||
break;
|
break;
|
||||||
case MKTAG('z', 'T', 'X', 't'):
|
case MKTAG('z', 'T', 'X', 't'):
|
||||||
if (decode_text_chunk(s, length, 1) < 0)
|
if (decode_text_chunk(s, &gb_chunk, 1) < 0)
|
||||||
av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n");
|
av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n");
|
||||||
bytestream2_skip(&s->gb, length + 4);
|
|
||||||
break;
|
break;
|
||||||
case MKTAG('s', 'T', 'E', 'R'): {
|
case MKTAG('s', 'T', 'E', 'R'): {
|
||||||
int mode = bytestream2_get_byte(&s->gb);
|
int mode = bytestream2_get_byte(&gb_chunk);
|
||||||
|
|
||||||
if (mode == 0 || mode == 1) {
|
if (mode == 0 || mode == 1) {
|
||||||
s->stereo_mode = mode;
|
s->stereo_mode = mode;
|
||||||
@@ -1315,33 +1302,31 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
av_log(avctx, AV_LOG_WARNING,
|
av_log(avctx, AV_LOG_WARNING,
|
||||||
"Unknown value in sTER chunk (%d)\n", mode);
|
"Unknown value in sTER chunk (%d)\n", mode);
|
||||||
}
|
}
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MKTAG('i', 'C', 'C', 'P'): {
|
case MKTAG('i', 'C', 'C', 'P'): {
|
||||||
if ((ret = decode_iccp_chunk(s, length, p)) < 0)
|
if ((ret = decode_iccp_chunk(s, &gb_chunk, p)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MKTAG('c', 'H', 'R', 'M'): {
|
case MKTAG('c', 'H', 'R', 'M'): {
|
||||||
s->have_chrm = 1;
|
s->have_chrm = 1;
|
||||||
|
|
||||||
s->white_point[0] = bytestream2_get_be32(&s->gb);
|
s->white_point[0] = bytestream2_get_be32(&gb_chunk);
|
||||||
s->white_point[1] = bytestream2_get_be32(&s->gb);
|
s->white_point[1] = bytestream2_get_be32(&gb_chunk);
|
||||||
|
|
||||||
/* RGB Primaries */
|
/* RGB Primaries */
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
s->display_primaries[i][0] = bytestream2_get_be32(&s->gb);
|
s->display_primaries[i][0] = bytestream2_get_be32(&gb_chunk);
|
||||||
s->display_primaries[i][1] = bytestream2_get_be32(&s->gb);
|
s->display_primaries[i][1] = bytestream2_get_be32(&gb_chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MKTAG('g', 'A', 'M', 'A'): {
|
case MKTAG('g', 'A', 'M', 'A'): {
|
||||||
AVBPrint bp;
|
AVBPrint bp;
|
||||||
char *gamma_str;
|
char *gamma_str;
|
||||||
int num = bytestream2_get_be32(&s->gb);
|
int num = bytestream2_get_be32(&gb_chunk);
|
||||||
|
|
||||||
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
|
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
|
||||||
av_bprintf(&bp, "%i/%i", num, 100000);
|
av_bprintf(&bp, "%i/%i", num, 100000);
|
||||||
@@ -1351,7 +1336,6 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
|
|
||||||
av_dict_set(&s->frame_metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL);
|
av_dict_set(&s->frame_metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL);
|
||||||
|
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MKTAG('I', 'E', 'N', 'D'):
|
case MKTAG('I', 'E', 'N', 'D'):
|
||||||
@@ -1361,13 +1345,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
|||||||
ret = AVERROR_INVALIDDATA;
|
ret = AVERROR_INVALIDDATA;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
bytestream2_skip(&s->gb, 4); /* crc */
|
|
||||||
goto exit_loop;
|
goto exit_loop;
|
||||||
default:
|
|
||||||
/* skip tag */
|
|
||||||
skip_tag:
|
|
||||||
bytestream2_skip(&s->gb, length + 4);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exit_loop:
|
exit_loop:
|
||||||
|
Reference in New Issue
Block a user