Ignore a negative trailer /Size in incremental saves (#5566)

Found while testing crates/cos/src/writer.rs:248

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-11-01 15:04:36 -05:00
committed by GitHub
co-authored by Claude Haiku 5.5
parent fdaa502f27
commit 2289b5755d
2 changed files with 11 additions and 1 deletions
+1 -1
View File
@@ -245,7 +245,7 @@ pub fn write_incremental(doc: &Document, opts: &SaveOptions) -> Result<Vec<u8>,
if let Some(p) = prev {
trailer.set(b"Prev".to_vec(), Object::Int(p as i64));
}
let size = doc.next_num().max(trailer.int(b"Size").unwrap_or(0) as u32);
let size = doc.next_num().max(trailer.int(b"Size").map_or(0, |n| n.clamp(0, i64::from(u32::MAX)) as u32));
if as_stream {
let rows = offsets.iter().map(|(n, (o, g, used))| (*n, if *used { Row::InFile(*o, *g) } else { Row::Free(*g) })).collect();
write_xref_stream(&mut out, base, &mut trailer, rows, size);
+10
View File
@@ -228,6 +228,16 @@ fn incremental_save_keeps_a_trailer_only_edit() {
assert_qpdf_clean(&saved);
}
#[test]
fn incremental_save_ignores_a_negative_trailer_size() {
let mut doc = Document::open(Arc::new(classic_table())).unwrap();
doc.trailer_mut().set(b"Size".to_vec(), Object::Int(-1));
let next = doc.add(Object::Int(5)).num + 1;
let saved = write_incremental(&doc, &SaveOptions::default()).unwrap();
let back = Document::open(Arc::new(saved)).unwrap();
assert_eq!(back.trailer().int(b"Size"), Some(i64::from(next)));
}
/// What one edit added and a later one unlinked (a deleted comment, a cleared redaction mark) is
/// not written: the file never held it, and writing it would keep what was removed. Additions the
/// update still refers to, from the trailer or a changed object and through other additions, are.