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())]);
