@@ -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\t here" , "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.
431431func 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