You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ze...@apache.org on 2026/08/05 17:39:20 UTC

(arrow-go) branch main updated: fix(arrow/flight/session): clone option values (#1044)

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 f7be6f32 fix(arrow/flight/session): clone option values (#1044)
f7be6f32 is described below

commit f7be6f32f846cd8bcb7d5222ad804905163fdf86
Author: Minh Vu <vu...@gmail.com>
AuthorDate: Wed Aug 5 19:39:15 2026 +0200

    fix(arrow/flight/session): clone option values (#1044)
    
    ## What changed
    
    Clone mutable Flight session option protobufs when storing and
    retrieving individual option values.
    
    ## Why
    
    The stateful session implementation previously stored caller-owned
    pointers and returned its internal pointers after releasing the mutex.
    Callers could therefore mutate session state outside synchronization,
    despite the implementation's goroutine-safety contract.
    
    The regression test covers both aliasing directions: modifying the input
    after `SetSessionOption` and modifying the value returned by
    `GetSessionOption`.
    
    ## Validation
    
    `go test ./arrow/flight/session`
    
    `go test -race ./arrow/flight/session`
---
 arrow/flight/session/session.go      |  4 ++--
 arrow/flight/session/session_test.go | 40 ++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/arrow/flight/session/session.go b/arrow/flight/session/session.go
index 202de38b..6c2278ac 100644
--- a/arrow/flight/session/session.go
+++ b/arrow/flight/session/session.go
@@ -108,7 +108,7 @@ func (session *serverSession) GetSessionOption(name string) *flight.SessionOptio
 		return nil
 	}
 
-	return value
+	return proto.Clone(value).(*flight.SessionOptionValue)
 }
 
 func (session *serverSession) GetSessionOptions() map[string]*flight.SessionOptionValue {
@@ -131,7 +131,7 @@ func (session *serverSession) SetSessionOption(name string, value *flight.Sessio
 
 	session.mu.Lock()
 	defer session.mu.Unlock()
-	session.options[name] = value
+	session.options[name] = proto.Clone(value).(*flight.SessionOptionValue)
 }
 
 func (session *serverSession) EraseSessionOption(name string) {
diff --git a/arrow/flight/session/session_test.go b/arrow/flight/session/session_test.go
new file mode 100644
index 00000000..c280eac9
--- /dev/null
+++ b/arrow/flight/session/session_test.go
@@ -0,0 +1,40 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package session
+
+import (
+	"testing"
+
+	"github.com/apache/arrow-go/v18/arrow/flight"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestServerSessionClonesOptionValues(t *testing.T) {
+	session := serverSession{options: make(map[string]*flight.SessionOptionValue)}
+	values, err := flight.NewSessionOptionValues(map[string]any{"key": []string{"original"}})
+	require.NoError(t, err)
+	value := values["key"]
+
+	session.SetSessionOption("key", value)
+	value.GetStringListValue().Values[0] = "modified input"
+	assert.Equal(t, []string{"original"}, session.GetSessionOption("key").GetStringListValue().GetValues())
+
+	got := session.GetSessionOption("key")
+	got.GetStringListValue().Values[0] = "modified output"
+	assert.Equal(t, []string{"original"}, session.GetSessionOption("key").GetStringListValue().GetValues())
+}