Commit 5cd8e58b94 for ffmpeg
commit 5cd8e58b943d75859de1c0576c58582279e68aac
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Mon Oct 12 02:27:49 2026 +0200
avfilter/vf_deshake: use the linesize of the reference frame
Fixes: out of array read
Fixes: Au41rSBM5kGS
Found during triage of the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24765
Out of array read Replicated through UnModified FFmpeg with ASAN
diff --git a/libavfilter/vf_deshake.c b/libavfilter/vf_deshake.c
index afd0989e05..8a2dbe2fa5 100644
--- a/libavfilter/vf_deshake.c
+++ b/libavfilter/vf_deshake.c
@@ -171,16 +171,16 @@ static double clean_mean(double *values, int count)
* chooses the most likely shift by the smallest difference in blocks.
*/
static void find_block_motion(DeshakeContext *deshake, uint8_t *src1,
- uint8_t *src2, int cx, int cy, int stride,
- IntMotionVector *mv)
+ uint8_t *src2, int cx, int cy, int stride1,
+ int stride2, IntMotionVector *mv)
{
int x, y;
int diff;
int smallest = INT_MAX;
int tmp, tmp2;
- #define CMP(i, j) deshake->sad(src1 + cy * stride + cx, stride,\
- src2 + (j) * stride + (i), stride)
+ #define CMP(i, j) deshake->sad(src1 + cy * stride1 + cx, stride1,\
+ src2 + (j) * stride2 + (i), stride2)
if (deshake->search == EXHAUSTIVE) {
// Compare every possible position - this is sloooow!
@@ -285,7 +285,7 @@ static double block_angle(int x, int y, int cx, int cy, IntMotionVector *shift)
* motion vector (1, -2).
*/
static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
- int width, int height, int stride, Transform *t)
+ int width, int height, int stride1, int stride2, Transform *t)
{
int x, y;
IntMotionVector mv = {0, 0};
@@ -312,10 +312,10 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
for (x = deshake->rx; x < width - deshake->rx - 16; x += 16) {
// If the contrast is too low, just skip this block as it probably
// won't be very useful to us.
- contrast = block_contrast(src2, x, y, stride, deshake->blocksize);
+ contrast = block_contrast(src2, x, y, stride2, deshake->blocksize);
if (contrast > deshake->contrast) {
//av_log(NULL, AV_LOG_ERROR, "%d\n", contrast);
- find_block_motion(deshake, src1, src2, x, y, stride, &mv);
+ find_block_motion(deshake, src1, src2, x, y, stride1, stride2, &mv);
if (mv.x != -1 && mv.y != -1) {
deshake->counts[mv.x + deshake->rx][mv.y + deshake->ry] += 1;
if (x > deshake->rx && y > deshake->ry)
@@ -476,7 +476,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
}
av_frame_copy_props(out, in);
- aligned = !((intptr_t)in->data[0] & 15 | in->linesize[0] & 15);
+ const AVFrame *ref = deshake->ref ? deshake->ref : in;
+ aligned = !((intptr_t)ref->data[0] & 15 | ref->linesize[0] & 15);
deshake->sad = av_pixelutils_get_sad_fn(4, 4, aligned, deshake); // 16x16, 2nd source unaligned
if (!deshake->sad) {
ret = AVERROR(EINVAL);
@@ -485,9 +486,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
if (deshake->cx < 0 || deshake->cy < 0 || deshake->cw < 0 || deshake->ch < 0) {
// Find the most likely global motion for the current frame
- find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t);
+ find_motion(deshake, ref->data[0], in->data[0], link->w, link->h, ref->linesize[0], in->linesize[0], &t);
} else {
- uint8_t *src1 = (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0];
+ uint8_t *src1 = ref->data[0];
uint8_t *src2 = in->data[0];
deshake->cx = FFMIN(deshake->cx, link->w);
@@ -499,10 +500,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
// Quadword align right margin
deshake->cw &= ~15;
- src1 += deshake->cy * in->linesize[0] + deshake->cx;
+ src1 += deshake->cy * ref->linesize[0] + deshake->cx;
src2 += deshake->cy * in->linesize[0] + deshake->cx;
- find_motion(deshake, src1, src2, deshake->cw, deshake->ch, in->linesize[0], &t);
+ find_motion(deshake, src1, src2, deshake->cw, deshake->ch, ref->linesize[0], in->linesize[0], &t);
}