Repository: J-F-Liu/lopdf (language: rust)

Issue:
Panic `ObjectNotFound` in `src/document.rs:446:83`
```
thread 'main' panicked at /home/rafal/.cargo/git/checkouts/lopdf-0013854ec52a6141/c25cef3/src/document.rs:446:83:
called `Result::unwrap()` on an `Err` value: ObjectNotFound
stack backtrace:
   0: rust_begin_unwind
             at /rustc/7120fdac7a6e55a5e4b606256042890b36067052/library/std/src/panicking.rs:665:5
   1: core::panicking::panic_fmt
             at /rustc/7120fdac7a6e55a5e4b606256042890b36067052/library/core/src/panicking.rs:74:14
   2: core::result::unwrap_failed
             at /rustc/7120fdac7a6e55a5e4b606256042890b36067052/library/core/src/result.rs:1679:5
   3: core::result::Result<T,E>::unwrap
             at /rustc/7120fdac7a6e55a5e4b606256042890b36067052/library/core/src/result.rs:1102:23
   4: lopdf::document::Document::get_page_resources
             at /home/rafal/.cargo/git/checkouts/lopdf-0013854ec52a6141/c25cef3/src/document.rs:446:13
   5: lopdf::document::Document::get_page_fonts
             at /home/rafal/.cargo/git/checkouts/lopdf-0013854ec52a6141/c25cef3/src/document.rs:478:45
   6: lopdf::parser_aux::<impl lopdf::document::Document>::extract_text
             at /home/rafal/.cargo/git/checkouts/lopdf-0013854ec52a6141/c25cef3/src/parser_aux.rs:71:25
   7: lopdf::check_file
             at /home/rafal/Projekty/Rust/run_command_for_every_file/src/crates/lopdf/src/main.rs:41:29
   8: lopdf::main
             at /home/rafal/Projekty/Rust/run_command_for_every_file/src/crates/lopdf/src/main.rs:23:9
   9: core::ops::function::FnOnce::call_once
             at /rustc/7120fdac7a6e55a5e4b606256042890b36067052/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Aborted (core dumped)

```

code
```
fn check_file(file_path: &str) {
    let Ok(content) = fs::read(file_path) else {
        return;
    };
    let cursor = Cursor::new(content);
    match Document::load_from(cursor) {
        Ok(mut document) => {
            let pages = document.get_pages();

            let mut doc_clone = document.clone();
            doc_clone.decompress();

            for (i, _) in pages.iter().enumerate() {
                let page_number = (i + 1) as u32;
                let _text = document.extract_text(&[page_number]);
            }

            let _ = document.save_to(&mut Cursor::new(Vec::new()));
        }
        Err(err) => {
            eprintln!("Error reading PDF contents: {}", err)
        }
    }
}
```

file - [crash.pdf.zip](https://github.com/user-attachments/files/16594769/crash.pdf.zip)



Discussion / hints:

Fix patch:
diff --git a/src/document.rs b/src/document.rs
index aea5abd..7d1348b 100644
--- a/src/document.rs
+++ b/src/document.rs
@@ -420,7 +420,7 @@ impl Document {
     }
 
     /// Get resources used by a page.
-    pub fn get_page_resources(&self, page_id: ObjectId) -> (Option<&Dictionary>, Vec<ObjectId>) {
+    pub fn get_page_resources(&self, page_id: ObjectId) -> Result<(Option<&Dictionary>, Vec<ObjectId>)> {
         fn collect_resources(
             page_node: &Dictionary, resource_ids: &mut Vec<ObjectId>, doc: &Document,
             already_seen: &mut HashSet<ObjectId>,
@@ -443,13 +443,13 @@ impl Document {
         let mut resource_ids = Vec::new();
         if let Ok(page) = self.get_dictionary(page_id) {
             resource_dict = page.get(b"Resources").and_then(Object::as_dict).ok();
-            collect_resources(page, &mut resource_ids, self, &mut HashSet::new()).unwrap();
+            collect_resources(page, &mut resource_ids, self, &mut HashSet::new())?;
         }
-        (resource_dict, resource_ids)
+        Ok((resource_dict, resource_ids))
     }
 
     /// Get fonts used by a page.
-    pub fn get_page_fonts(&self, page_id: ObjectId) -> BTreeMap<Vec<u8>, &Dictionary> {
+    pub fn get_page_fonts(&self, page_id: ObjectId) -> Result<BTreeMap<Vec<u8>, &Dictionary>> {
         fn collect_fonts_from_resources<'a>(
             resources: &'a Dictionary, fonts: &mut BTreeMap<Vec<u8>, &'a Dictionary>, doc: &'a Document,
         ) {
@@ -475,7 +475,7 @@ impl Document {
         }
 
         let mut fonts = BTreeMap::new();
-        let (resource_dict, resource_ids) = self.get_page_resources(page_id);
+        let (resource_dict, resource_ids) = self.get_page_resources(page_id)?;
         if let Some(resources) = resource_dict {
             collect_fonts_from_resources(resources, &mut fonts, self);
         }
@@ -484,7 +484,7 @@ impl Document {
                 collect_fonts_from_resources(resources, &mut fonts, self);
             }
         }
-        fonts
+        Ok(fonts)
     }
 
     /// Get the PDF annotations of a page. The /Subtype of each annotation dictionary defines the
diff --git a/src/parser_aux.rs b/src/parser_aux.rs
index eff1a0f..b335c14 100644
--- a/src/parser_aux.rs
+++ b/src/parser_aux.rs
@@ -68,7 +68,7 @@ impl Document {
         let pages = self.get_pages();
         for page_number in page_numbers {
             let page_id = *pages.get(page_number).ok_or(Error::PageNumberNotFound(*page_number))?;
-            let fonts = self.get_page_fonts(page_id);
+            let fonts = self.get_page_fonts(page_id)?;
             let encodings = fonts
                 .into_iter()
                 .map(|(name, font)| (name, font.get_font_encoding()))
@@ -108,7 +108,7 @@ impl Document {
             .nth(page)
             .ok_or(Error::PageNumberNotFound(page_number))?;
         let encodings = self
-            .get_page_fonts(page_id)
+            .get_page_fonts(page_id)?
             .into_iter()
             .map(|(name, font)| (name, font.get_font_encoding().to_owned()))
             .collect::<BTreeMap<Vec<u8>, String>>();


Test patch: