#37350 [BC-Insight] `null` Is Not Unmarshalled Correctly Into json.RawMessage
Previous#37104 [BC-Insight] Reth RPC is vulnerable to DNS rebinding attacksNext#37210 [BC-Insight] Missing Check of HTTP Batch Response Length
Was this helpful?
Was this helpful?
Was this helpful?
// CallContext performs a JSON-RPC call with the given arguments. If the context is
// canceled before the call has successfully returned, CallContext returns immediately.
//
// The result must be a pointer so that package json can unmarshal into it. You
// can also pass nil, in which case the result is ignored.
func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
if result != nil && reflect.TypeOf(result).Kind() != reflect.Ptr {
return fmt.Errorf("call result parameter must be pointer or nil interface: %v", result)
}
msg, err := c.newMessage(method, args...)
if err != nil {
return err
}
op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
if c.isHTTP {
err = c.sendHTTP(ctx, op, msg)
} else {
err = c.send(ctx, op, msg)
}
if err != nil {
return err
}
// dispatch has accepted the request and will close the channel when it quits.
switch resp, err := op.wait(ctx, c); {
case err != nil:
return err
case resp.Error != nil:
return resp.Error
case len(resp.Result) == 0:
return ErrNoResult
default:
return json.Unmarshal(resp.Result, &result)
}
}func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {
...
default:
return json.Unmarshal(resp.Result, &result)
if result == nil {
return nil
}
return json.Unmarshal(resp.Result, result)
}package rpc
import (
"context"
"encoding/json"
"errors"
"fmt"
"math/rand"
"net"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"sync"
"testing"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/ledgerwatch/erigon-lib/common/dbg"
"github.com/ledgerwatch/log/v3"
)
type nullTestService struct{}
func TestNullResponse(t *testing.T) {
logger := log.New()
server := newTestServer(logger)
defer server.Stop()
err := server.RegisterName("test", new(nullTestService))
if err != nil {
t.Fatal(err)
}
client := DialInProc(server, logger)
defer client.Close()
result := &jsonrpcMessage{}
err = client.Call(&result.Result, "test_returnNull")
if err != nil {
t.Fatal(err)
}
if result.Result == nil {
t.Fatal("Expected non-nil result")
}
if !reflect.DeepEqual(result.Result, json.RawMessage("null")) {
t.Errorf("Expected null, got %s", result.Result)
}
}=== RUN TestNullResponse
[WARN] [12-02|12:17:37.643] Cannot register RPC callback [invalidRets1] - error must the last return value
[WARN] [12-02|12:17:37.643] Cannot register RPC callback [invalidRets2] - error must the last return value
[WARN] [12-02|12:17:37.643] Cannot register RPC callback [invalidRets3] - maximum 2 return values are allowed, got 3
client_test.go:140: Expected non-nil result
--- FAIL: TestNullResponse (0.00s)
FAIL