vp4: prevent unaligned memory access in loop filter
authorPeter Ross <pross@xvid.org>
Thu, 20 Jun 2019 21:52:31 +0000 (07:52 +1000)
committerMichael Niedermayer <michael@niedermayer.cc>
Wed, 30 Oct 2019 09:06:38 +0000 (10:06 +0100)
VP4 applies a loop filter during motion compensation, causing the block offset
will often by unaligned. This produces a bus error on some platforms, namely
ARMv7 NEON.

This patch adds a unaligned version of the loop filter function pointer
to VP3DSPContext.

Reported-by: Mike Melanson <mike@multimedia.cx>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
libavcodec/vp3.c
libavcodec/vp3dsp.c
libavcodec/vp3dsp.h
libavcodec/x86/vp3dsp_init.c

index a2bd2ef..9a3821a 100644 (file)
@@ -2031,11 +2031,17 @@ static int vp4_mc_loop_filter(Vp3DecodeContext *s, int plane, int motion_x, int
              plane_width,
              plane_height);
 
+#define safe_loop_filter(name, ptr, stride, bounding_values) \
+    if ((uintptr_t)(ptr) & 7) \
+        s->vp3dsp.name##_unaligned(ptr, stride, bounding_values); \
+    else \
+        s->vp3dsp.name(ptr, stride, bounding_values);
+
         if (x_offset)
-            s->vp3dsp.h_loop_filter(loop + loop_stride + x_offset + 1, loop_stride, bounding_values);
+            safe_loop_filter(h_loop_filter, loop + loop_stride + x_offset + 1, loop_stride, bounding_values);
 
         if (y_offset)
-            s->vp3dsp.v_loop_filter(loop + (y_offset + 1)*loop_stride + 1, loop_stride, bounding_values);
+            safe_loop_filter(v_loop_filter, loop + (y_offset + 1)*loop_stride + 1, loop_stride, bounding_values);
     }
 
     for (i = 0; i < 9; i++)
index ac4c574..f485fba 100644 (file)
@@ -449,8 +449,8 @@ av_cold void ff_vp3dsp_init(VP3DSPContext *c, int flags)
     c->idct_put      = vp3_idct_put_c;
     c->idct_add      = vp3_idct_add_c;
     c->idct_dc_add   = vp3_idct_dc_add_c;
-    c->v_loop_filter = vp3_v_loop_filter_8_c;
-    c->h_loop_filter = vp3_h_loop_filter_8_c;
+    c->v_loop_filter = c->v_loop_filter_unaligned = vp3_v_loop_filter_8_c;
+    c->h_loop_filter = c->h_loop_filter_unaligned = vp3_h_loop_filter_8_c;
 
     if (ARCH_ARM)
         ff_vp3dsp_init_arm(c, flags);
index 32b2cad..3b849ec 100644 (file)
@@ -43,6 +43,8 @@ typedef struct VP3DSPContext {
     void (*idct_dc_add)(uint8_t *dest, ptrdiff_t stride, int16_t *block);
     void (*v_loop_filter)(uint8_t *src, ptrdiff_t stride, int *bounding_values);
     void (*h_loop_filter)(uint8_t *src, ptrdiff_t stride, int *bounding_values);
+    void (*v_loop_filter_unaligned)(uint8_t *src, ptrdiff_t stride, int *bounding_values);
+    void (*h_loop_filter_unaligned)(uint8_t *src, ptrdiff_t stride, int *bounding_values);
 } VP3DSPContext;
 
 void ff_vp3dsp_v_loop_filter_12(uint8_t *first_pixel, ptrdiff_t stride, int *bounding_values);
index 1ba9576..ba47e1c 100644 (file)
@@ -59,8 +59,8 @@ av_cold void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags)
         c->idct_dc_add = ff_vp3_idct_dc_add_mmxext;
 
         if (!(flags & AV_CODEC_FLAG_BITEXACT)) {
-            c->v_loop_filter = ff_vp3_v_loop_filter_mmxext;
-            c->h_loop_filter = ff_vp3_h_loop_filter_mmxext;
+            c->v_loop_filter = c->v_loop_filter_unaligned = ff_vp3_v_loop_filter_mmxext;
+            c->h_loop_filter = c->v_loop_filter_unaligned = ff_vp3_h_loop_filter_mmxext;
         }
     }