From patchwork Fri May 22 22:46:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lynne X-Patchwork-Id: 19809 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 0E23244BD09 for ; Sat, 23 May 2020 01:46:22 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E68AC6881FE; Sat, 23 May 2020 01:46:21 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from w4.tutanota.de (w4.tutanota.de [81.3.6.165]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6EA166808E8 for ; Sat, 23 May 2020 01:46:15 +0300 (EEST) Received: from w3.tutanota.de (unknown [192.168.1.164]) by w4.tutanota.de (Postfix) with ESMTP id 1DC3C1060157 for ; Fri, 22 May 2020 22:46:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1590187575; s=s1; d=lynne.ee; h=From:From:To:To:Subject:Subject:Content-Description:Content-ID:Content-Type:Content-Type:Content-Transfer-Encoding:Cc:Date:Date:In-Reply-To:MIME-Version:MIME-Version:Message-ID:Message-ID:Reply-To:References:Sender; bh=u/t4xIjKEa/fSts3IJ+TbtmlZBuogMcUsVA3axgbIHg=; b=Tdc5l0EJmG87OQwCF1hALkbH2YSawTABYJYQbKGV6KpRKXZ+VuEFcueVVll5ylR/ YDEx78s1R7vYbnU3p2POIL84URtxiNEs/6n1m81CkUYYQMhYww7PTlpSZF5p6y+QT0s MRbluOfbGEG/5wzbiHK+dxODMqzdv25n5ZF6ZZm5ATj0IHH8VRp2vYChOUlYrsd/+EM xDvCkUZwgyjnuQFb4/TMTkm641Kp5i1DWkjq71ADh+xTM/UZq59sdDalUhOOJgITl7c KJinVthIZg2j0XH0TcfBlWBiurgagwB1F29GYCwZ+/nrZ7vSzhnM+EPs6mDQ3MttkV0 fQpj6ROdGw== Date: Sat, 23 May 2020 00:46:15 +0200 (CEST) From: Lynne To: Ffmpeg Devel Message-ID: MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3] pngdec: add ability to check chunk CRC X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Posting this again. By default now, if AV_EF_CRCCHECK or AV_EF_IGNORE_ERR are enabled the decoder will skip the chunk and carry on with the next one. This should make the decoder able to decode more corrupt files because the functions which decode individual chunks will very likely error out if fed invalid data and stop the decoding of the entire image. Patch attached. I think this one is important since it allows at least partial decoding of damaged files. Subject: [PATCH 3/3] pngdec: add ability to check chunk CRC By default now, if AV_EF_CRCCHECK or AV_EF_IGNORE_ERR are enabled the decoder will skip the chunk and carry on with the next one. This should make the decoder able to decode more corrupt files because the functions which decode individual chunks will very likely error out if fed invalid data and stop the decoding of the entire image. --- libavcodec/pngdec.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 86f885bbee..ff3882a58d 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -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",