Commit b90ec19645 for ffmpeg

commit b90ec196453748b3c83e434d38e7abaae5f2dbb2
Author: Michael Niedermayer <michael@niedermayer.cc>
Date:   Sun Oct 11 07:22:27 2026 +0200

    avcodec/pthread_frame: give each worker context its own copy of the channel layout

    The worker contexts are created by av_memdup() of the user context, a
    custom channel layout map was shared with all of them. Copying the
    layout into the first worker in update_context_from_thread() freed the
    shared map and read it afterwards, decoders which uninit the layout in
    init freed it twice.

    Fixes: heap use after free
    Fixes: double free
    Fixes: l08oZE4M5Rmz
    Regression since: 548aeb9383
    Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24577
    Heap use after free Replicated through UnModified FFmpeg with ASAN

diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 5ec9a8a974..085aff5508 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -790,6 +790,7 @@ av_cold void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
         ff_pthread_free(p, per_thread_offsets);
         av_packet_free(&p->avpkt);

+        av_channel_layout_uninit(&ctx->ch_layout);
         av_freep(&p->avctx);
     }

@@ -821,9 +822,11 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
     copy = av_memdup(avctx, sizeof(*avctx));
     if (!copy)
         return AVERROR(ENOMEM);
+    copy->internal = NULL;
     copy->priv_data = NULL;
     copy->decoded_side_data = NULL;
     copy->nb_decoded_side_data = 0;
+    copy->ch_layout = (AVChannelLayout){ 0 };

     /* From now on, this PerThreadContext will be cleaned up by
      * ff_frame_thread_free in case of errors. */
@@ -832,6 +835,10 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
     p->parent = fctx;
     p->avctx  = copy;

+    err = av_channel_layout_copy(&copy->ch_layout, &avctx->ch_layout);
+    if (err < 0)
+        return err;
+
     copy->internal = ff_decode_internal_alloc();
     if (!copy->internal)
         return AVERROR(ENOMEM);