This is an automated email from the ASF dual-hosted git repository.

Jefffrey pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 3b98da0a32 fix(arrow-ipc): return an error instead of panicking on IPC 
file with no footer schema (#10744)
3b98da0a32 is described below

commit 3b98da0a32f373007387f0058a84c5de885c6b03
Author: Aditya Mishra <[email protected]>
AuthorDate: Wed Aug 19 06:05:40 2026 +0530

    fix(arrow-ipc): return an error instead of panicking on IPC file with no 
footer schema (#10744)
    
    # Which issue does this PR close?
    
    - Closes #10663
    
    # Rationale for this change
    
    `FileReaderBuilder::build` read the footer's schema with
    
[`footer.schema().unwrap()`](https://github.com/bit2swaz/arrow-rs/blob/93180c87b97fe0b19cd4b84fdef6839230a01400/arrow-ipc/src/reader.rs#L1253).
    the schema table is optional in the footer flatbuffer, so an IPC file
    whose footer verifies but has no schema table makes that `unwrap()`
    panic instead of returning an error. the flatbuffer verifier accepts
    such a file, so this is reachable from untrusted input
    
    this is the same class of untrusted-input panic as #10437 and #10575.
    those two are in `convert.rs` and #10647 made them fallible, but this
    sink is one level up in `reader.rs` where the footer's schema table is
    absent, so #10647 leaves it alone
    
    # What changes are included in this PR?
    
    swap the `unwrap()` for `ok_or_else(...)?` returning an
    `ArrowError::ParseError`, matching the `recordBatches` check right above
    it
    
    # Are these changes tested?
    
    yes. added `test_missing_footer_schema_error` which builds a footer that
    verifies but has no schema table and checks `FileReader::try_new`
    returns `Err` instead of panicking
    
    # Are there any user-facing changes?
    
    reading a malformed IPC file with no footer schema now returns an
    `ArrowError` instead of panicking. no API changes
    
    ---------
    
    Co-authored-by: Andrew Lamb <[email protected]>
---
 arrow-ipc/src/reader.rs | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/arrow-ipc/src/reader.rs b/arrow-ipc/src/reader.rs
index 5e8a46cfab..c42cc5d31c 100644
--- a/arrow-ipc/src/reader.rs
+++ b/arrow-ipc/src/reader.rs
@@ -1250,7 +1250,9 @@ impl FileReaderBuilder {
 
         let total_blocks = blocks.len();
 
-        let ipc_schema = footer.schema().unwrap();
+        let ipc_schema = footer.schema().ok_or_else(|| {
+            ArrowError::ParseError("Unable to get schema from IPC 
Footer".to_string())
+        })?;
         if !ipc_schema.endianness().equals_to_target_endianness() {
             return Err(ArrowError::IpcError(
                 "the endianness of the source system does not match the 
endianness of the target system.".to_owned()
@@ -2194,6 +2196,43 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_missing_footer_schema_error() {
+        use crate::r#gen::File::{Footer, FooterArgs};
+        use flatbuffers::FlatBufferBuilder;
+
+        // a footer that verifies but has no schema table. record batches 
present
+        // (so the earlier ok_or_else passes) but schema absent, which used to 
panic.
+        let mut fbb = FlatBufferBuilder::new();
+        let record_batches = fbb.create_vector::<Block>(&[]);
+        let footer = Footer::create(
+            &mut fbb,
+            &FooterArgs {
+                version: MetadataVersion::V5,
+                schema: None,
+                dictionaries: None,
+                recordBatches: Some(record_batches),
+                custom_metadata: None,
+            },
+        );
+        fbb.finish(footer, None);
+        let footer_data = fbb.finished_data();
+
+        // assemble a minimal IPC file: magic header, footer, footer length, 
magic trailer
+        let mut buf = Vec::new();
+        buf.extend_from_slice(&crate::ARROW_MAGIC);
+        buf.extend_from_slice(footer_data);
+        buf.extend_from_slice(&(footer_data.len() as i32).to_le_bytes());
+        buf.extend_from_slice(&crate::ARROW_MAGIC);
+
+        let err = FileReader::try_new(Cursor::new(buf), None)
+            .expect_err("expected an error, not a panic");
+        assert!(
+            matches!(err, ArrowError::ParseError(_)),
+            "expected ParseError, got {err:?}"
+        );
+    }
+
     /// Test that the reader can read legacy files where empty list arrays 
were written with a 0-byte offsets buffer.
     #[test]
     fn test_read_legacy_empty_list_without_offsets_buffer() {

Reply via email to