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

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-11882-08928b340c77062c1c343815e2d140f090bd110b
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git

commit 258f331c94ae360ffa91d84341ca211ccd9f8449
Author: Wleeaf <[email protected]>
AuthorDate: Sun Oct 25 23:02:27 2026 +0000

    fix(arrow-ipc): return an error instead of panicking on unions with more 
than 128 fields (#11882)
    
    # Which issue does this PR close?
    
    - Closes #11850.
    
    # Rationale for this change
    
    When an IPC schema has a union without `typeIds`, the type ids are
    assigned with `UnionFields::from_fields`, which panics if there are more
    than 128 children. The schema comes from untrusted input, so this should
    be an error.
    
    # What changes are included in this PR?
    
    Use the fallible `UnionFields::try_from_fields` in `get_data_type` and
    propagate its error, matching the `typeIds` branch, which already uses
    `UnionFields::try_new`.
    
    # Are these changes tested?
    
    Yes. The reproducer from the issue is added as
    `try_fb_to_schema_union_without_type_ids_too_many_fields_is_err`. It
    panics without the fix and passes with it.
    
    # Are there any significant user-facing changes?
    
    No.
    
    AI usage: this change was prepared with Claude Code (an AI coding
    agent). The fix and test were generated by it and checked against the
    failing test from the issue.
    
    Co-authored-by: Wleeaf <[email protected]>
    Co-authored-by: RIchard Baah <[email protected]>
---
 arrow-ipc/src/convert.rs | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/arrow-ipc/src/convert.rs b/arrow-ipc/src/convert.rs
index 936ad52b12..dff94fffff 100644
--- a/arrow-ipc/src/convert.rs
+++ b/arrow-ipc/src/convert.rs
@@ -583,7 +583,7 @@ pub(crate) fn get_data_type(
             }
 
             let fields = match union.typeIds() {
-                None => UnionFields::from_fields(fields),
+                None => UnionFields::try_from_fields(fields)?,
                 Some(ids) => UnionFields::try_new(ids.iter().map(|i| i as i8), 
fields)?,
             };
 
@@ -1187,6 +1187,32 @@ mod tests {
         assert_single_field_schema_is_err(fbb, field);
     }
 
+    #[test]
+    fn try_fb_to_schema_union_without_type_ids_too_many_fields_is_err() {
+        let mut fbb = FlatBufferBuilder::new();
+        let null = crate::Null::create(&mut fbb, &crate::NullArgs::default());
+        let child = crate::Field::create(
+            &mut fbb,
+            &crate::FieldArgs {
+                type_type: crate::Type::Null,
+                type_: Some(null.as_union_value()),
+                ..Default::default()
+            },
+        );
+        let children = fbb.create_vector(&[child; 129]);
+        let union = crate::Union::create(&mut fbb, 
&crate::UnionArgs::default());
+        let field = crate::Field::create(
+            &mut fbb,
+            &crate::FieldArgs {
+                type_type: crate::Type::Union,
+                type_: Some(union.as_union_value()),
+                children: Some(children),
+                ..Default::default()
+            },
+        );
+        assert_single_field_schema_is_err(fbb, field);
+    }
+
     #[test]
     fn convert_schema_round_trip() {
         let md = HashMap::from([("Key".to_string(), "value".to_string())]);

Reply via email to