Skip to content

Commit 5989962

Browse files
committed
Reject negative union type IDs
Signed-off-by: "Connor Tsui" <connor.tsui20@gmail.com>
1 parent a6513a0 commit 5989962

1 file changed

Lines changed: 20 additions & 2 deletions

File tree

vortex-array/src/dtype/union.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use crate::dtype::Nullability;
2525
/// Per Arrow's spec, the per-row type tag is an `int8`. By default, tag `i` selects the child at
2626
/// offset `i` (`type_ids = [0, 1, ..., N-1]`).
2727
///
28+
/// Type IDs are restricted to the Arrow-compatible range `0..=127`; negative tags are rejected.
29+
///
2830
/// Schemas may also use non-consecutive tags (e.g. `[0, 5, 7]`), in which case the value of
2931
/// `type_ids[i]` is the tag used in the data to select the child at offset `i`. Supporting
3032
/// non-consecutive tags lets the schema remove children without renumbering the remaining tags.
@@ -179,6 +181,11 @@ impl UnionVariants {
179181
"type_ids must be distinct, got {:?}",
180182
type_ids
181183
);
184+
vortex_ensure!(
185+
type_ids.iter().all(|type_id| *type_id >= 0),
186+
"type_ids must be non-negative, got {:?}",
187+
type_ids
188+
);
182189
vortex_ensure!(
183190
names.iter().all_unique(),
184191
"union variant names must be distinct, got {:?}",
@@ -193,7 +200,7 @@ impl UnionVariants {
193200
/// # Errors
194201
///
195202
/// Returns an error if names, dtypes, or type IDs do not all have the same length, or if there
196-
/// are any duplicate names or type ids.
203+
/// are any duplicate names or type ids, or if a type ID is negative.
197204
pub fn try_new(names: FieldNames, dtypes: Vec<DType>, type_ids: Vec<i8>) -> VortexResult<Self> {
198205
Self::validate_shape(&names, dtypes.len(), &type_ids)?;
199206

@@ -237,7 +244,7 @@ impl UnionVariants {
237244
/// # Errors
238245
///
239246
/// Returns an error if names, dtypes, or type IDs do not all have the same length, or if there
240-
/// are any duplicate names or type ids.
247+
/// are any duplicate names or type ids, or if a type ID is negative.
241248
pub(crate) fn try_from_fields(
242249
names: FieldNames,
243250
dtypes: Vec<FieldDType>,
@@ -429,6 +436,17 @@ mod tests {
429436
assert!(result.unwrap_err().to_string().contains("distinct"));
430437
}
431438

439+
#[test]
440+
fn test_negative_type_ids_rejected() {
441+
let result = UnionVariants::try_new(
442+
["negative"].into(),
443+
vec![DType::Primitive(PType::I32, Nullability::NonNullable)],
444+
vec![-1],
445+
);
446+
assert!(result.is_err());
447+
assert!(result.unwrap_err().to_string().contains("non-negative"));
448+
}
449+
432450
#[test]
433451
fn test_length_mismatch_rejected() {
434452
let result = UnionVariants::try_new(

0 commit comments

Comments
 (0)