diff options
5 files changed, 24 insertions, 2 deletions
diff --git a/compat/json/testdata/fuzz/FuzzUnmarshalJSON/12cc404310c36cfd14cc33eac5eb4303f0d9d31e9c29a6892bb474a64e78fe5f b/compat/json/testdata/fuzz/FuzzUnmarshalJSON/12cc404310c36cfd14cc33eac5eb4303f0d9d31e9c29a6892bb474a64e78fe5f new file mode 100644 index 0000000..8200529 --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzUnmarshalJSON/12cc404310c36cfd14cc33eac5eb4303f0d9d31e9c29a6892bb474a64e78fe5f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") diff --git a/compat/json/testdata/fuzz/FuzzUnmarshalJSON/df26c4ef7bfba3827830052ec4ae29b24d5dd803ffcfeff314198aef23e76257 b/compat/json/testdata/fuzz/FuzzUnmarshalJSON/df26c4ef7bfba3827830052ec4ae29b24d5dd803ffcfeff314198aef23e76257 new file mode 100644 index 0000000..200e1a6 --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzUnmarshalJSON/df26c4ef7bfba3827830052ec4ae29b24d5dd803ffcfeff314198aef23e76257 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("[[0,]") @@ -252,6 +252,7 @@ var ( jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem() textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() boolType = reflect.TypeOf(true) + float64Type = reflect.TypeOf(float64(0)) ) var kind2bits = map[reflect.Kind]int{ @@ -687,7 +688,7 @@ func (dec *Decoder) decodeAny() any { } f64, err := num.Float64() if err != nil { - panic("should not happen") + dec.panicType("number "+buf.String(), float64Type, err) } return f64 case 't', 'f': diff --git a/decode_scan_test.go b/decode_scan_test.go index 5ad454f..1f04ead 100644 --- a/decode_scan_test.go +++ b/decode_scan_test.go @@ -105,6 +105,13 @@ func TestRuneTypeScanner(t *testing.T) { {0, 0, RuneTypeEOF, nil}, {0, 0, RuneTypeEOF, nil}, }}, + "syntax-error": {`[[0,]`, []ReadRuneTypeResult{ + {'[', 1, RuneTypeArrayBeg, nil}, + {'[', 1, RuneTypeArrayBeg, nil}, + {'0', 1, RuneTypeNumberIntZero, nil}, + {',', 1, RuneTypeArrayComma, nil}, + {']', 1, RuneTypeError, &DecodeSyntaxError{Offset: 5, Err: fmt.Errorf("invalid character %q looking for beginning of value", ']')}}, + }}, } for tcName, tc := range testcases { t.Run(tcName, func(t *testing.T) { @@ -238,6 +238,7 @@ type Parser struct { // // [ array: waiting for item to start or ']' // a array: reading item / waiting for ',' or ']' + // ] array: waiting for item to start // // Within each element type, the stack item is replaced, not pushed. // @@ -454,12 +455,21 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) { par.pushState(RuneTypeError) return par.HandleRune(c) } + case RuneTypeArrayEnd: // waiting for item + switch c { + case 0x0020, 0x000A, 0x000D, 0x0009: + return RuneTypeSpace, nil + default: + par.replaceState(RuneTypeArrayComma) + par.pushState(RuneTypeError) + return par.HandleRune(c) + } case RuneTypeArrayComma: // waiting for ',' or ']' switch c { case 0x0020, 0x000A, 0x000D, 0x0009: return RuneTypeSpace, nil case ',': - par.replaceState(RuneTypeArrayBeg) + par.replaceState(RuneTypeArrayEnd) return RuneTypeArrayComma, nil case ']': par.popState() |