#include "libavutil/avassert.h"
#include "libavutil/bprint.h"
+#include "libavutil/crc.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/stereo3d.h"
{
int ret;
s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
- s->zstream.next_in = (unsigned char *)s->gb.buffer;
+ s->zstream.next_in = s->gb.buffer;
bytestream2_skip(&s->gb, length);
/* decode one line if possible */
zstream.opaque = NULL;
if (inflateInit(&zstream) != Z_OK)
return AVERROR_EXTERNAL;
- zstream.next_in = (unsigned char *)data;
+ zstream.next_in = data;
zstream.avail_in = data_end - data;
av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED);
return AVERROR_INVALIDDATA;
}
+ if (s->pic_state & PNG_IDAT) {
+ av_log(avctx, AV_LOG_ERROR, "fctl after IDAT\n");
+ return AVERROR_INVALIDDATA;
+ }
+
s->last_w = s->cur_w;
s->last_h = s->cur_h;
s->last_x_offset = s->x_offset;
static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
AVFrame *p, AVPacket *avpkt)
{
+ const AVCRC *crc_tab = av_crc_get_table(AV_CRC_32_IEEE_LE);
AVDictionary **metadatap = NULL;
uint32_t tag, length;
int decode_next_dat = 0;
ret = AVERROR_INVALIDDATA;
goto fail;
}
+ if (avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_IGNORE_ERR)) {
+ uint32_t crc_sig = AV_RB32(s->gb.buffer + length + 4);
+ uint32_t crc_cal = ~av_crc(crc_tab, UINT32_MAX, s->gb.buffer, length + 4);
+ if (crc_sig ^ crc_cal) {
+ av_log(avctx, AV_LOG_ERROR, "CRC mismatch in chunk");
+ if (avctx->err_recognition & AV_EF_EXPLODE) {
+ av_log(avctx, AV_LOG_ERROR, ", quitting\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ av_log(avctx, AV_LOG_ERROR, ", skipping\n");
+ bytestream2_skip(&s->gb, 4); /* tag */
+ goto skip_tag;
+ }
+ }
tag = bytestream2_get_le32(&s->gb);
if (avctx->debug & FF_DEBUG_STARTCODE)
av_log(avctx, AV_LOG_DEBUG, "png: tag=%s length=%u\n",
case MKTAG('f', 'd', 'A', 'T'):
if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
goto skip_tag;
- if (!decode_next_dat) {
+ if (!decode_next_dat || length < 4) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
break;
}
case MKTAG('i', 'C', 'C', 'P'): {
- if (decode_iccp_chunk(s, length, p) < 0)
+ if ((ret = decode_iccp_chunk(s, length, p)) < 0)
goto fail;
break;
}
if (avpkt->size < 2)
return AVERROR_INVALIDDATA;
+ if (avpkt->size == 2)
+ return 0;
bytestream2_init(gb, avpkt->data, avpkt->size);