@@ -23,6 +23,7 @@
#include "libavutil/avassert.h"
#include "libavutil/bprint.h"
+#include "libavutil/crc.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/stereo3d.h"
@@ -1179,6 +1180,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
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;
@@ -1213,6 +1215,21 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
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",