This is an automated email from the ASF dual-hosted git repository.
Alanxtl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git
The following commit(s) were added to refs/heads/develop by this push:
new c32066f97 fix(filter/generic): guard $invoke arg type assertions to
avoid panic (#3680)
c32066f97 is described below
commit c32066f97c2ff2ae9470b89f11d30a7e3567c019
Author: Lcos <[email protected]>
AuthorDate: Tue Aug 18 23:01:33 2026 +0800
fix(filter/generic): guard $invoke arg type assertions to avoid panic
(#3680)
* fix(filter/generic): guard $invoke arg type assertions to avoid panic
IsGenericInvocation only guarantees len(Arguments)==3, not the element
types. The two bare type assertions in genericServiceFilter.Invoke
(arg[0].(string) and arg[2].([]hessian.Object)) could panic on a
malformed or malicious $invoke request. Replace them with comma-ok
form and return a perrors-wrapped error via RPCResult{Err}, matching
the existing error-return style in the same function.
Fixes #3679
Signed-off-by: Lcos <[email protected]>
Signed-off-by: user.email <[email protected]>
* Update filter/generic/service_filter.go
Co-authored-by: Xuetao Li <[email protected]>
---------
Signed-off-by: Lcos <[email protected]>
Signed-off-by: user.email <[email protected]>
Co-authored-by: Xuetao Li <[email protected]>
---
filter/generic/service_filter.go | 10 +++++--
filter/generic/service_filter_test.go | 49 +++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/filter/generic/service_filter.go b/filter/generic/service_filter.go
index 64619b56c..480b82264 100644
--- a/filter/generic/service_filter.go
+++ b/filter/generic/service_filter.go
@@ -76,10 +76,16 @@ func (f *genericServiceFilter) Invoke(ctx context.Context,
invoker base.Invoker,
}
// get real invocation info from the generic invocation
- mtdName := inv.Arguments()[0].(string)
+ mtdName, ok := inv.Arguments()[0].(string)
+ if !ok {
+ return &result.RPCResult{Err: perrors.Errorf("$invoke: arg[0]
must be string, got %T", inv.Arguments()[0])}
+ }
// types are not required in dubbo-go, for dubbo-go client to dubbo-go
server, types could be nil
types := inv.Arguments()[1]
- args := inv.Arguments()[2].([]hessian.Object)
+ args, ok := inv.Arguments()[2].([]hessian.Object)
+ if !ok {
+ return &result.RPCResult{Err: perrors.Errorf("$invoke: arg[2]
must be []hessian.Object, got %T", inv.Arguments()[2])}
+ }
logger.Debugf("[Filter][Generic] received a generic invocation,
methodName=%s types=%v args=%v", mtdName, types, args)
diff --git a/filter/generic/service_filter_test.go
b/filter/generic/service_filter_test.go
index 4bee9cfd3..4fd3c68f2 100644
--- a/filter/generic/service_filter_test.go
+++ b/filter/generic/service_filter_test.go
@@ -269,6 +269,55 @@ func TestServiceFilter_InvokeWithUnsupportedGenericMode(t
*testing.T) {
}
}
+// TestServiceFilter_InvokeRejectsMalformedArgs ensures a $invoke with
wrong-typed
+// arguments returns an error instead of panicking. See
service_filter.go:79,82.
+func TestServiceFilter_InvokeRejectsMalformedArgs(t *testing.T) {
+ filter := &genericServiceFilter{}
+
+ cases := []struct {
+ name string
+ args []any
+ want string
+ }{
+ {
+ name: "arg0-not-string",
+ args: []any{123, []string{}, []hessian.Object{}},
+ want: "$invoke: arg[0] must be string, got int",
+ },
+ {
+ name: "arg0-nil",
+ args: []any{nil, []string{}, []hessian.Object{}},
+ want: "$invoke: arg[0] must be string, got <nil>",
+ },
+ {
+ name: "arg2-not-hessian-slice",
+ args: []any{"Hello", []string{}, "not-a-slice"},
+ want: "$invoke: arg[2] must be []hessian.Object, got
string",
+ },
+ {
+ name: "arg2-nil",
+ args: []any{"Hello", []string{}, nil},
+ want: "$invoke: arg[2] must be []hessian.Object, got
<nil>",
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.name, func(t *testing.T) {
+ inv := invocation.NewRPCInvocation(constant.Generic,
tc.args,
+ map[string]any{constant.GenericKey: "true"})
+
+ ctrl := gomock.NewController(t)
+ mockInvoker := mock.NewMockInvoker(ctrl)
+ mockInvoker.EXPECT().Invoke(gomock.Any(),
gomock.Any()).Times(0)
+
+ res := filter.Invoke(context.Background(), mockInvoker,
inv)
+
+ require.EqualError(t, res.Error(), tc.want)
+ assert.Nil(t, res.Result())
+ })
+ }
+}
+
func TestServiceFilter_InvokeWithEmptyGenericModeUsesDefault(t *testing.T) {
filter := &genericServiceFilter{}
service := &MockHelloService{}