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

Git pushed a commit to branch master
in repository ffmpeg.

commit f570fa787a813195775521ed28bf0ff302cc93b8
Author:     Andreas Rheinhardt <[email protected]>
AuthorDate: Tue Feb 24 16:41:07 2026 +0100
Commit:     Andreas Rheinhardt <[email protected]>
CommitDate: Sat Feb 28 09:56:01 2026 +0100

    swscale/swscale_internal: Move altivec parts to ppc/
    
    Up until now, several altivec-specific fields are directly
    put into SwsInternal #if HAVE_ALTIVEC is true. These fields
    are of altivec-specific vector types and therefore
    require altivec specific headers to be included.
    
    Unfortunately, said altivec specific headers redefine
    bool in a manner that is incompatible with stdbool.
    swscale/ops.h uses bool and this led graph.c and ops.c
    to disagree about the layout of structures from ops.h,
    leading to heap corruption [1], [2] in the sws-unscaled
    FATE test.
    
    Fix this by moving the altivec-specific parts out of SwsInternal
    and into a structure that extends SwsInternal and is allocated
    jointly with it. Said structure is local to yuv2rgb_altivec.c,
    because this is the only file accessing said fields. Should
    more files need them, an altivec-specific swscale header would
    need to be added.
    
    Thanks to jfiusdq <[email protected]> for analyzing the issue.
    
    [1]: 
https://fate.ffmpeg.org/report.cgi?slot=ppc64-linux-gcc-14.3-asan&time=20260224065643
    [2]: 
https://fate.ffmpeg.org/report.cgi?slot=ppc64-linux-gcc-14.3&time=20260224051615
    
    Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libswscale/ppc/yuv2rgb_altivec.c | 100 ++++++++++++++++++++++++++-------------
 libswscale/ppc/yuv2yuv_altivec.c |   1 +
 libswscale/swscale_internal.h    |  19 +++-----
 libswscale/utils.c               |   2 +-
 4 files changed, 76 insertions(+), 46 deletions(-)

diff --git a/libswscale/ppc/yuv2rgb_altivec.c b/libswscale/ppc/yuv2rgb_altivec.c
index 3efb33d22e..cad3f8d7c0 100644
--- a/libswscale/ppc/yuv2rgb_altivec.c
+++ b/libswscale/ppc/yuv2rgb_altivec.c
@@ -103,6 +103,34 @@
 #include "yuv2rgb_altivec.h"
 
 #if HAVE_ALTIVEC
+// util_altivec.h includes the system header altivec.h which redefines bool,
+// making it incompatible with stdbool.h. It therefore must not be included
+// before another one of our headers that may use bool.
+#include "libavutil/ppc/util_altivec.h"
+#include <assert.h>
+
+typedef struct SwsInternalAltivec {
+    SwsInternal c;
+
+    vector signed short   CY;
+    vector signed short   CRV;
+    vector signed short   CBU;
+    vector signed short   CGU;
+    vector signed short   CGV;
+    vector signed short   OY;
+    vector unsigned short CSHIFT;
+    vector signed short  *vYCoeffsBank, *vCCoeffsBank;
+} SwsInternalAltivec;
+// Check that the sizes of the types match.
+// Note that given that SwsInternal is always allocated via av_malloc,
+// every pointer to an SwsInternal is always sufficiently aligned.
+static_assert(sizeof(SwsInternalAltivec) <= sizeof(SwsInternal) + 
SWSINTERNAL_ADDITIONAL_ASM_SIZE,
+              "SWSINTERNAL_ADDITIONAL_ASM_SIZE needs to be increased");
+
+static inline SwsInternalAltivec *sws_internal_altivec(SwsInternal *c)
+{
+    return (SwsInternalAltivec*)c;
+}
 
 #undef PROFILE_THE_BEAST
 #undef INC_SCALING
@@ -259,25 +287,26 @@ static inline void cvtyuvtoRGB(SwsInternal *c, vector 
signed short Y,
                                vector signed short *R, vector signed short *G,
                                vector signed short *B)
 {
+    SwsInternalAltivec *const a = sws_internal_altivec(c);
     vector signed short vx, ux, uvx;
 
-    Y = vec_mradds(Y, c->CY, c->OY);
+    Y = vec_mradds(Y, a->CY, a->OY);
     U = vec_sub(U, (vector signed short)
                        vec_splat((vector signed short) { 128 }, 0));
     V = vec_sub(V, (vector signed short)
                        vec_splat((vector signed short) { 128 }, 0));
 
-    // ux  = (CBU * (u << c->CSHIFT) + 0x4000) >> 15;
-    ux = vec_sl(U, c->CSHIFT);
-    *B = vec_mradds(ux, c->CBU, Y);
+    // ux  = (CBU * (u << a->CSHIFT) + 0x4000) >> 15;
+    ux = vec_sl(U, a->CSHIFT);
+    *B = vec_mradds(ux, a->CBU, Y);
 
-    // vx  = (CRV * (v << c->CSHIFT) + 0x4000) >> 15;
-    vx = vec_sl(V, c->CSHIFT);
-    *R = vec_mradds(vx, c->CRV, Y);
+    // vx  = (CRV * (v << a->CSHIFT) + 0x4000) >> 15;
+    vx = vec_sl(V, a->CSHIFT);
+    *R = vec_mradds(vx, a->CRV, Y);
 
     // uvx = ((CGU * u) + (CGV * v)) >> 15;
-    uvx = vec_mradds(U, c->CGU, Y);
-    *G  = vec_mradds(V, c->CGV, uvx);
+    uvx = vec_mradds(U, a->CGU, Y);
+    *G  = vec_mradds(V, a->CGV, uvx);
 }
 
 /*
@@ -301,6 +330,7 @@ static int altivec_ ## name(SwsInternal *c, const unsigned 
char *const *in,   \
                             const int *instrides, int srcSliceY, int 
srcSliceH,   \
                             unsigned char *const *oplanes, const int 
*outstrides) \
 {                                                                             \
+    SwsInternalAltivec *const a = sws_internal_altivec(c);                    \
     int w = c->opts.src_w;                                                    \
     int h = srcSliceH;                                                        \
     int i, j;                                                                 \
@@ -318,13 +348,13 @@ static int altivec_ ## name(SwsInternal *c, const 
unsigned char *const *in,   \
     vector signed short R1, G1, B1;                                           \
     vector unsigned char R, G, B;                                             \
                                                                               \
-    vector signed short lCY       = c->CY;                                    \
-    vector signed short lOY       = c->OY;                                    \
-    vector signed short lCRV      = c->CRV;                                   \
-    vector signed short lCBU      = c->CBU;                                   \
-    vector signed short lCGU      = c->CGU;                                   \
-    vector signed short lCGV      = c->CGV;                                   \
-    vector unsigned short lCSHIFT = c->CSHIFT;                                \
+    vector signed short lCY       = a->CY;                                    \
+    vector signed short lOY       = a->OY;                                    \
+    vector signed short lCRV      = a->CRV;                                   \
+    vector signed short lCBU      = a->CBU;                                   \
+    vector signed short lCGU      = a->CGU;                                   \
+    vector signed short lCGV      = a->CGV;                                   \
+    vector unsigned short lCSHIFT = a->CSHIFT;                                \
                                                                               \
     const ubyte *y1i = in[0];                                                 \
     const ubyte *y2i = in[0] + instrides[0];                                  \
@@ -612,6 +642,8 @@ av_cold void ff_yuv2rgb_init_tables_ppc(SwsInternal *c,
                                         int saturation)
 {
 #if HAVE_ALTIVEC
+    SwsInternalAltivec *const a = sws_internal_altivec(c);
+
     union {
         DECLARE_ALIGNED(16, signed short, tmp)[8];
         vector signed short vec;
@@ -627,13 +659,13 @@ av_cold void ff_yuv2rgb_init_tables_ppc(SwsInternal *c,
     buf.tmp[4] = -((inv_table[2] >> 1) * (contrast >> 16) * (saturation >> 
16));  // cgu
     buf.tmp[5] = -((inv_table[3] >> 1) * (contrast >> 16) * (saturation >> 
16));  // cgv
 
-    c->CSHIFT = (vector unsigned short) vec_splat_u16(2);
-    c->CY     = vec_splat((vector signed short) buf.vec, 0);
-    c->OY     = vec_splat((vector signed short) buf.vec, 1);
-    c->CRV    = vec_splat((vector signed short) buf.vec, 2);
-    c->CBU    = vec_splat((vector signed short) buf.vec, 3);
-    c->CGU    = vec_splat((vector signed short) buf.vec, 4);
-    c->CGV    = vec_splat((vector signed short) buf.vec, 5);
+    a->CSHIFT = (vector unsigned short) vec_splat_u16(2);
+    a->CY     = vec_splat((vector signed short) buf.vec, 0);
+    a->OY     = vec_splat((vector signed short) buf.vec, 1);
+    a->CRV    = vec_splat((vector signed short) buf.vec, 2);
+    a->CBU    = vec_splat((vector signed short) buf.vec, 3);
+    a->CGU    = vec_splat((vector signed short) buf.vec, 4);
+    a->CGV    = vec_splat((vector signed short) buf.vec, 5);
     return;
 #endif /* HAVE_ALTIVEC */
 }
@@ -653,6 +685,8 @@ static av_always_inline void 
yuv2packedX_altivec(SwsInternal *c,
                                                  int dstW, int dstY,
                                                  enum AVPixelFormat target)
 {
+    SwsInternalAltivec *const a = sws_internal_altivec(c);
+
     int i, j;
     vector signed short X, X0, X1, Y0, U0, V0, Y1, U1, V1, U, V;
     vector signed short R0, G0, B0, R1, G1, B1;
@@ -666,8 +700,8 @@ static av_always_inline void 
yuv2packedX_altivec(SwsInternal *c,
 
     vector signed short *YCoeffs, *CCoeffs;
 
-    YCoeffs = c->vYCoeffsBank + dstY * lumFilterSize;
-    CCoeffs = c->vCCoeffsBank + dstY * chrFilterSize;
+    YCoeffs = a->vYCoeffsBank + dstY * lumFilterSize;
+    CCoeffs = a->vCCoeffsBank + dstY * chrFilterSize;
 
     out = (vector unsigned char *) dest;
 
@@ -876,20 +910,21 @@ YUV2PACKEDX_WRAPPER(bgr24, AV_PIX_FMT_BGR24);
 av_cold int ff_sws_init_altivec_bufs(SwsInternal *c)
 {
     const SwsContext *const sws = &c->opts;
+    SwsInternalAltivec *const a = sws_internal_altivec(c);
 
-    c->vYCoeffsBank = av_malloc_array(sws->dst_h, c->vLumFilterSize * 
sizeof(*c->vYCoeffsBank));
-    c->vCCoeffsBank = av_malloc_array(c->chrDstH, c->vChrFilterSize * 
sizeof(*c->vCCoeffsBank));
-    if (!c->vYCoeffsBank || !c->vCCoeffsBank)
+    a->vYCoeffsBank = av_malloc_array(sws->dst_h, c->vLumFilterSize * 
sizeof(*a->vYCoeffsBank));
+    a->vCCoeffsBank = av_malloc_array(c->chrDstH, c->vChrFilterSize * 
sizeof(*a->vCCoeffsBank));
+    if (!a->vYCoeffsBank || !a->vCCoeffsBank)
         return AVERROR(ENOMEM);
 
     for (int i = 0; i < c->vLumFilterSize * sws->dst_h; ++i) {
-        short *p = (short *)&c->vYCoeffsBank[i];
+        short *p = (short *)&a->vYCoeffsBank[i];
         for (int j = 0; j < 8; ++j)
             p[j] = c->vLumFilter[i];
     }
 
     for (int i = 0; i < c->vChrFilterSize * c->chrDstH; ++i) {
-        short *p = (short *)&c->vCCoeffsBank[i];
+        short *p = (short *)&a->vCCoeffsBank[i];
         for (int j = 0; j < 8; ++j)
             p[j] = c->vChrFilter[i];
     }
@@ -899,7 +934,8 @@ av_cold int ff_sws_init_altivec_bufs(SwsInternal *c)
 
 av_cold void ff_sws_free_altivec_bufs(SwsInternal *c)
 {
-    av_freep(&c->vYCoeffsBank);
-    av_freep(&c->vCCoeffsBank);
+    SwsInternalAltivec *const a = sws_internal_altivec(c);
+    av_freep(&a->vYCoeffsBank);
+    av_freep(&a->vCCoeffsBank);
 }
 #endif /* HAVE_ALTIVEC */
diff --git a/libswscale/ppc/yuv2yuv_altivec.c b/libswscale/ppc/yuv2yuv_altivec.c
index 7884c38d69..3e3bbea23a 100644
--- a/libswscale/ppc/yuv2yuv_altivec.c
+++ b/libswscale/ppc/yuv2yuv_altivec.c
@@ -30,6 +30,7 @@
 #include "libswscale/swscale_internal.h"
 
 #if HAVE_ALTIVEC
+#include "libavutil/ppc/util_altivec.h"
 
 static int yv12toyuy2_unscaled_altivec(SwsInternal *c, const uint8_t *const 
src[],
                                        const int srcStride[], int srcSliceY,
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index d9fddb271b..f4007379ab 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -37,10 +37,14 @@
 #include "libavutil/pixfmt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/slicethread.h"
+#include "libavutil/half2float.h"
+
 #if HAVE_ALTIVEC
-#include "libavutil/ppc/util_altivec.h"
+#define SWSINTERNAL_ADDITIONAL_ASM_SIZE (7*16 + 2*8 + /* alignment */ 16)
+#endif
+#ifndef SWSINTERNAL_ADDITIONAL_ASM_SIZE
+#define SWSINTERNAL_ADDITIONAL_ASM_SIZE 0
 #endif
-#include "libavutil/half2float.h"
 
 #define STR(s) AV_TOSTRING(s) // AV_STRINGIFY is too long
 
@@ -544,17 +548,6 @@ struct SwsInternal {
 
     const uint8_t *chrDither8, *lumDither8;
 
-#if HAVE_ALTIVEC
-    vector signed short   CY;
-    vector signed short   CRV;
-    vector signed short   CBU;
-    vector signed short   CGU;
-    vector signed short   CGV;
-    vector signed short   OY;
-    vector unsigned short CSHIFT;
-    vector signed short  *vYCoeffsBank, *vCCoeffsBank;
-#endif
-
     int use_mmx_vfilter;
 
 /* pre defined color-spaces gamma */
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 4e6e503b75..90839817d8 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -1031,7 +1031,7 @@ int sws_getColorspaceDetails(SwsContext *sws, int 
**inv_table,
 
 SwsContext *sws_alloc_context(void)
 {
-    SwsInternal *c = (SwsInternal *) av_mallocz(sizeof(SwsInternal));
+    SwsInternal *c = av_mallocz(sizeof(*c) + SWSINTERNAL_ADDITIONAL_ASM_SIZE);
     if (!c)
         return NULL;
 

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

Reply via email to