mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-25 02:40:09 +00:00
Refuse header/footer Bates numbers that would overflow u64 (#2253)
Found while testing crates/edit/src/lib.rs:445 Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
@@ -136,3 +136,7 @@ real_name = "Alexander Alber"
|
||||
[people.mtlcl410]
|
||||
display_name = "mtlcl410"
|
||||
sync_github_name = false
|
||||
|
||||
[people.Silvertree2010]
|
||||
display_name = "Netter"
|
||||
sync_github_name = false
|
||||
|
||||
+10
-2
@@ -450,18 +450,26 @@ pub fn add_header_footer(doc: &mut Document, pages: &[usize], hf: &HeaderFooter,
|
||||
u32::MAX
|
||||
)));
|
||||
}
|
||||
// The same goes for Bates numbers: the last selected page must still fit in a u64.
|
||||
let bates0 = hf.text.iter().find_map(|t| bates_start(t)).unwrap_or(1);
|
||||
if bates0.checked_add(pages.len().saturating_sub(1) as u64).is_none() {
|
||||
return Err(EditError::Invalid(format!(
|
||||
"the Bates start number {bates0} leaves no room for {} pages (Bates numbers stop at {})",
|
||||
pages.len(),
|
||||
u64::MAX
|
||||
)));
|
||||
}
|
||||
if replace {
|
||||
remove_marks(doc, pages, MarkKind::HeaderFooter)?;
|
||||
}
|
||||
let all = page_list(doc);
|
||||
let count = all.len();
|
||||
let bates0 = hf.text.iter().find_map(|t| bates_start(t)).unwrap_or(1);
|
||||
for (k, &i) in pages.iter().enumerate() {
|
||||
let page = &all[i];
|
||||
let (w, h) = page.display_size(doc);
|
||||
let number =
|
||||
u32::try_from(u64::from(hf.start_number) + k as u64).map_err(|_| EditError::Invalid("the header page numbers are too large".into()))?;
|
||||
let bates = bates0 + k as u64;
|
||||
let bates = bates0.checked_add(k as u64).ok_or_else(|| EditError::Invalid("the Bates numbers are too large".into()))?;
|
||||
let size = hf.font_size;
|
||||
let [top, bottom, left, right] = hf.margins;
|
||||
let mut body: Vec<u8> = format!("BT\n/PCHelv {} Tf\n{}\n", n(size), rgb(hf.color)).into_bytes();
|
||||
|
||||
@@ -115,6 +115,23 @@ fn header_start_number_that_would_wrap_is_refused_without_drawing() {
|
||||
assert_eq!(marks_present(&doc).len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn header_bates_start_that_would_overflow_is_refused_without_drawing() {
|
||||
// A Bates start of u64::MAX has no room for a second page. The run must be refused up front
|
||||
// instead of overflowing (a panic in debug builds, a wrap to 0 in release builds).
|
||||
let mut doc = fixture();
|
||||
let hf = HeaderFooter {
|
||||
text: [String::new(), String::new(), "<<Bates Number#6#18446744073709551615#A#B>>".into(), String::new(), String::new(), String::new()],
|
||||
..HeaderFooter::default()
|
||||
};
|
||||
let err = add_header_footer(&mut doc, &[0, 1], &hf, false, &cx()).unwrap_err();
|
||||
assert!(err.to_string().contains("Bates"), "{err}");
|
||||
assert!(marks_present(&doc).is_empty(), "nothing is drawn when the run is refused");
|
||||
// A single page still fits the start number itself.
|
||||
add_header_footer(&mut doc, &[0], &hf, false, &cx()).unwrap();
|
||||
assert_eq!(marks_present(&doc).len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_and_remove_restore_the_original_content() {
|
||||
let mut doc = fixture();
|
||||
|
||||
Reference in New Issue
Block a user