From 801fd3aa676be57fa3e686704d305b08a61fe106 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Tue, 3 Nov 2026 15:10:02 -0500 Subject: [PATCH] fix(engine): decode signature preview images within a small work allowance (#5981) * fix(engine): decode signature preview images within a small work allowance * style: rustfmt --- crates/engine/src/signature_image.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/signature_image.rs b/crates/engine/src/signature_image.rs index ae8842ddfb..074adfc82d 100644 --- a/crates/engine/src/signature_image.rs +++ b/crates/engine/src/signature_image.rs @@ -55,7 +55,10 @@ impl Document { if w <= 0 || h <= 0 || w > i64::from(MAX_SIDE) || h > i64::from(MAX_SIDE) || w.saturating_mul(h) > MAX_PIXELS as i64 { return Err(SignatureImageError::PlacedSize.to_string()); } - let (_, bytes) = pdfcraft_create::image_file(&editor.cos, picture)?; + // Decoded within an allowance sized for the small picture a signature is, not the + // document's: a stream that inflates past it is refused before it is held whole. + let (_, bytes) = + pdfcraft_create::image_file_within(&editor.cos, picture, &mut pdfcraft_cos::ImageBudget::with_work(SIGNATURE_IMAGE_WORK))?; let image = SignatureImage::from_bytes(&bytes).map_err(|e| e.to_string())?; let opacity = pdfcraft_annot::props(&editor.cos, page, index).map(|p| p.opacity).filter(|v| v.is_finite()).unwrap_or(1.0).clamp(0.0, 1.0) as f32; @@ -90,6 +93,9 @@ pub fn upright_box(rotation: i64, at: [f64; 2], width: f64, height: f64) -> Opti /// Saved signatures live in settings, so both source and normalized PNG are bounded. pub const MAX_SIGNATURE_IMAGE_BYTES: usize = 4 << 20; const MAX_PIXELS: u64 = 4 << 20; +/// Steps of decoding the signature's picture may take: every stage of its filters, for a +/// picture of at most [`MAX_PIXELS`] samples, fits in it many times over. +const SIGNATURE_IMAGE_WORK: u64 = 1 << 28; const MAX_SIDE: u32 = 4096; /// Larger sources (scans, phone photos) are decoded within these bounds, then scaled down. const MAX_SOURCE_SIDE: u32 = 8192;