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 <[email protected]>
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())
+}

Reply via email to