M2.6: tests pin that content which doesn't decode is kept and edited around

A stream that doesn't decode at all is not damage to write over: edit and
accessibility keep it as stored and go on with the page's other streams,
and only running past the page's decode allowance refuses. Nothing pinned
either, nor that selecting objects reads a stream of a few MB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmsdeUCdTaD72jkDw2pJKY
This commit is contained in:
Grzegorz MartensandClaude Opus 5.5 committed 2026-11-07 12:37:35 +01:00
1 parent 50d0fcc403
commit 3fec35e1ea
2 files changed
+37

No files matched your search

+17
View File
@@ -1129,6 +1129,23 @@ fn a_tags_content_in_a_stream_damaged_partway_is_not_rewritten() {
assert_ne!(list.get(1), Some(&Object::Ref(ObjRef::new(4, 0))), "the tag's stream is rewritten");
}
/// A content stream that doesn't decode at all is kept as stored, and a tag in the page's other
/// streams is still marked: only running past the decode budget refuses.
#[test]
fn a_tag_beside_a_stream_that_does_not_decode_is_marked() {
use pdfcraft_cos::{Dict, ObjRef, Object, Stream};
let mut doc = figures_doc();
let mut dict = Dict::new();
dict.set(b"Filter".to_vec(), Object::name("NoSuchFilter"));
let other = doc.add(Object::Stream(Stream::from_raw(dict, b"0 g".to_vec())));
doc.update_dict(ObjRef::new(3, 0), |p| p.set(b"Contents".to_vec(), Object::Array(vec![Object::Ref(other), Object::Ref(ObjRef::new(4, 0))])))
.unwrap();
mark_tag_artifact(&mut doc, ObjRef::new(7, 0)).unwrap();
let contents = doc.get(ObjRef::new(3, 0)).as_dict().unwrap().get(b"Contents").cloned();
let Some(Object::Array(list)) = contents else { panic!("contents {contents:?}") };
assert_eq!(list.first(), Some(&Object::Ref(other)), "kept as stored");
}
fn ref_(n: u32) -> Option<pdfcraft_cos::ObjRef> {
Some(pdfcraft_cos::ObjRef::new(n, 0))
}
+20
View File
@@ -5198,6 +5198,26 @@ fn an_edit_never_rewrites_a_content_stream_damaged_partway() {
assert_eq!(kept.raw, damaged.raw, "stored as it was");
}
/// A content stream that doesn't decode at all is no damage to write over: it is kept as stored,
/// and the page's other streams are read and edited around it. A stream of a few MB is read for
/// selecting objects.
#[test]
fn a_content_stream_that_does_not_decode_is_kept_and_edited_around() {
let mut doc = split_page("", "BT /F1 12 Tf 72 600 Td (Whole) Tj ET");
let mut dict = pdfcraft_cos::Dict::new();
dict.set(b"Filter".to_vec(), Object::name("NoSuchFilter"));
let unknown = pdfcraft_cos::Stream::from_raw(dict, b"BT /F1 12 Tf 72 700 Td (Unread) Tj ET".to_vec());
doc.set(pdfcraft_cos::ObjRef::new(4, 0), unknown.clone());
text::replace_line(&mut doc, 0, 0, "Edited").unwrap();
let doc = reopen(&doc);
assert_eq!(text::text_lines(&doc, 0).unwrap().into_iter().map(|l| l.text).collect::<Vec<_>>(), ["Edited"]);
let Object::Stream(kept) = &*doc.get(pdfcraft_cos::ObjRef::new(4, 0)) else { panic!("not a stream") };
assert_eq!(kept.raw, unknown.raw, "stored as it was");
let large = format!("{}0 0 m 10 10 l S", " ".repeat(2 << 20));
assert!(editable_objects(&split_page(&large, "BT /F1 12 Tf 72 600 Td (Whole) Tj ET"), 0).is_ok());
}
/// Objects are selected only from content read whole: what a damaged stream hides past the
/// damage could change the graphics state of every later item.
#[test]