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

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new c253857b fix(array): validate dense union offset lengths (#875)
c253857b is described below

commit c253857b6873a83ad7ca26be32ecb5b9d35b16ce
Author: Minh Vu <[email protected]>
AuthorDate: Wed Jul 1 18:20:02 2026 +0200

    fix(array): validate dense union offset lengths (#875)
    
    ### What changed
    
    NewDenseUnionFromArraysWithFieldCodes now rejects mismatched type ID and
    offset lengths before constructing dense union data.
    
    ### Why
    
    Dense unions use typeIDs.Len() as the logical length while borrowing the
    offsets buffer. If the offsets array is shorter, later access can panic
    or read invalid offset data; if it is longer, trailing offsets are
    silently ignored.
    
    ### Validation
    
    - go test ./arrow/array -run 'TestUnions/TestMakeDenseUnions' -count=1
    - go test ./arrow/array -count=1
    -
    PARQUET_TEST_DATA=/Users/hoangvu/Code/OSS/arrow-go/parquet-testing/data
    ARROW_TEST_DATA=/Users/hoangvu/Code/OSS/arrow-go/arrow-testing/data go
    test ./... -count=1
---
 arrow/array/union.go      |  2 ++
 arrow/array/union_test.go | 14 ++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/arrow/array/union.go b/arrow/array/union.go
index beaaf4e1..d9d18267 100644
--- a/arrow/array/union.go
+++ b/arrow/array/union.go
@@ -549,6 +549,8 @@ func NewDenseUnionFromArraysWithFieldCodes(typeIDs, offsets 
arrow.Array, childre
                return nil, errors.New("arrow/array: union typeIDs may not have 
nulls")
        case offsets.NullN() != 0:
                return nil, errors.New("arrow/array: nulls are not allowed in 
offsets for NewDenseUnionFromArrays*")
+       case typeIDs.Len() != offsets.Len():
+               return nil, errors.New("arrow/array: union typeIDs and offsets 
must have the same length")
        case len(fields) > 0 && len(fields) != len(children):
                return nil, errors.New("arrow/array: fields must be the same 
length as children")
        case len(codes) > 0 && len(codes) != len(children):
diff --git a/arrow/array/union_test.go b/arrow/array/union_test.go
index aa03056a..5d975d57 100644
--- a/arrow/array/union_test.go
+++ b/arrow/array/union_test.go
@@ -457,6 +457,20 @@ func (s *UnionFactorySuite) TestMakeDenseUnions() {
                defer result.Release()
                s.Error(result.ValidateFull())
        })
+
+       s.Run("mismatched type ids and offset lengths", func() {
+               shortOffsets := s.offsetsFromSlice(0, 0, 0, 1, 1, 0, 1, 2, 1)
+               defer shortOffsets.Release()
+               result, err := array.NewDenseUnionFromArrays(s.typeIDs, 
shortOffsets, children)
+               s.Nil(result)
+               s.EqualError(err, "arrow/array: union typeIDs and offsets must 
have the same length")
+
+               longOffsets := s.offsetsFromSlice(0, 0, 0, 1, 1, 0, 1, 2, 1, 2, 
0)
+               defer longOffsets.Release()
+               result, err = array.NewDenseUnionFromArrays(s.typeIDs, 
longOffsets, children)
+               s.Nil(result)
+               s.EqualError(err, "arrow/array: union typeIDs and offsets must 
have the same length")
+       })
 }
 
 func (s *UnionFactorySuite) TestDenseUnionStringRoundTrip() {

Reply via email to