You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by vi...@apache.org on 2026/04/29 11:29:27 UTC
(dubbo-go) 01/01: fix(jsonrpc): prevent nil pointer panic on unregistered service path (#3310)
This is an automated email from the ASF dual-hosted git repository.
cvictory pushed a commit to branch task/fix-jsonrpc-nil-panic-3310-20260429-192213
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git
commit 6499e1bb509ed3d02acc912d1da5986cd24dcb47
Author: victory <sh...@alibaba-inc.com>
AuthorDate: Wed Apr 29 19:28:53 2026 +0800
fix(jsonrpc): prevent nil pointer panic on unregistered service path (#3310)
Check the ok return value from ExporterMap().Load(path) in serveRequest().
When the path is not registered, return a descriptive "service not found"
error instead of panicking on a nil type assertion.
Closes #3310
---
protocol/jsonrpc/server.go | 5 ++++-
protocol/jsonrpc/server_test.go | 48 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/protocol/jsonrpc/server.go b/protocol/jsonrpc/server.go
index a863e13b3..5157d523e 100644
--- a/protocol/jsonrpc/server.go
+++ b/protocol/jsonrpc/server.go
@@ -350,7 +350,10 @@ func serveRequest(ctx context.Context, header map[string]string, body []byte, co
logger.Debugf("args: %v", args)
// exporter invoke
- exporter, _ := jsonrpcProtocol.ExporterMap().Load(path)
+ exporter, ok := jsonrpcProtocol.ExporterMap().Load(path)
+ if !ok {
+ return perrors.Errorf("service not found: %s", path)
+ }
invoker := exporter.(*JsonrpcExporter).GetInvoker()
if invoker != nil {
result := invoker.Invoke(ctx, invocation.NewRPCInvocation(methodName, args, map[string]any{
diff --git a/protocol/jsonrpc/server_test.go b/protocol/jsonrpc/server_test.go
index 14163370f..29ff9bafd 100644
--- a/protocol/jsonrpc/server_test.go
+++ b/protocol/jsonrpc/server_test.go
@@ -22,6 +22,7 @@ import (
"io"
"net"
"net/http"
+ "strconv"
"testing"
"time"
)
@@ -51,6 +52,53 @@ func sendHTTPRequest(t *testing.T, conn net.Conn, contentType string) (*http.Res
return resp, err
}
+// TestHandlePkg_UnregisteredPath verifies that a valid JSON-RPC request sent
+// to a path with no registered exporter returns an error response instead of
+// panicking with a nil pointer dereference (issue #3310).
+func TestHandlePkg_UnregisteredPath(t *testing.T) {
+ // Ensure the package-level jsonrpcProtocol is initialized, as it would be
+ // in production when the protocol is loaded via extension.
+ GetProtocol()
+
+ serverConn, clientConn := net.Pipe()
+ defer func() {
+ _ = clientConn.Close()
+ }()
+ defer func() {
+ _ = serverConn.Close()
+ }()
+
+ s := NewServer()
+ go s.handlePkg(serverConn)
+
+ jsonBody := `{"jsonrpc":"2.0","method":"SayHello","params":["hello"],"id":1}`
+
+ err := clientConn.SetReadDeadline(time.Now().Add(3 * time.Second))
+ require.NoError(t, err)
+
+ req := "POST /UnregisteredService HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Content-Type: application/json\r\n" +
+ "Content-Length: " + strconv.Itoa(len(jsonBody)) + "\r\n" +
+ "\r\n" +
+ jsonBody
+ _, err = clientConn.Write([]byte(req))
+ require.NoError(t, err)
+
+ resp, err := http.ReadResponse(bufio.NewReader(clientConn), nil)
+ require.NoError(t, err, "server should respond without panicking")
+ defer func() {
+ _ = resp.Body.Close()
+ }()
+
+ body, err := io.ReadAll(resp.Body)
+ require.NoError(t, err)
+
+ require.Equal(t, 500, resp.StatusCode)
+ require.Contains(t, string(body), "service not found",
+ "response body should indicate the service was not found")
+}
+
func TestHandlePkg_ContentType(t *testing.T) {
tests := []struct {
name string