This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch release/8.1
in repository ffmpeg.

The following commit(s) were added to refs/heads/release/8.1 by this push:
     new 45f1910444 avcodec/pngenc: fix overrun caused by exif size discrepancy
45f1910444 is described below

commit 45f1910444f34b02621f9f0426ea1a538a613c41
Author:     Leo Izen <[email protected]>
AuthorDate: Sun Jul 12 10:22:47 2026 -0400
Commit:     ffmpeg-devel <[email protected]>
CommitDate: Tue Jul 21 22:19:59 2026 +0000

    avcodec/pngenc: fix overrun caused by exif size discrepancy
    
    If the estimated EXIF size based on the attached frame data is lower
    than the actual EXIF size after sanitizing the IFD, then an overrun
    might occur. Instead, we parse the IFD and use the parsed size as the
    estimated exif size so there won't be any discrepancy between the two
    values.
    
    Signed-off-by: Leo Izen <[email protected]>
    Reported-by: Adrian Junge <[email protected]>
    (cherry picked from commit b506fafec9a19fcbc2be5271875fd4a63d6615bc)
---
 libavcodec/pngenc.c | 48 ++++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index 82a9d5b835..8acd98b551 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -72,6 +72,8 @@ typedef struct PNGEncContext {
     int color_type;
     int bits_per_pixel;
 
+    AVBufferRef *exif_data;
+
     // APNG
     uint32_t palette_checksum;   // Used to ensure a single unique palette
     uint32_t sequence_number;
@@ -377,7 +379,6 @@ static int encode_headers(AVCodecContext *avctx, const 
AVFrame *pict)
 {
     AVFrameSideData *side_data;
     PNGEncContext *s = avctx->priv_data;
-    AVBufferRef *exif_data = NULL;
     int ret;
 
     /* write png header */
@@ -419,17 +420,10 @@ static int encode_headers(AVCodecContext *avctx, const 
AVFrame *pict)
         }
     }
 
-    ret = ff_exif_get_buffer(avctx, pict, &exif_data, AV_EXIF_TIFF_HEADER);
-    if (exif_data) {
-        // png_write_chunk accepts an int, not a size_t, so we have to check 
overflow
-        if (exif_data->size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
-            // that's a very big exif chunk, probably a bug
-            av_log(avctx, AV_LOG_ERROR, "extremely large EXIF buffer detected, 
not writing\n");
-        else
-            png_write_chunk(&s->bytestream, MKTAG('e','X','I','f'), 
exif_data->data, exif_data->size);
-        av_buffer_unref(&exif_data);
-    } else if (ret < 0) {
-        av_log(avctx, AV_LOG_WARNING, "unable to attach EXIF metadata: %s\n", 
av_err2str(ret));
+    if (s->exif_data) {
+        /* we checked for overflow when we attached the buffer to s->exif_data 
*/
+        png_write_chunk(&s->bytestream, MKTAG('e','X','I','f'), 
s->exif_data->data, s->exif_data->size);
+        av_buffer_unref(&s->exif_data);
     }
 
     side_data = av_frame_get_side_data(pict, AV_FRAME_DATA_ICC_PROFILE);
@@ -649,25 +643,30 @@ static int add_icc_profile_size(AVCodecContext *avctx, 
const AVFrame *pict,
 static int add_exif_profile_size(AVCodecContext *avctx, const AVFrame *pict,
                                  uint64_t *max_packet_size)
 {
-    const AVFrameSideData *sd;
     uint64_t new_pkt_size;
-    /* includes orientation tag */
-    const int base_exif_size = 92;
-    uint64_t estimated_exif_size;
+    PNGEncContext *s = avctx->priv_data;
 
-    sd = av_frame_get_side_data(pict, AV_FRAME_DATA_EXIF);
-    estimated_exif_size = sd ? sd->size : 0;
-    sd = av_frame_get_side_data(pict, AV_FRAME_DATA_DISPLAYMATRIX);
-    if (sd)
-        estimated_exif_size += base_exif_size;
+    int result = ff_exif_get_buffer(avctx, pict, &s->exif_data, 
AV_EXIF_TIFF_HEADER);
+    if (!s->exif_data) {
+        if (result < 0)
+            av_log(avctx, AV_LOG_WARNING, "unable to attach EXIF metadata: 
%s\n", av_err2str(result));
+        return 0;
+    }
 
-    if (!estimated_exif_size)
+    /* png_write_chunk accepts an int, not a size_t, so we have to check 
overflow */
+    if (s->exif_data->size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
+        /* that's a very big exif chunk, probably a bug */
+        av_log(avctx, AV_LOG_ERROR, "extremely large EXIF buffer detected, not 
writing\n");
+        av_buffer_unref(&s->exif_data);
         return 0;
+    }
 
     /* 12 is the png chunk header size */
-    new_pkt_size = *max_packet_size + estimated_exif_size + 12;
-    if (new_pkt_size < *max_packet_size)
+    new_pkt_size = *max_packet_size + s->exif_data->size + 12;
+    if (new_pkt_size < *max_packet_size) {
+        av_buffer_unref(&s->exif_data);
         return AVERROR_INVALIDDATA;
+    }
 
     *max_packet_size = new_pkt_size;
 
@@ -1258,6 +1257,7 @@ static av_cold int png_enc_close(AVCodecContext *avctx)
     ff_deflate_end(&s->zstream);
     av_frame_free(&s->last_frame);
     av_frame_free(&s->prev_frame);
+    av_buffer_unref(&s->exif_data);
     av_freep(&s->last_frame_packet);
     av_freep(&s->extra_data);
     s->extra_data_size = 0;

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to