fix(encode): reject a non-positive playback rate - #235
Closed
LeadcodeDev wants to merge 1 commit into
Closed
LeadcodeDev wants to merge 1 commit into
LeadcodeDev wants to merge 1 commit into
Conversation
LeadcodeDev
force-pushed
the
fix/encode-atempo-guard
branch
from
September 21, 2026 23:39
886e5ea to
22c3b05
Compare
53 tasks
LeadcodeDev
force-pushed
the
fix/encode-atempo-guard
branch
from
September 22, 2026 06:10
c26ae08 to
3e994c1
Compare
LeadcodeDev
added this pull request to stack #280
September 22, 2026 06:40
LeadcodeDev
force-pushed
the
fix/encode-atempo-guard
branch
from
September 22, 2026 08:34
3e994c1 to
13ebfda
Compare
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
force-pushed
the
fix/encode-atempo-guard
branch
from
September 22, 2026 08:43
13ebfda to
4a6de54
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Severity Medium, category correctness. Location:
crates/rustmotion/src/encode/video_audio.rs:221Impact
remainingnever 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 freshStringon 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}—volumedefaults to 1.0 (crates/rustmotion-components/src/video.rs:14fn default_volume() -> f32 { 1.0 }), socollect_videos_in_childcollects it (v.volume > 0.0, line 128),collect_video_audio_trackscallsextract_audio_to_wav(..., occ.playback_rate)(line 421), which callsbuild_atempo_filter(0.0)at line 333.playback_rateis an unvalidatedOption<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_implline 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 rejectingplayback_rate <= 0at load time would also stoppreload.rs:182, which consumes the same field.Evidence the audit read
Part of the September 2026 audit remediation chantier. Refs #220 (RM-18).