project: output_size never asks for sides past the comp limit

A 30 000 px comp (the repaired MAX_SIZE on load) at resolution 4.0
produced 120 000 px sides, which overflow u32 in the exporters'
w * h * 4 (debug panic, release wrap then slice panic) after already
requesting a ~57 GB frame. The resize path in the same file clamps to
30 000; output_size now does too.

Regression test: output_size_never_exceeds_the_comp_limit — on main it
returns (120000, 120000); with the clamp (30000, 30000), through both
RenderSettings and the OutputModule wrapper.
This commit is contained in:
midasmatterhorn
2026-10-16 14:37:14 +03:00
parent 19d19a339e
commit 912f828aa3
+15 -1
View File
@@ -444,7 +444,11 @@ impl RenderSettings {
}
pub fn output_size(&self, comp: &Comp) -> (u32, u32) {
let s = self.resolution.clamp(0.01, 4.0);
(((comp.width as f64 * s).round() as u32).max(1), ((comp.height as f64 * s).round() as u32).max(1))
// A 30 000 px comp at 4x would otherwise request 120 000 px sides, overflowing
// `w * h * 4` in the exporters. The resize path clamps to the same limit.
let w = ((comp.width as f64 * s).round() as u32).max(1).min(30_000);
let h = ((comp.height as f64 * s).round() as u32).max(1).min(30_000);
(w, h)
}
pub fn resolution_label(&self) -> &'static str {
match self.resolution {
@@ -1663,6 +1667,16 @@ mod tests {
assert_eq!(m.output_size(&c, &half), (400, 200));
}
#[test]
fn output_size_never_exceeds_the_comp_limit() {
// 30 000 px at 4x must not request 120 000 px sides (exporter `w * h * 4`).
let c = Comp::new(30_000, 30_000, FrameRate::new(30, 1), Tick::from_seconds_f64(1.0));
let rs = RenderSettings { resolution: 4.0, ..Default::default() };
assert_eq!(rs.output_size(&c), (30_000, 30_000));
let m = OutputModule::for_format(OutputFormat::PngSequence);
assert_eq!(m.output_size(&c, &rs), (30_000, 30_000));
}
#[test]
fn uncompressed_quicktime_format() {
let f = OutputFormat::from_name("uncompressed").unwrap();