PR #23788 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23788
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23788.patch

Fixes a minor use-after-free, and invalid SPIR-V generation. Makes all tests 
pass.


>From 076ad9bed369f41731180deb8e1be712d00889a0 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Mon, 13 Jul 2026 00:13:59 +0900
Subject: [PATCH 1/2] swscale/vulkan: fix invalid SPIR-V generation for
 plane-remapped passes

The CLEAR codegen iterated components by value[i].den, while the
constants pass iterates by clear.mask; unmasked components may hold
leftover values with a nonzero denominator, consuming more constant
IDs than were registered and emitting ID 0 into the instruction
stream.

The image handle arrays were also sized by the number of planes an
op touches, but plane_src/plane_dst contain actual frame plane
indices, so a pass writing only e.g. the alpha plane references
handle 3 while only handle 0 was loaded.

Either results in invalid SPIR-V, which crashes RADV inside
spirv_to_nir when creating the shader object.
---
 libswscale/vulkan/ops.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c
index 045f220745..54f1c689eb 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -908,6 +908,16 @@ static int read_filtered(SPICtx *spi, SPIRVIDs *id, const 
SwsOpList *ops,
                                     acc_s[0], acc_s[1], acc_s[2], acc_s[3]);
 }
 
+/* Plane indices refer to actual frame planes, so the image handle arrays
+ * have to cover the highest plane referenced, not just the plane count. */
+static int rw_op_img_count(const SwsOp *op, const uint8_t *planes)
+{
+    int count = 0;
+    for (int i = 0; i < ff_sws_rw_op_planes(op); i++)
+        count = FFMAX(count, planes[i] + 1);
+    return count;
+}
+
 static int add_ops_spirv(SwsContext *sws, VulkanPriv *p, FFVulkanOpsCtx *s,
                          const SwsOpList *ops, FFVulkanShader *shd)
 {
@@ -929,11 +939,11 @@ static int add_ops_spirv(SwsContext *sws, VulkanPriv *p, 
FFVulkanOpsCtx *s,
 
     /* Image ops, to determine types */
     const SwsOp *op_w = ff_sws_op_list_output(ops);
-    int out_img_count = ff_sws_rw_op_planes(op_w);
+    int out_img_count = rw_op_img_count(op_w, ops->plane_dst);
     p->dst_rep = op_w->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : 
FF_VK_REP_UINT;
 
     const SwsOp *op_r = ff_sws_op_list_input(ops);
-    int in_img_count = op_r ? ff_sws_rw_op_planes(op_r) : 0;
+    int in_img_count = op_r ? rw_op_img_count(op_r, ops->plane_src) : 0;
     if (op_r)
         p->src_rep = op_r->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : 
FF_VK_REP_UINT;
 
@@ -1038,7 +1048,7 @@ static int add_ops_spirv(SwsContext *sws, VulkanPriv *p, 
FFVulkanOpsCtx *s,
     }
 
     /* Load output image handles */
-    int out_img[4];
+    int out_img[4] = { 0 };
     for (int i = 0; i < out_img_count; i++) {
         int img = spi_OpAccessChain(spi, id->out_img_sptr,
                                     id->in_vars[2], id->u32_cid[i]);
@@ -1171,7 +1181,7 @@ static int add_ops_spirv(SwsContext *sws, VulkanPriv *p, 
FFVulkanOpsCtx *s,
             break;
         case SWS_OP_CLEAR:
             for (int i = 0; i < 4; i++) {
-                if (!op->clear.value[i].den)
+                if (!SWS_COMP_TEST(op->clear.mask, i))
                     continue;
                 data = spi_OpCompositeInsert(spi, type_v,
                                              id->const_ids[nb_const_ids++],
-- 
2.52.0


>From 9d6c9fe47a53d4691bb4b68d1ad23b3700aa4974 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Mon, 13 Jul 2026 00:13:59 +0900
Subject: [PATCH 2/2] swscale/ops_dispatch: fix use-after-free when adding
 opaque ops passes

comp points into p, which is freed before comp->backend is read.
Use the copy taken before the free.
---
 libswscale/ops_dispatch.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libswscale/ops_dispatch.c b/libswscale/ops_dispatch.c
index dd166a5f92..2da38fc333 100644
--- a/libswscale/ops_dispatch.c
+++ b/libswscale/ops_dispatch.c
@@ -550,7 +550,7 @@ static int compile_single(const CompileArgs *args, const 
SwsOpList *ops,
                                     input, 0, c.slice_align, c.func_opaque,
                                     NULL, c.priv, c.free, output);
         if (ret >= 0) {
-            (*output)->backend = comp->backend->flags;
+            (*output)->backend = c.backend->flags;
             ff_sws_pass_link_output(*output, link);
         }
         return ret;
-- 
2.52.0

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

Reply via email to