Skip to content

feature/speed: fail init on frames too small for one SpEED block - #1620

Open
lusoris wants to merge 1 commit into
Netflix:masterfrom
VMAFx:fix/speed-init-too-small
Open

lusoris wants to merge 1 commit into
Netflix:masterfrom
VMAFx:fix/speed-init-too-small

Conversation

@lusoris

@lusoris lusoris commented Sep 28, 2026 •

Copy link
Copy Markdown

speed_init_dimensions() detects a plane that is too small to hold one 5x5 block after the scale reductions. It logs SpEED: image too small, operating width or height is 0 and returns -EINVAL. speed_init() ignores that return value (speed.c:1076), and init_chroma() and the speed_temporal init() ignore speed_init()'s return in turn (speed.c:1342 and :1575). Extraction then runs with zero blocks: submatrix_width and submatrix_height wrap, and compute_mean() reads past the end of the frame buffer (speed.c:683).

speed_chroma works on the chroma planes, so with 4:2:0 input any frame under 160 pixels wide or high reaches this. speed_temporal works on luma and reaches it under 80 pixels. All eight vmaf_v1.0.16 models use speed_chroma, so measuring a 256x144 rung with, for example, the built-in vmaf_v1.0.16_3d0h crashes.

This returns both errors, so the extractor fails to initialize and vmaf stops with problem reading pictures and a non-zero exit status. The size check runs before any allocation, so nothing leaks, and every size that worked before takes the same path as before.

Reproducer, three 256x144 4:2:0 frames:

head -c 165888 python/test/resource/yuv/src01_hrc00_576x324.yuv > ref_256x144.yuv
head -c 165888 python/test/resource/yuv/src01_hrc01_576x324.yuv > dis_256x144.yuv
build-release/tools/vmaf -r ref_256x144.yuv -d dis_256x144.yuv -w 256 -h 144 -p 420 -b 8 \
  -m version=vmaf_v1.0.16_3d0h -q -o /dev/null
# unpatched: libvmaf ERROR SpEED: image too small, operating width or height is 0
#            exit 139
# patched:   the same error, then "problem reading pictures", exit 234

Under AddressSanitizer the unpatched run reports a heap-buffer-overflow in compute_mean(); the patched run reports nothing from SpEED.

Tests: test_speed_chroma gains two tests.

  • test_speed_init_rejects_frame_below_one_block expects speed_init() to reject a 128x72 plane without allocating, and to accept 128x80, the smallest plane with one block.
  • test_speed_chroma_init_rejects_144p initializes the registered speed_chroma extractor at 256x144 4:2:0.

Against the unpatched speed.c the first fails with speed_init() accepted a plane with no complete block.

Validation against upstream 9e48141bd1eb8d2329e09d3744e7c24af53017ca, x86-64 Linux (AVX-512 host), GCC 16.2.1, Meson 1.12.1. Rebased on master 9e48141 (2026-10-02):

meson setup build-release libvmaf --buildtype=release -Denable_float=true -Denable_docs=false
ninja -C build-release
meson test -C build-release --print-errorlogs
# 24/24 passed

--feature speed_chroma --feature speed_temporal gives JSON identical to the unpatched build at 320x180, 256x160, 160x256 and 576x324, apart from the fps field. None of the Netflix reference pairs uses SpEED, so no golden value can change.

Overlap: #1574 and #1551 also edit speed.c; this adds no conflict with either.

@lusoris
lusoris force-pushed the fix/speed-init-too-small branch 2 times, most recently from 90786f0 to c439aa7 Compare October 1, 2026 18:11
@lusoris
lusoris force-pushed the fix/speed-init-too-small branch from c439aa7 to 3b8f59b Compare October 2, 2026 05:22
speed_init_dimensions() returns -EINVAL when a plane holds no complete
block after the scale reductions, but speed_init() ignored it, and
init_chroma() and the speed_temporal init() ignored speed_init()'s
return. Extraction then ran with zero blocks and compute_mean() read
past the end of the frame buffer: any 4:2:0 frame under 160 pixels in
either dimension crashed speed_chroma, which every vmaf_v1.0.16 model
uses.

Return both errors so the extractor fails to initialize. The check runs
before any allocation. Add tests for speed_init() at 128x72 and 128x80
and for the registered speed_chroma extractor at 256x144.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant