Skip to content

Commit 666f8dc

Browse files
fix(arrow/array): validate union child upper bound (#1043)
## What changed Reject a union child index equal to the number of children. ## Why The previous bounds check allowed `idx == len(children)` through, causing a generic runtime index panic instead of the intended Arrow validation panic. The regression test covers both the negative and upper bounds for dense and sparse union builders. ## Validation `go test ./arrow/array`
1 parent 5327f57 commit 666f8dc

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

arrow/array/union.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ func (b *unionBuilder) NumChildren() int {
801801
}
802802

803803
func (b *unionBuilder) Child(idx int) Builder {
804-
if idx < 0 || idx > len(b.children) {
804+
if idx < 0 || idx >= len(b.children) {
805805
panic("arrow/array: invalid child index for union builder")
806806
}
807807
return b.children[idx]

arrow/array/union_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,41 @@ func int32ArrFromSlice(offsets ...int32) arrow.Array {
4242
return array.MakeFromData(data)
4343
}
4444

45+
func TestUnionBuilderChildBounds(t *testing.T) {
46+
fields := []arrow.Field{{Name: "value", Type: arrow.PrimitiveTypes.Int32}}
47+
codes := []arrow.UnionTypeCode{0}
48+
tests := []struct {
49+
name string
50+
new func() array.UnionBuilder
51+
}{
52+
{
53+
name: "dense",
54+
new: func() array.UnionBuilder {
55+
return array.NewDenseUnionBuilder(memory.DefaultAllocator, arrow.DenseUnionOf(fields, codes))
56+
},
57+
},
58+
{
59+
name: "sparse",
60+
new: func() array.UnionBuilder {
61+
return array.NewSparseUnionBuilder(memory.DefaultAllocator, arrow.SparseUnionOf(fields, codes))
62+
},
63+
},
64+
}
65+
66+
for _, tt := range tests {
67+
t.Run(tt.name, func(t *testing.T) {
68+
builder := tt.new()
69+
defer builder.Release()
70+
71+
for _, index := range []int{-1, len(fields)} {
72+
assert.PanicsWithValue(t, "arrow/array: invalid child index for union builder", func() {
73+
builder.Child(index)
74+
})
75+
}
76+
})
77+
}
78+
}
79+
4580
func TestUnionSliceEquals(t *testing.T) {
4681
unionFields := []arrow.Field{
4782
{Name: "u0", Type: arrow.PrimitiveTypes.Int32, Nullable: true},

0 commit comments

Comments
 (0)