cnYui opened a new pull request, #1032:
URL: https://github.com/apache/dubbo-go-pixiu/pull/1032

   **What this PR does**:
   
   `descriptor_source_strategy` defaults to `AUTO` (`grpc.go` — 
`default:"auto"`), which `getDescriptorSource` documents as `// file + 
reflection`. But `initDescriptorSource` only loaded the local proto files for 
`LOCAL`:
   
   ```go
   func (dr *Descriptor) initDescriptorSource(cfg *Config) *Descriptor {
        if cfg.DescriptorSourceStrategy.String() == LOCAL {
                dr.initFileDescriptorSource(cfg)
        }
        return dr
   }
   ```
   
   and it is the only wiring call (`grpc.go`, in `FilterFactory.Apply`). So 
under the default strategy `dr.fileSource` stays `nil`, and 
`getDescriptorCompose` assigns it straight into an interface field:
   
   ```go
   cs.file = dr.getFileSource()   // nil *fileSource -> non-nil DescriptorSource
   ```
   
   `cs.file == nil` is therefore **false**, and the fallback in 
`compositeSource.FindSymbol` dereferences the nil receiver:
   
   ```go
   return cs.file.FindSymbol(fullyQualifiedName)   // descriptor_source.go:163
   ```
   
   Two consequences on the out-of-the-box configuration:
   
   1. Any request whose server-reflection lookup fails — a backend that does 
not implement the reflection API, or an unknown service name — hits a 
nil-pointer dereference inside the filter chain. `pkg/common/http/manager.go` 
recovers it, so this is not a process crash, but the caller gets a 500 with a 
stack trace in the log instead of the intended 405/400.
   2. The `file` half of `AUTO` never runs at all, so local `.proto` files are 
silently ignored under the default strategy.
   
   `getFileDescriptorCompose` returns the same typed-nil, so `LOCAL` with a 
`path` that cannot be read fails the same way.
   
   The change, confined to `descriptor.go` and `descriptor_source.go`:
   
   - `initDescriptorSource` loads the local proto files for `AUTO` as well as 
`LOCAL`, once at `Apply()` time. It now uses `strings.ToLower(...)` to match 
the comparison `getDescriptorSource` already does.
   - `getDescriptorCompose` only assigns `cs.file` when the file source is 
non-nil, so a typed-nil is never boxed into the interface.
   - `getFileDescriptorCompose` returns an error instead of a nil source when 
the local proto files could not be loaded.
   - `compositeSource.FindSymbol` and `AllExtensionsForType` guard `cs.file`, 
so a missing file source surfaces an error rather than a panic.
   - `AllExtensionsForType` is restructured flat. Its `cs.reflection == nil` 
branch used to compute `cs.file.AllExtensionsForType(...)` and then fall 
through to `return nil, nil`, discarding the successful result; it now returns 
it. (Collapsing that branch in place would leave the trailing `return nil, nil` 
unreachable and fail `go vet`, hence the flat rewrite.)
   
   **Which issue(s) this PR fixes**:
   
   Fixes #
   
   **Special notes for your reviewer**:
   
   `pkg/filter/http/grpcproxy` had no test file for `descriptor.go`, so this 
adds `descriptor_test.go` with four cases that drive the real production path 
(`initDescriptorSource` → `getDescriptorSource` → `getMethodDescriptor`) 
against a gRPC server with no reflection service registered.
   
   All four fail on `develop` (`fd9a27e`) and pass with this change. Before, on 
unmodified sources:
   
   ```
   --- FAIL: TestDescriptorAutoStrategyFallsBackToLocalProtoFiles
           Error: Expected value not to be nil.          # AUTO never loaded 
the protos
   --- FAIL: TestDescriptorLocalStrategyReportsUnloadableProtoFiles
           Error: An error is expected but got nil.
   --- FAIL: TestCompositeSourceFindSymbolWithoutFileSource
   panic: runtime error: invalid memory address or nil pointer dereference
   --- FAIL: TestCompositeSourceAllExtensionsForTypeWithoutReflection
           Error: "[]" should have 1 item(s), but has 0
   ```
   
   With the `require.NotNil` guard temporarily removed so the first test 
reaches the fallback, unmodified sources panic exactly on the live request path:
   
   ```
   panic: runtime error: invalid memory address or nil pointer dereference
   grpcproxy.(*fileSource).FindSymbol
        pkg/filter/http/grpcproxy/descriptor_source.go:123
   grpcproxy.(*compositeSource).FindSymbol
        pkg/filter/http/grpcproxy/descriptor_source.go:163
   grpcproxy.(*Descriptor).getMethodDescriptor
        pkg/filter/http/grpcproxy/descriptor.go:216
   ```
   
   After the change (Go 1.25.7):
   
   ```
   $ go build ./pkg/filter/http/grpcproxy/     # rc=0
   $ go vet ./pkg/filter/http/grpcproxy/       # rc=0, silent
   $ golangci-lint run ./pkg/filter/http/grpcproxy/...
   0 issues.
   $ gofmt -s -l <the three changed files>     # no output
   $ imports-formatter                          # leaves the three files 
unchanged
   $ go test ./pkg/filter/http/grpcproxy/ -v
   --- PASS: TestGRPCConnectionManagerSharesConcurrentConnection (0.01s)
   ... 14 pre-existing tests, all PASS ...
   --- PASS: TestDescriptorAutoStrategyFallsBackToLocalProtoFiles (0.02s)
   --- PASS: TestDescriptorLocalStrategyReportsUnloadableProtoFiles (0.00s)
   --- PASS: TestCompositeSourceFindSymbolWithoutFileSource (0.00s)
   --- PASS: TestCompositeSourceAllExtensionsForTypeWithoutReflection (0.00s)
   PASS
   ok   github.com/apache/dubbo-go-pixiu/pkg/filter/http/grpcproxy      0.730s
   ```
   
   Notes:
   
   - Loading the file source for `AUTO` runs once in `Apply()`, not per 
request, so a misconfigured `path` logs one error at startup rather than on 
every request. With `path` unset the loader reads the executable's directory, 
finds no `.proto` files and yields a valid empty source (INFO only, no error), 
so reflection-only `AUTO` deployments are unaffected.
   - `AllExtensionsForType`'s discarded-result bug is currently latent: 
`cs.reflection` is nil only when `getDescriptorCompose` also returns a non-nil 
error, which `Decode` turns into `filter.Stop`. It is fixed here because it is 
the same function, not because it is separately reachable.
   - Scope is kept to `descriptor.go` and `descriptor_source.go` to avoid 
conflicting with #1023, which is editing `grpc.go` and `connection_manager.go` 
in this package.
   - I verified the touched package only. A full `go build ./...` was not 
possible on my machine: I am on Windows, where `admin/core` cannot build 
because `utils.GetWriteSyncer` lives in the Unix-only 
`admin/utils/rotatelogs_unix.go`, and the build then ran the disk out of space. 
Neither is related to this change, and `pkg/filter/http/grpcproxy` builds, vets 
and tests clean.
   
   **Does this PR introduce a user-facing change?**:
   
   ```release-note
   Fix a nil-pointer dereference in the gRPC proxy filter under the default 
`AUTO` descriptor source strategy, which returned a 500 whenever a 
server-reflection lookup failed, and make `AUTO` actually load the local .proto 
files it documents as its fallback.
   ```
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to