diff --git a/crates/cos/src/document/reader.rs b/crates/cos/src/document/reader.rs index 0bd4c980cd..8c52ea15de 100644 --- a/crates/cos/src/document/reader.rs +++ b/crates/cos/src/document/reader.rs @@ -417,10 +417,13 @@ impl Document { // Each section's rows are capped, so the chain is too: at most MAX_XREF_OBJECTS rows // merged in all, or the file is rebuilt from object headers, as when one section's // stream decodes past that. This counts rows merged, not the map's size, since a chain - // that relists the same objects costs as much to merge. A section's rows (its hybrid - // stream's included) never outnumber the rows the compact reader counts for it, and - // that reader stops at about a quarter of this cap: no chain within its limit is refused. - let Some(total) = merged_rows.checked_add(sect.len()).filter(|total| *total <= MAX_XREF_OBJECTS) else { + // that relists the same objects costs as much to merge. Rows set aside count too: they + // are kept for the whole chain, and a section can set aside nearly all it lists. A + // section's rows (its hybrid stream's included) never outnumber the rows the compact + // reader counts for it, and that reader stops at about a quarter of this cap: no chain + // within its limit is refused. + let rows = sect.len().saturating_add(odd.len()); + let Some(total) = merged_rows.checked_add(rows).filter(|total| *total <= MAX_XREF_OBJECTS) else { return Err(CosError::Syntax { offset: usize::try_from(off).unwrap_or(usize::MAX), detail: format!("cross-reference chain lists more than {MAX_XREF_OBJECTS} entries"),