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

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


The following commit(s) were added to refs/heads/main by this push:
     new 5ce9c0a71 fix(view): protect identifiers from mutation (#1543)
5ce9c0a71 is described below

commit 5ce9c0a71c1b84e92a14bb1ce70cc884da494993
Author: Minh Vu <[email protected]>
AuthorDate: Thu Jul 30 00:03:50 2026 +0200

    fix(view): protect identifiers from mutation (#1543)
    
    ## What changed
    
    Copy view identifiers when constructing a View and when returning
    Identifier.
    
    ## Why
    
    View identifiers are slices. New previously retained the caller-owned
    slice, and Identifier returned that same backing array. Either path
    allowed external mutation to change the identity of an existing View and
    affect equality or catalog behavior.
    
    The regression test mutates both the constructor input and the getter
    result.
    
    ## Testing
    
    - go test ./view
    - go vet ./view
    - go test ./...
---
 view/view.go      |  4 ++--
 view/view_test.go | 12 ++++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/view/view.go b/view/view.go
index 9f38d6581..a12be3938 100644
--- a/view/view.go
+++ b/view/view.go
@@ -44,7 +44,7 @@ func (t View) Equals(other View) bool {
                t.metadata.Equals(other.metadata)
 }
 
-func (t View) Identifier() table.Identifier     { return t.identifier }
+func (t View) Identifier() table.Identifier     { return 
slices.Clone(t.identifier) }
 func (t View) Metadata() Metadata               { return t.metadata }
 func (t View) MetadataLocation() string         { return t.metadataLocation }
 func (t View) CurrentVersion() *Version         { return 
t.metadata.CurrentVersion() }
@@ -56,7 +56,7 @@ func (t View) Schemas() map[int]*iceberg.Schema { return 
t.metadata.SchemasByID(
 
 func New(ident table.Identifier, meta Metadata, metadataLocation string) *View 
{
        return &View{
-               identifier:       ident,
+               identifier:       slices.Clone(ident),
                metadata:         meta,
                metadataLocation: metadataLocation,
        }
diff --git a/view/view_test.go b/view/view_test.go
index eedb3af18..977568757 100644
--- a/view/view_test.go
+++ b/view/view_test.go
@@ -145,3 +145,15 @@ func TestCreateViewReturnsMetadataCloseError(t *testing.T) 
{
        require.EqualError(t, err, "error on close")
        require.Nil(t, createdView)
 }
+
+func (t *ViewTestSuite) TestIdentifierReturnsDefensiveCopy() {
+       identifier := []string{"namespace", "view"}
+       vw := New(identifier, nil, "metadata.json")
+
+       identifier[0] = "changed-input"
+       t.Equal([]string{"namespace", "view"}, vw.Identifier())
+
+       returned := vw.Identifier()
+       returned[1] = "changed-output"
+       t.Equal([]string{"namespace", "view"}, vw.Identifier())
+}

Reply via email to