This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch 57_maintenance
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/57_maintenance by this push:
new d0ea74f988 [57_maintenance] fix: `UnionFields::from_iter` should
validate input (#11726)
d0ea74f988 is described below
commit d0ea74f98887c697e80d6c7f5a5ca74546a90e5f
Author: Andrew Lamb <[email protected]>
AuthorDate: Wed Oct 21 15:33:46 2026 -0400
[57_maintenance] fix: `UnionFields::from_iter` should validate input
(#11726)
- Backport https://github.com/apache/arrow-rs/pull/11533
- For inclusion in https://github.com/apache/arrow-rs/issues/11666
Cherry-pick of
https://github.com/apache/arrow-rs/commit/b2e2c2d9c24a3bb9a8105bbf55fb03b337e917dd
Co-authored-by: Jeffrey Vo <[email protected]>
---
arrow-schema/src/fields.rs | 38 ++++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/arrow-schema/src/fields.rs b/arrow-schema/src/fields.rs
index 93638181d9..3b33d161b7 100644
--- a/arrow-schema/src/fields.rs
+++ b/arrow-schema/src/fields.rs
@@ -317,7 +317,12 @@ impl<'a> IntoIterator for &'a Fields {
}
}
-/// A cheaply cloneable, owned collection of [`FieldRef`] and their
corresponding type ids
+/// A cheaply cloneable, owned collection of [`FieldRef`] and their
corresponding
+/// type ids.
+///
+/// Invariants:
+/// - All type ids are unique
+/// - All type ids are non-negative
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
@@ -358,8 +363,9 @@ impl UnionFields {
/// # Errors
///
/// This function returns an error if:
+ /// - Iterators are not the same length
/// - Any type_id appears more than once (duplicate type ids)
- /// - The type_ids are duplicated
+ /// - There is a negative type_id
///
/// # Examples
///
@@ -672,14 +678,26 @@ impl UnionFields {
output.push((field_type_id, from_field.clone()))
}
}
- *self = output.into_iter().collect();
+ // TODO: see above comment; can we remove the need to go through
try_new
+ // and just validate in this function ourselves?
+ let (type_ids, fields): (Vec<i8>, Vec<FieldRef>) =
output.into_iter().unzip();
+ *self = Self::try_new(type_ids, fields)?;
Ok(())
}
}
impl FromIterator<(i8, FieldRef)> for UnionFields {
+ /// # Panics
+ ///
+ /// This will panic on invalid inputs:
+ /// - Duplicate type IDs
+ /// - Negative type IDs
+ ///
+ /// Prefer using [`UnionFields::try_new`] for a fallible construction
method.
fn from_iter<T: IntoIterator<Item = (i8, FieldRef)>>(iter: T) -> Self {
- Self(iter.into_iter().collect())
+ let iter = iter.into_iter();
+ let (type_ids, fields): (Vec<i8>, Vec<FieldRef>) = iter.unzip();
+ Self::try_new(type_ids, fields).expect("invalid arguments passed")
}
}
@@ -1039,4 +1057,16 @@ mod tests {
assert!(res.is_ok());
assert_eq!(res.unwrap().len(), 3);
}
+
+ #[test]
+ #[should_panic(
+ expected = "invalid arguments passed: InvalidArgumentError(\"type ids
must be non-negative: -1\")"
+ )]
+ fn test_union_fields_from_iter_should_validate() {
+ let fields: Vec<(i8, FieldRef)> = vec![
+ (0, Arc::new(Field::new("a", DataType::Int32, true))),
+ (-1, Arc::new(Field::new("a", DataType::Int32, true))),
+ ];
+ UnionFields::from_iter(fields);
+ }
}