Skip to content

Commit

Permalink
rpc: check batch response length to prevent deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
jmank88 committed Oct 31, 2022
1 parent a705649 commit 4e3d5e0
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 6 deletions.
1 change: 1 addition & 0 deletions rpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
)

var (
ErrBadResult = errors.New("bad result in JSON-RPC response")
ErrClientQuit = errors.New("client is closed")
ErrNoResult = errors.New("no result in JSON-RPC response")
ErrSubscriptionQueueOverflow = errors.New("subscription queue overflow")
Expand Down
10 changes: 4 additions & 6 deletions rpc/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func TestClientBatchRequest_len(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
_, err := rw.Write(b)
if err != nil {
t.Error("failed to write reponse:", err)
t.Error("failed to write response:", err)
}
}))
t.Cleanup(s.Close)
Expand All @@ -170,7 +170,7 @@ func TestClientBatchRequest_len(t *testing.T) {
t.Fatal("failed to dial test server:", err)
}
defer client.Close()

t.Run("too-few", func(t *testing.T) {
batch := []BatchElem{
{Method: "foo"},
Expand All @@ -179,8 +179,7 @@ func TestClientBatchRequest_len(t *testing.T) {
}
ctx, cancelFn := context.WithTimeout(context.Background(), time.Second)
defer cancelFn()
err := client.BatchCallContext(ctx, batch)
if !errors.Is(err, ErrBadResult) {
if err := client.BatchCallContext(ctx, batch); !errors.Is(err, ErrBadResult) {
t.Errorf("expected %q but got: %v", ErrBadResult, err)
}
})
Expand All @@ -191,8 +190,7 @@ func TestClientBatchRequest_len(t *testing.T) {
}
ctx, cancelFn := context.WithTimeout(context.Background(), time.Second)
defer cancelFn()
err := client.BatchCallContext(ctx, batch)
if !errors.Is(err, ErrBadResult) {
if err := client.BatchCallContext(ctx, batch); !errors.Is(err, ErrBadResult) {
t.Errorf("expected %q but got: %v", ErrBadResult, err)
}
})
Expand Down
3 changes: 3 additions & 0 deletions rpc/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonr
if err := json.NewDecoder(respBody).Decode(&respmsgs); err != nil {
return err
}
if len(respmsgs) != len(msgs) {
return fmt.Errorf("batch has %d requests but response has %d: %w", len(msgs), len(respmsgs), ErrBadResult)
}
for i := 0; i < len(respmsgs); i++ {
op.resp <- &respmsgs[i]
}
Expand Down

0 comments on commit 4e3d5e0

Please sign in to comment.