Refuse ruled-line extraction after incomplete page content

This commit is contained in:
FredApps committed 2026-11-08 14:40:19 +01:00
1 parent a59e43e8a4
commit 4c49290289
2 files changed
+22

No files matched your search

+4
View File
@@ -26,6 +26,10 @@ pub fn page_rules(doc: &Document, page: usize) -> Result<Vec<[f64; 4]>, EditErro
let pages = pdfcraft_model::pages(doc);
let p = pages.get(page).ok_or(EditError::NoSuchPage(page))?;
let streams = crate::text::content_streams(doc, &p.dict)?;
// Unread content can change the graphics state used by every later stream.
if streams.iter().any(|stream| stream.read != crate::text::Read::Whole) {
return Err(EditError::Invalid("page content could not be completely decoded; cannot extract its ruled lines safely".into()));
}
let pieces = Pieces::join(&streams.iter().map(|stream| stream.data.as_slice()).collect::<Vec<_>>());
let ops = pieces.parse().ops;
+18
View File
@@ -11202,3 +11202,21 @@ fn review_inside_scope_group_move_matches_direct_transform_under_outer_scale() {
}
}
}
#[test]
fn page_rules_refuse_unread_graphics_state() {
let mut dict = Dict::new();
dict.set(b"Filter".to_vec(), Object::name("UnsupportedFilter"));
let unread = Stream::from_raw(dict, b"2 0 0 2 0 0 cm".to_vec());
let damaged = damaged_flate(b"0 g\n", b"2 0 0 2 0 0 cm");
for stream in [unread, damaged] {
let mut doc = image_page_with("10 10 m 100 10 l S");
let incomplete = doc.add(Object::Stream(stream));
doc.update_dict(ObjRef::new(3, 0), |page| {
page.set(b"Contents".to_vec(), Object::Array(vec![Object::Ref(incomplete), Object::Ref(ObjRef::new(4, 0))]));
})
.unwrap();
assert!(page_rules(&doc, 0).is_err(), "later geometry cannot be trusted after unread graphics state");
}
assert_eq!(page_rules(&image_page_with("10 10 m 100 10 l S"), 0).unwrap(), [[10.0, 10.0, 100.0, 10.0]]);
}