Skip to content

Commit dde81f1

Browse files
committed
address review feedback
1 parent f1e252c commit dde81f1

3 files changed

Lines changed: 37 additions & 22 deletions

File tree

rpc/json.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,6 @@ func parseMessage(raw json.RawMessage) ([]*jsonrpcMessage, bool) {
429429
func fillMessage(input []byte, msg *jsonrpcMessage) {
430430
// The raw fields point into input rather than being copied out of it, which
431431
// matters because params is nearly all of a large request.
432-
redo := false
433432
forEachJSONField(input, func(key, value []byte) {
434433
switch string(key) {
435434
case "jsonrpc":
@@ -446,16 +445,9 @@ func fillMessage(input []byte, msg *jsonrpcMessage) {
446445
case "result":
447446
msg.Result = value
448447
default:
449-
// encoding/json matched field names case insensitively and
450-
// unescaped them, so an unknown key may still name a field.
451-
// Redo the message with it to keep that behavior.
452-
redo = true
448+
// ignore unknown fields
453449
}
454450
})
455-
if redo {
456-
*msg = jsonrpcMessage{}
457-
json.Unmarshal(input, msg)
458-
}
459451
}
460452

461453
// isBatch returns true when the first non-whitespace characters is '['

rpc/jsonscan.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ func forEachJSONField(data []byte, fn func(key, value []byte)) {
132132
if keyEnd-1 <= keyStart {
133133
return
134134
}
135-
// The key keeps any escapes it had, the caller deals with them.
136135
fn(data[keyStart+1:keyEnd-1], data[valStart:valEnd])
137136
}
138137
}

rpc/jsonscan_test.go

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ var messageCorpus = []string{
5555
// duplicate keys, last one wins
5656
`{"method":"first","method":"second","id":1}`,
5757
`{"id":1,"id":2}`,
58-
// keys in other spellings, matched the way encoding/json matched them
58+
// keys in other spellings are unknown fields, only the exact names match
5959
`{"METHOD":"m","ID":1}`,
6060
`{"Method":"m","Id":1,"Jsonrpc":"2.0"}`,
6161
"{\"metho\\u0064\":\"m\",\"i\\u0064\":7}",
@@ -126,12 +126,11 @@ func TestParseMessage(t *testing.T) {
126126
{"escaped tab in method", `{"method":"tab\there","id":1}`, false, []*jsonrpcMessage{msg("", "tab\there", "1", "", "")}},
127127
{"duplicate key, last wins", `{"method":"first","method":"second","id":1}`, false, []*jsonrpcMessage{msg("", "second", "1", "", "")}},
128128

129-
// encoding/json matched keys case insensitively and unescaped them
130-
// first, and clients may depend on that
131-
{"cased keys", `{"Method":"m","ID":1,"Params":[1]}`, false, []*jsonrpcMessage{msg("", "m", "1", "[1]", "")}},
132-
{"upper case keys", `{"METHOD":"m","JSONRPC":"2.0"}`, false, []*jsonrpcMessage{msg("2.0", "m", "", "", "")}},
133-
{"escaped keys", "{\"metho\\u0064\":\"m\",\"i\\u0064\":7}", false, []*jsonrpcMessage{msg("", "m", "7", "", "")}},
134-
{"key escapes apply once", `{"metho\\u0064":"m"}`, false, []*jsonrpcMessage{zero()}},
129+
// field names have one spelling in the spec, any other spelling is an
130+
// unknown key, even where encoding/json would have matched it
131+
{"cased keys ignored", `{"Method":"m","ID":1,"Params":[1]}`, false, []*jsonrpcMessage{zero()}},
132+
{"upper case keys ignored", `{"METHOD":"m","JSONRPC":"2.0"}`, false, []*jsonrpcMessage{zero()}},
133+
{"escaped keys ignored", "{\"metho\\u0064\":\"m\",\"i\\u0064\":7}", false, []*jsonrpcMessage{zero()}},
135134

136135
// a string holding structural bytes must not end the value early
137136
{
@@ -426,8 +425,9 @@ func FuzzJSONScanFields(f *testing.F) {
426425
})
427426
}
428427

429-
// FuzzFillMessage checks that the envelope split fills the same fields
430-
// encoding/json fills, for any valid JSON value.
428+
// FuzzFillMessage checks the envelope split against encoding/json field by
429+
// field. Field names have one spelling, so the reference picks each one out of
430+
// a decoded map by its exact name.
431431
func FuzzFillMessage(f *testing.F) {
432432
for _, s := range messageCorpus {
433433
f.Add(s)
@@ -437,10 +437,34 @@ func FuzzFillMessage(f *testing.F) {
437437
if !json.Valid(data) {
438438
return
439439
}
440-
// The old decoder ignored the decode error and kept whatever fields
441-
// had been filled in, so the comparison does too.
440+
if bytes.IndexByte(data, '\\') >= 0 {
441+
// encoding/json unescapes map keys, so an escaped key would match
442+
// in the reference but is an unknown key to fillMessage. Escape
443+
// handling is pinned by the tests above.
444+
return
445+
}
442446
var want jsonrpcMessage
443-
json.Unmarshal(data, &want)
447+
var obj map[string]json.RawMessage
448+
if err := json.Unmarshal(data, &obj); err == nil {
449+
if v, ok := obj["jsonrpc"]; ok {
450+
json.Unmarshal(v, &want.Version)
451+
}
452+
if v, ok := obj["id"]; ok {
453+
want.ID = v
454+
}
455+
if v, ok := obj["method"]; ok {
456+
json.Unmarshal(v, &want.Method)
457+
}
458+
if v, ok := obj["params"]; ok {
459+
want.Params = v
460+
}
461+
if v, ok := obj["error"]; ok {
462+
want.Error = v
463+
}
464+
if v, ok := obj["result"]; ok {
465+
want.Result = v
466+
}
467+
}
444468
got := new(jsonrpcMessage)
445469
fillMessage(data, got)
446470
if err := sameMessage(got, &want); err != nil {

0 commit comments

Comments
 (0)