[FFmpeg-devel] [PATCH 1/3] avcodec/pngdec: Use internal AVBPrint string when parsing chunks

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Wed Mar 17 18:32:00 EET 2021


One saves an allocation in case the string fits into the buffer.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
5663301560d77486c7f7c03c1aa5f542fab23c24 caused a regression that makes
some png files lose their metadata, because decode_idat_chunk() unrefs
the frame that the metadata has been attached to. I therefore tested
these commits with the aforementioned commit reverted.

 libavcodec/pngdec.c | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index a5a71ef161..6b9fdf5a22 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -517,7 +517,7 @@ static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed,
     const uint8_t *data_end    = data + length;
     const uint8_t *keyword     = data;
     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, *txt_utf8 = NULL;
     unsigned text_len;
     AVBPrint bp;
 
@@ -533,19 +533,16 @@ static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed,
             return AVERROR_INVALIDDATA;
         if ((ret = decode_zbuf(&bp, data, data_end)) < 0)
             return ret;
+        data     = bp.str;
         text_len = bp.len;
-        ret = av_bprint_finalize(&bp, (char **)&text);
-        if (ret < 0)
-            return ret;
     } else {
-        text = (uint8_t *)data;
-        text_len = data_end - text;
+        text_len = data_end - data;
     }
 
     kw_utf8  = iso88591_to_utf8(keyword, keyword_end - keyword);
-    txt_utf8 = iso88591_to_utf8(text, text_len);
-    if (text != data)
-        av_free(text);
+    txt_utf8 = iso88591_to_utf8(data, text_len);
+    if (compressed)
+        av_bprint_finalize(&bp, NULL);
     if (!(kw_utf8 && txt_utf8)) {
         av_free(kw_utf8);
         av_free(txt_utf8);
@@ -851,7 +848,7 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
 static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f)
 {
     int ret, cnt = 0;
-    uint8_t *data, profile_name[82];
+    uint8_t profile_name[82];
     AVBPrint bp;
     AVFrameSideData *sd;
 
@@ -873,19 +870,15 @@ static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f)
     if ((ret = decode_zbuf(&bp, s->gb.buffer, s->gb.buffer + length)) < 0)
         return ret;
 
-    ret = av_bprint_finalize(&bp, (char **)&data);
-    if (ret < 0)
-        return ret;
-
     sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, bp.len);
     if (!sd) {
-        av_free(data);
+        av_bprint_finalize(&bp, NULL);
         return AVERROR(ENOMEM);
     }
 
+    memcpy(sd->data, bp.str, bp.len);
+    av_bprint_finalize(&bp, NULL);
     av_dict_set(&sd->metadata, "name", profile_name, 0);
-    memcpy(sd->data, data, bp.len);
-    av_free(data);
 
     /* ICC compressed data and CRC */
     bytestream2_skip(&s->gb, length + 4);
-- 
2.27.0



More information about the ffmpeg-devel mailing list