mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
Marking a tag as an artifact refuses content past the page's decode budget
This commit is contained in:
+19
-1
@@ -50,6 +50,8 @@ pub enum ArtifactError {
|
||||
AmbiguousParent,
|
||||
#[error("couldn't update the parent tree: {0}")]
|
||||
ParentTree(String),
|
||||
#[error("the page has more content than can be edited")]
|
||||
TooLarge,
|
||||
#[error(transparent)]
|
||||
Cos(#[from] pdfcraft_cos::CosError),
|
||||
}
|
||||
@@ -483,7 +485,23 @@ pub fn mark_tag_artifact(doc: &mut Document, obj: ObjRef) -> Result<(), Artifact
|
||||
let pages = pdfcraft_model::pages(doc);
|
||||
let page_ref = element.page.ok_or(ArtifactError::NoPage)?;
|
||||
let page = pages.iter().find(|page| page.obj == page_ref).ok_or(ArtifactError::NoPage)?;
|
||||
let mut ops = pdfcraft_content::parse(&page_content(doc, &page.dict)).ops;
|
||||
let mut content = Vec::new();
|
||||
if let Some(c) = page.dict.get(b"Contents") {
|
||||
let mut budget = DecodeBudget::page();
|
||||
for data in budget.decode_contents(doc, c) {
|
||||
match data {
|
||||
Ok(data) => {
|
||||
content.extend_from_slice(&data);
|
||||
content.push(b' ');
|
||||
}
|
||||
// The page's /Contents is replaced with what was decoded: content past the
|
||||
// budget would be dropped from the page.
|
||||
Err(_) if budget.exhausted() => return Err(ArtifactError::TooLarge),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut ops = pdfcraft_content::parse(&content).ops;
|
||||
let mut found = HashSet::new();
|
||||
for op in &mut ops {
|
||||
let id = (op.op == b"BDC")
|
||||
|
||||
@@ -1307,3 +1307,20 @@ fn content_past_the_decode_budget_needs_a_manual_check() {
|
||||
assert_eq!(status(&report, Rule::ImageOnly), Status::Manual);
|
||||
assert_eq!(status(&report, Rule::TaggedContent), Status::Manual);
|
||||
}
|
||||
|
||||
/// Marking a tag as an artifact replaces the page's content with what it decoded, so content past
|
||||
/// the page's decode budget is refused rather than dropped from the page.
|
||||
#[test]
|
||||
fn marking_a_tag_artifact_refuses_content_past_the_decode_budget() {
|
||||
use pdfcraft_cos::{Dict, ObjRef, Object, Stream};
|
||||
let mut doc = figures_doc();
|
||||
let filler = doc.add(Stream::flate(Dict::new(), &vec![b' '; 1 << 20]));
|
||||
let last = doc.add(Stream::from_raw(Dict::new(), b"0 0 5 5 re f".to_vec()));
|
||||
let mut contents = vec![Object::Ref(ObjRef::new(4, 0))];
|
||||
contents.extend(std::iter::repeat_n(Object::Ref(filler), 256));
|
||||
contents.push(Object::Ref(last));
|
||||
let contents = Object::Array(contents);
|
||||
doc.update_dict(ObjRef::new(3, 0), |p| p.set(b"Contents".to_vec(), contents.clone())).unwrap();
|
||||
assert_eq!(mark_tag_artifact(&mut doc, ObjRef::new(7, 0)), Err(ArtifactError::TooLarge));
|
||||
assert_eq!(doc.get(ObjRef::new(3, 0)).as_dict().unwrap().get(b"Contents"), Some(&contents), "the page keeps its content");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user