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 2bc506ad fix(parquet/variant): handle empty metadata keys (#985)
2bc506ad is described below

commit 2bc506ad7db7138e012001f4897629de543d8879
Author: Minh Vu <[email protected]>
AuthorDate: Thu Jul 23 20:12:21 2026 +0200

    fix(parquet/variant): handle empty metadata keys (#985)
    
    ### Rationale for this change
    
    Variant metadata may contain an empty object key. `Metadata.KeyAt`
    validates the dictionary index, then previously took the address of the
    key's first byte. That panics when the key is empty.
    
    ### What changes are included in this PR?
    
    Use `unsafe.SliceData` for the existing zero-copy byte-to-string
    conversion so zero-length keys are handled safely. Add a builder-based
    regression covering both `KeyAt` and `IdFor`.
    
    ### Are these changes tested?
    
    Yes:
    
    - `go test ./parquet/variant`
    - `go test -race -count=1 ./parquet/variant`
    
    ### Are there any user-facing changes?
    
    `Metadata.KeyAt` now returns an empty string for a valid empty key
    instead of panicking. There is no API change.
---
 parquet/variant/variant.go      |  3 ++-
 parquet/variant/variant_test.go | 16 ++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/parquet/variant/variant.go b/parquet/variant/variant.go
index 0e8a904b..25eacd43 100644
--- a/parquet/variant/variant.go
+++ b/parquet/variant/variant.go
@@ -258,7 +258,8 @@ func (m Metadata) KeyAt(id uint32) (string, error) {
                        id, len(m.keys))
        }
 
-       return unsafe.String(&m.keys[id][0], len(m.keys[id])), nil
+       key := m.keys[id]
+       return unsafe.String(unsafe.SliceData(key), len(key)), nil
 }
 
 // IdFor returns the dictionary IDs for the given key.
diff --git a/parquet/variant/variant_test.go b/parquet/variant/variant_test.go
index b2f55339..649a719c 100644
--- a/parquet/variant/variant_test.go
+++ b/parquet/variant/variant_test.go
@@ -122,6 +122,22 @@ func TestBasicRead(t *testing.T) {
        })
 }
 
+func TestMetadataEmptyKey(t *testing.T) {
+       var b variant.Builder
+       start := b.Offset()
+       fields := []variant.FieldEntry{b.NextField(start, "")}
+       require.NoError(t, b.AppendNull())
+       require.NoError(t, b.FinishObject(start, fields))
+       value, err := b.Build()
+       require.NoError(t, err)
+       metadata := value.Metadata()
+
+       key, err := metadata.KeyAt(0)
+       require.NoError(t, err)
+       assert.Empty(t, key)
+       assert.Equal(t, []uint32{0}, metadata.IdFor(""))
+}
+
 func loadVariant(t *testing.T, test string) variant.Value {
        dir := getVariantDir()
        if dir == "" {

Reply via email to