fix(print): refuse huge posters at the sheet limit instead of overflowing (#1335) (#1376)

A poster scale large enough to make both tile counts saturate at
usize::MAX overflowed when they were multiplied for the 1024-sheet
check: a panic with overflow checks, and a product that wraps to 1
without them, which let the sheet loops run. The headless doc_print
tool accepts any finite positive scale, so a script could reach it.

Multiply with checked_mul and treat an overflow as over the limit, so
the request gets the existing "more than 1024 sheets" error.

Adds tests::huge_posters_are_refused_at_the_sheet_limit, which panics
before this change and passes with and without overflow checks after it.
This commit is contained in:
Marco Arnulfo authored and GitHub committed 2026-10-12 06:27:50 -04:00
1 parent 9593ff7419
commit 2796f3de0d
2 files changed
+13 -1

No files matched your search

+2 -1
View File
@@ -467,7 +467,8 @@ pub fn layout(sizes: &[(f64, f64)], settings: &Settings) -> Result<Vec<Sheet>, P
let (stepx, stepy) = (tw - overlap, th - overlap);
let nx = (((sw - overlap) / stepx).ceil() as usize).max(1);
let ny = (((sh - overlap) / stepy).ceil() as usize).max(1);
if nx * ny > 1024 {
// The counts saturate at usize::MAX for a huge scale, so their product can overflow.
if nx.checked_mul(ny).is_none_or(|n| n > 1024) {
return Err(PrintError::Invalid("the poster would need more than 1024 sheets".into()));
}
// Tiles from the top-left, row by row.
+11
View File
@@ -192,6 +192,17 @@ fn posters_tile_with_overlap() {
assert!(layout(&[(200.0, 300.0)], &settings(vec![0], Layout::Poster { scale: 400.0, overlap: 400.0, cut_marks: false })).is_err());
}
/// Issue #1335: a scale so large that the tile counts saturate is refused with the sheet-limit
/// error, not an overflow in counting the sheets.
#[test]
fn huge_posters_are_refused_at_the_sheet_limit() {
let refused = Err(PrintError::Invalid("the poster would need more than 1024 sheets".into()));
for scale in [100_000.0, 1e22, f64::MAX] {
let poster = settings(vec![0], Layout::Poster { scale, overlap: 18.0, cut_marks: true });
assert_eq!(layout(&[(200.0, 300.0)], &poster), refused, "scale {scale}");
}
}
#[test]
fn imposed_pdf_has_the_sheets_and_honours_comments_and_forms() {
let doc = fixture(3);