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

Issue:
xref stream silently discarded
When loading a document, if an xref object cannot be uncompressed due to an unsupported filter, no error occurs and the entries it contains are discarded.

The following code replicates the issue: a valid PDF is provided, an invalid PDF is generated.

```rust
const PDF: &[u8; 317] = b"%PDF-1.5
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
2 0 obj<</Type/Pages/Count 1/Kids[3 0 R]/MediaBox[0 0 595 842]>>endobj
3 0 obj<</Type/Page/Parent 2 0 R>>endobj
4 0 obj<</Type/XRef/Index[1 3]/W[1 1 1]/Root 1 0 R/Size 4/Filter/ASCIIHexDecode/Length 19>>stream
010900013400017B00
endstream
endobj
startxref
164
%%EOF";

fn main() {
	let mut document = lopdf::Document::load_from(std::io::Cursor::new(PDF)).unwrap();
	document.save("out.pdf").unwrap();
}
```


Discussion / hints:

Fix patch:
diff --git a/src/object.rs b/src/object.rs
index da00bb3..e8ff0a3 100644
--- a/src/object.rs
+++ b/src/object.rs
@@ -770,11 +770,15 @@ impl Stream {
         }
     }
 
-    pub fn decompress(&mut self) {
-        if let Ok(data) = self.decompressed_content() {
-            self.dict.remove(b"DecodeParms");
-            self.dict.remove(b"Filter");
-            self.set_content(data);
-        }
+    pub fn decompress(&mut self) -> Result<()> {
+        let data = self.decompressed_content()?;
+        self.dict.remove(b"DecodeParms");
+        self.dict.remove(b"Filter");
+        self.set_content(data);
+        Ok(())
+    }
+
+    pub fn is_compressed(&self) -> bool {
+        self.dict.get(b"Filter").is_ok()
     }
 }
diff --git a/src/object_stream.rs b/src/object_stream.rs
index 6b9e6bc..85ff14c 100644
--- a/src/object_stream.rs
+++ b/src/object_stream.rs
@@ -16,7 +16,7 @@ pub struct ObjectStream {
 
 impl ObjectStream {
     pub fn new(stream: &mut Stream) -> Result<ObjectStream> {
-        stream.decompress();
+        let _ = stream.decompress();
 
         if stream.content.is_empty() {
             return Ok(ObjectStream {
diff --git a/src/parser_aux.rs b/src/parser_aux.rs
index 7ec1c56..6c22a5f 100644
--- a/src/parser_aux.rs
+++ b/src/parser_aux.rs
@@ -203,7 +203,9 @@ fn try_to_replace_encoded_text(
 
 /// Decode CrossReferenceStream
 pub fn decode_xref_stream(mut stream: Stream) -> Result<(Xref, Dictionary)> {
-    stream.decompress();
+    if stream.is_compressed() {
+        stream.decompress()?;
+    }
     let mut dict = stream.dict;
     let mut reader = Cursor::new(stream.content);
     let size = dict
diff --git a/src/processor.rs b/src/processor.rs
index fa3a8bd..1dd5375 100644
--- a/src/processor.rs
+++ b/src/processor.rs
@@ -34,7 +34,7 @@ impl Document {
     pub fn decompress(&mut self) {
         for object in self.objects.values_mut() {
             if let Object::Stream(ref mut stream) = *object {
-                stream.decompress()
+                let _ = stream.decompress();
             }
         }
     }


Test patch: