codec_store_buffer: VASliceDataBufferType memcpy has no bounds check vs surface_object->source_data capacity — SEGV on resolution upshift #13
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
mpv crashes immediately at the first frame of a 1920×1088 H.264 source when the libva session was initialized at a smaller resolution. Backtrace:
Verified on higgs (Pi CM5, daedalus path) with
LIBVA_DRIVER_NAME=v4l2_request mpv --hwdec=vaapi-copy bbb_1080p30_h264.mp4against a libva session whose CAPTURE buffers were sized for an earlier 1280×720 cap_pool_init.Location
src/picture.c:64-118—codec_store_buffer,VASliceDataBufferTypebranch.No
surface_object->source_data_capacity(or equivalent) is consulted.source_datawas allocated at surface-creation time for the resolution / level the libva client originally probed. When a stream uses larger slices than the buffer was sized for — e.g. a stream-level resolution upshift, or a single I-frame whose slice happens to be unusually large — the memcpy walks past the allocation.Fatal in mpv's --hwdec=vaapi-copy because the libavcodec VAAPI driver pre-allocates a single VA surface per FFmpeg frame; when the stream's first SPS lands at 1080p and the surface had been sized for 720p, the very first slice copy overflows.
In Firefox the bug is latent but doesn't crash visibly — VAAPI surfaces happen to be allocated with enough slack for typical YouTube resolution swings, and any small overrun lands in adjacent heap that isn't immediately dereferenced. Still a hazard.
Proposed fix
Track the source_data buffer capacity on
object_surface(or whereversource_datais allocated; likelysurface.cvaCreateSurfaces2/object_surface_data_setup) and consult it before eachmemcpy/memset:Applied at all three append sites (Annex-B start code, VP8 frame header padding, the slice payload itself).
Better fix
Grow
source_dataon demand when capacity is exceeded (reallocif heap-backed, or a configurable cap level chosen at surface creation that scales with the stream's max slice size). The current design pre-sizes for the resolution at surface creation, which is brittle against any stream-level resolution change.For a Phase 8 daedalus pipeline specifically, the bigger root cause is that surfaces should be recreated on resolution change rather than reused — but that's a larger refactor. Bounds-check first.
Severity
Medium-high — SIGSEGV inside a sandboxed process is recoverable (mpv crashes, user blinks, restarts), but the same overrun in Firefox's RDD process could in principle land in security-sensitive heap. Not exploitable as observed (memcpy is well-defined writes), but no reason to leave it unguarded.
Repro
LIBVA_DRIVER_NAME=v4l2_request mpv --hwdec=vaapi-copy <a 1080p H.264 mp4>where the daemon's startup default capture resolution is 720p.h264_set_controlsthen SIGSEGV.Graceful workaround for testing: pre-scale the source to match the daemon's startup capture default (1280×720 today), or restart the daemon with the larger resolution as default.