Skip to content

fix(encode): reject a non-positive playback rate - #235

Closed
LeadcodeDev wants to merge 1 commit into
fix/encode-atomic-outputfrom
fix/encode-atempo-guard
Closed

LeadcodeDev wants to merge 1 commit into
fix/encode-atomic-outputfrom
fix/encode-atempo-guard

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Severity Medium, category correctness. Location: crates/rustmotion/src/encode/video_audio.rs:221

Impact

remaining never reaches 0.5 when it starts at 0.0 (0.0/0.5 == 0.0) or at any negative value (it diverges toward -inf). The loop never terminates and pushes a fresh String on every iteration, so rustmotion hangs while consuming memory until the OOM killer fires. Reached from a plain scenario JSON: {"type":"video","src":"clip.mp4","playback_rate":0} — volume defaults to 1.0 (crates/rustmotion-components/src/video.rs:14 fn default_volume() -> f32 { 1.0 }), so collect_videos_in_child collects it (v.volume > 0.0, line 128), collect_video_audio_tracks calls extract_audio_to_wav(..., occ.playback_rate) (line 421), which calls build_atempo_filter(0.0) at line 333. playback_rate is an unvalidated Option<f64> (crates/rustmotion-components/src/video.rs:26); a repo-wide grep shows no validator constrains it. Both the ffmpeg render path (encode_with_ffmpeg_hw_impl line 432) and the native path (mux.rs:34) reach it.

Fix

Guard the entry point: if !rate.is_finite() || rate <= 0.0 { return None; } (or surface a schema error naming the component), and additionally bound the stage count so no future arithmetic edge case can spin. A validation rule rejecting playback_rate <= 0 at load time would also stop preload.rs:182, which consumes the same field.

Evidence the audit read

} else {
        // Each stage multiplies by at least 0.5
        while remaining < 0.5 - EPSILON {
            parts.push("atempo=0.5".to_string());
            remaining /= 0.5;
        }

Stacked on fix/encode-atomic-output, which carries the previous finding of this workstream. GitHub shows only this finding's diff; merge in order.

Part of the September 2026 audit remediation chantier. Refs #220 (RM-18).

@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 21, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 21, 2026
@LeadcodeDev
LeadcodeDev force-pushed the fix/encode-atempo-guard branch from 886e5ea to 22c3b05 Compare September 21, 2026 23:39
@LeadcodeDev
LeadcodeDev force-pushed the fix/encode-atempo-guard branch from c26ae08 to 3e994c1 Compare September 22, 2026 06:10
@LeadcodeDev
LeadcodeDev added this pull request to stack #280 September 22, 2026 06:40
@LeadcodeDev
LeadcodeDev force-pushed the fix/encode-atempo-guard branch from 3e994c1 to 13ebfda Compare September 22, 2026 08:34
remaining never reaches 0.5 when it starts at 0.0 (0.0/0.5 == 0.0) or at any
negative value (it diverges toward -inf). The loop never terminates and
pushes a fresh String on every iteration, so rustmotion hangs while
consuming memory until the OOM killer fires. Reached from a plain scenario
JSON: {"type":"video","src":"clip.mp4","playback_rate":0} — volume defaults
to 1.0 (crates/rustmotion-components/src/video.rs:14 fn default_volume() ->
f32 { 1.0 }), so collect_videos_in_child collects it (v.volume > 0.0, line
128), collect_video_audio_tracks calls extract_audio_to_wav(...,
occ.playback_rate) (line 421), which calls build_atempo_filter(0.0) at line
333. playback_rate is an unvalidated Option<f64> (crates/rustmotion-
components/src/video.rs:26); a repo-wide grep shows no validator constrains
it. Both the ffmpeg render path (encode_with_ffmpeg_hw_impl line 432) and
the native path (mux.rs:34) reach it.

Fix: Guard the entry point: if !rate.is_finite() || rate <= 0.0 { return
None; } (or surface a schema error naming the component), and additionally
bound the stage count so no future arithmetic edge case can spin. A
validation rule rejecting playback_rate <= 0 at load time would also stop
preload.rs:182, which consumes the same field.

Refs #220
@LeadcodeDev
LeadcodeDev force-pushed the fix/encode-atempo-guard branch from 13ebfda to 4a6de54 Compare September 22, 2026 08:43
@LeadcodeDev
LeadcodeDev deleted the branch fix/encode-atomic-output September 22, 2026 08:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant