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

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new ddf066214 fix(go): return nil serializer on getTypeInfo err (#3719)
ddf066214 is described below

commit ddf06621410674532440a87b278e726ad3bdc492
Author: Ayush Kumar <[email protected]>
AuthorDate: Sat May 30 17:50:46 2026 +0530

    fix(go): return nil serializer on getTypeInfo err (#3719)
    
    ## Why?
    
    
    
    ## What does this PR do?
    
    
    
    ## Related issues
    Closes #3718
    
    ## AI Contribution Checklist
    Issue was flagged by claude
    ```
    Confirmed bug
    
    1. type_resolver.go:1018 — serializer-creation error is silently swallowed
    
    Confidence: high (confirmed by go vet and by reading the code). Severity: 
medium–high.
    
    serializer, err := r.createSerializer(value.Type(), false)
    if err != nil {
        fmt.Errorf("failed to create serializer: %w", err)   // <-- result 
discarded
    }
    info.Serializer = serializer        // serializer is nil here on error
    // ...
    r.typePointerCache[typePtr] = info  // nil serializer gets cached
    return info, nil                    // returns nil error despite failure
    
    The error is built with fmt.Errorf but never returned or assigned. On the 
lazy-init path, when createSerializer fails, serializer is nil, that nil is 
stored into info.Serializer, cached, and the function returns (info, nil) — 
pretending success. A later serialize/deserialize then uses a nil serializer → 
wrong behavior or a nil-deref panic, far from the real cause.
    
    Fix: return nil, fmt.Errorf("failed to create serializer: %w", err)
    
    go vet flags this directly:
    type_resolver.go:1018:5: result of fmt.Errorf call not used
    ```
    
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 go/fory/type_resolver.go      |  2 +-
 go/fory/type_resolver_test.go | 64 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/go/fory/type_resolver.go b/go/fory/type_resolver.go
index 82bf185f8..cc9d01765 100644
--- a/go/fory/type_resolver.go
+++ b/go/fory/type_resolver.go
@@ -1015,7 +1015,7 @@ func (r *TypeResolver) getTypeInfo(value reflect.Value, 
create bool) (*TypeInfo,
                        */
                        serializer, err := r.createSerializer(value.Type(), 
false)
                        if err != nil {
-                               fmt.Errorf("failed to create serializer: %w", 
err)
+                               return nil, fmt.Errorf("failed to create 
serializer: %w", err)
                        }
                        info.Serializer = serializer
                }
diff --git a/go/fory/type_resolver_test.go b/go/fory/type_resolver_test.go
new file mode 100644
index 000000000..e911b21e2
--- /dev/null
+++ b/go/fory/type_resolver_test.go
@@ -0,0 +1,64 @@
+// 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 fory
+
+import (
+       "reflect"
+       "testing"
+
+       "github.com/stretchr/testify/require"
+)
+
+// Regression test for the lazy-serializer-init path in getTypeInfo.
+//
+// Before the fix, a createSerializer failure on this path silently discarded
+// the error (fmt.Errorf result unused), stored a nil Serializer in the cache,
+// and returned (info, nil) — hiding the failure from callers.
+//
+// After the fix the error is propagated and no nil serializer is cached.
+func TestGetTypeInfo_LazyInitPropagatesError(t *testing.T) {
+       f := New()
+       resolver := f.typeResolver
+
+       // **int is explicitly rejected by createSerializer ("pointer to 
pointer is not
+       // supported"), so it is a reliable trigger for the error path.
+       ptrPtrInt := reflect.TypeOf((**int)(nil)) // **int
+
+       // Seed typesInfo with an entry whose Serializer is nil, mimicking a 
type
+       // that was registered but whose serializer has not been created yet.
+       resolver.typesInfo[ptrPtrInt] = &TypeInfo{
+               Type:       ptrPtrInt,
+               Serializer: nil, // nil triggers the lazy-init branch
+       }
+
+       value := reflect.New(ptrPtrInt).Elem() // zero Value of type **int
+       info, err := resolver.getTypeInfo(value, true)
+
+       // The bug: before the fix, err was nil and info had a nil Serializer.
+       // The fix: err must be non-nil; info should be nil.
+       require.Error(t, err, "expected error when createSerializer fails on 
lazy init, got nil")
+       require.Nil(t, info, "expected nil TypeInfo when createSerializer 
fails, got non-nil")
+
+       // Also verify the cache was NOT poisoned with a nil-serializer entry.
+       typePtr := typePointer(ptrPtrInt)
+       cached, ok := resolver.typePointerCache[typePtr]
+       if ok {
+               require.NotNil(t, cached.Serializer,
+                       "typePointerCache must not hold an entry with a nil 
Serializer")
+       }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to