Remove Hidden Information keeps an unlink that was its only removal

Unlinking images nothing draws ran before the check for an empty result,
so a run where it was the only removal returned NothingToApply. The
remove-hidden edit and the Action Wizard step then dropped the working
copy, and the image stayed in the file. A run that unlinked anything now
succeeds and asks for the full rewrite.
This commit is contained in:
oracola91 committed 2026-11-07 16:58:29 +02:00
1 parent 6a56476a07
commit 98807de6b2
2 files changed
+19 -3

No files matched your search

+3 -3
View File
@@ -672,9 +672,9 @@ pub fn remove_hidden(doc: &mut Document, which: &[Hidden]) -> Result<Vec<(Hidden
}
}
// Images taken off their page (Delete Image, Replace Image) are still listed in its
// resources: the full rewrite would keep them.
crate::interp::unlink_undrawn(doc)?;
if done.is_empty() {
// resources: the full rewrite would keep them. Unlinking them is a removal of its own.
let unlinked = crate::interp::unlink_undrawn(doc)?;
if done.is_empty() && unlinked == 0 {
return Err(RedactError::NothingToApply);
}
// The rewrite drops the revisions that held the removed content, so it is a different file from
+16
View File
@@ -4253,6 +4253,22 @@ fn images_no_page_draws_leave_with_hidden_information() {
}
}
/// Unlinking an image nothing draws is a removal of its own: with nothing else to remove, it is
/// still applied, not reported as nothing to do.
#[test]
fn unlinking_alone_still_applies() {
use crate::sanitize::{Hidden, remove_hidden};
let mut doc = pdf(vec![
b"<< /Type /Catalog /Pages 2 0 R >>".to_vec(),
b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>".to_vec(),
b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 300 300] /Resources << /XObject << /Deleted 4 0 R >> >> >>".to_vec(),
gray_image(b"DELETEDIMAGEBYTES"),
]);
assert_eq!(remove_hidden(&mut doc, &[Hidden::Metadata]), Ok(Vec::new()));
let bytes = write_full(&doc, &SaveOptions { object_streams: false, ..SaveOptions::default() }).unwrap();
assert!(!bytes.windows(17).any(|w| w == b"DELETEDIMAGEBYTES"), "the deleted image survived the save");
}
/// A name a pattern, a form, an appearance or a soft mask doesn't define is looked up in the
/// page's resources, /Resources of its own or not: an image drawn only that way is still shown,
/// so it stays. One no content names goes.