Skip to content

Commit 4e3d5e0

Browse files
committed
rpc: check batch response length to prevent deadlock
1 parent a705649 commit 4e3d5e0

File tree

3 files changed

+8
-6
lines changed

3 files changed

+8
-6
lines changed

rpc/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
)
3333

3434
var (
35+
ErrBadResult = errors.New("bad result in JSON-RPC response")
3536
ErrClientQuit = errors.New("client is closed")
3637
ErrNoResult = errors.New("no result in JSON-RPC response")
3738
ErrSubscriptionQueueOverflow = errors.New("subscription queue overflow")

rpc/client_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func TestClientBatchRequest_len(t *testing.T) {
160160
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
161161
_, err := rw.Write(b)
162162
if err != nil {
163-
t.Error("failed to write reponse:", err)
163+
t.Error("failed to write response:", err)
164164
}
165165
}))
166166
t.Cleanup(s.Close)
@@ -170,7 +170,7 @@ func TestClientBatchRequest_len(t *testing.T) {
170170
t.Fatal("failed to dial test server:", err)
171171
}
172172
defer client.Close()
173-
173+
174174
t.Run("too-few", func(t *testing.T) {
175175
batch := []BatchElem{
176176
{Method: "foo"},
@@ -179,8 +179,7 @@ func TestClientBatchRequest_len(t *testing.T) {
179179
}
180180
ctx, cancelFn := context.WithTimeout(context.Background(), time.Second)
181181
defer cancelFn()
182-
err := client.BatchCallContext(ctx, batch)
183-
if !errors.Is(err, ErrBadResult) {
182+
if err := client.BatchCallContext(ctx, batch); !errors.Is(err, ErrBadResult) {
184183
t.Errorf("expected %q but got: %v", ErrBadResult, err)
185184
}
186185
})
@@ -191,8 +190,7 @@ func TestClientBatchRequest_len(t *testing.T) {
191190
}
192191
ctx, cancelFn := context.WithTimeout(context.Background(), time.Second)
193192
defer cancelFn()
194-
err := client.BatchCallContext(ctx, batch)
195-
if !errors.Is(err, ErrBadResult) {
193+
if err := client.BatchCallContext(ctx, batch); !errors.Is(err, ErrBadResult) {
196194
t.Errorf("expected %q but got: %v", ErrBadResult, err)
197195
}
198196
})

rpc/http.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonr
192192
if err := json.NewDecoder(respBody).Decode(&respmsgs); err != nil {
193193
return err
194194
}
195+
if len(respmsgs) != len(msgs) {
196+
return fmt.Errorf("batch has %d requests but response has %d: %w", len(msgs), len(respmsgs), ErrBadResult)
197+
}
195198
for i := 0; i < len(respmsgs); i++ {
196199
op.resp <- &respmsgs[i]
197200
}

0 commit comments

Comments
 (0)