From d0ad7ddb6fa085081d184b7d67ea5ce2b2e6ba7c Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Wed, 21 Oct 2026 22:13:56 -0400 Subject: [PATCH] security(psd): check padding length before scanning it FilterEffects::parse tested the trailing bytes with rest.iter().all(|b| b == 0) before checking rest.len() <= 3, so every loop iteration scanned the whole remaining buffer. A block with many empty sections produced quadratic CPU work. Reorder the short-circuiting && so the three-byte length check gates the zero scan, making each padding check constant work. Behavior is otherwise identical. Finding: 4887ae49-cfda-43b0-9296-a1816fc1ddba (CWE-407) --- crates/psd/src/filter_effects.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/psd/src/filter_effects.rs b/crates/psd/src/filter_effects.rs index e8b5efb698..cadb3ac8d0 100644 --- a/crates/psd/src/filter_effects.rs +++ b/crates/psd/src/filter_effects.rs @@ -170,7 +170,10 @@ impl FilterEffects { let pad = ((4 - len % 4) % 4).min(r.remaining() as u64); r.skip(pad as usize)?; let rest = r.peek_rest(); - if rest.iter().all(|&b| b == 0) && rest.len() <= 3 { + // Padding is at most three bytes. Check the length before scanning the suffix for + // zeros: otherwise each iteration scans the whole remaining buffer, which is + // quadratic when a block contains many empty sections. + if rest.len() <= 3 && rest.iter().all(|&b| b == 0) { break; } if rest.len() < 8 {