From fad81f1271abf0bcd4d3cc2441211b419dd0decc Mon Sep 17 00:00:00 2001 From: Noah Treuhaft Date: Thu, 28 May 2026 18:25:40 -0400 Subject: [PATCH] vam: fix panic in upcast() runtime/vam/expr/function.Upcast.deunionAndUpcast does not change the type of zero-length vectors. This causes trouble because the vectors passed to vbuild.MergeSameTypesInDynamic then have multiple types, causing that function to return a vector.Dynamic instead of the expected vector with the target type. Fix by changing the type of zero-length vectors to the target type in deunionAndUpcast and then skipping zero-length vectors in vbuild.Merge. --- runtime/vam/expr/function/upcast.go | 15 ++++++++------- runtime/ztests/expr/function/defuse.yaml | 3 --- vector/vbuild/merge.go | 3 +++ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/runtime/vam/expr/function/upcast.go b/runtime/vam/expr/function/upcast.go index 98bcc5af4..cd9777015 100644 --- a/runtime/vam/expr/function/upcast.go +++ b/runtime/vam/expr/function/upcast.go @@ -2,7 +2,6 @@ package function import ( "fmt" - "slices" "github.com/brimdata/super" samfunc "github.com/brimdata/super/runtime/sam/expr/function" @@ -83,6 +82,9 @@ func (u *Upcast) upcast(vec vector.Any, to super.Type) vector.Any { if vec.Type() == to && vec.Kind() != vector.KindFusion { return vec } + if vec.Len() == 0 { + return vector.NewEmpty(to) + } switch vec := vec.(type) { case *vector.Fusion: return u.upcast(vec.Values, to) @@ -181,16 +183,15 @@ func (u *Upcast) deunionAndUpcast(vec vector.Any, to super.Type) vector.Any { if !ok { return u.upcast(vec, to) } - vecs := slices.Clone(d.Values) - for i, vec := range vecs { - if vec == nil || vec.Len() == 0 { - continue - } - vecs[i] = u.upcast(vecs[i], to) + vecs := make([]vector.Any, len(d.Values)) + for i, vec := range d.Values { + vecs[i] = u.upcast(vec, to) if vecs[i] == nil { return nil } } + // All elements of vecs have type to so this should always return a + // vector with type to (and never a dynamic). return vbuild.MergeSameTypesInDynamic(vector.NewDynamic(d.Tags, vecs)) } diff --git a/runtime/ztests/expr/function/defuse.yaml b/runtime/ztests/expr/function/defuse.yaml index 7d613d77d..c8d5b1c88 100644 --- a/runtime/ztests/expr/function/defuse.yaml +++ b/runtime/ztests/expr/function/defuse.yaml @@ -239,9 +239,6 @@ output: *input --- -# Panics in vam. -runtime: sam - spq: fuse | defuse(this) input: &input | diff --git a/vector/vbuild/merge.go b/vector/vbuild/merge.go index 4c91d4f08..1f9e637da 100644 --- a/vector/vbuild/merge.go +++ b/vector/vbuild/merge.go @@ -73,6 +73,9 @@ func Merge(tags []uint32, vecs []vector.Any) vector.Any { reverse := make([][]uint32, len(vecs)) var k uint32 for i, vec := range vecs { + if vec.Len() == 0 { + continue + } b.Write(vec) for range vec.Len() { reverse[i] = append(reverse[i], k)