1
0
mirror of https://github.com/golang/go synced 2024-11-25 08:27:57 -07:00

encoding/json: don't silently ignore error from (*Decoder).More

This commit is contained in:
Mateusz Poliwczak 2024-05-20 13:28:02 +02:00
parent 2f6426834c
commit 75417bfd11
2 changed files with 94 additions and 9 deletions

View File

@ -19,6 +19,7 @@ type Decoder struct {
scanned int64 // amount of data already scanned scanned int64 // amount of data already scanned
scan scanner scan scanner
err error err error
errFromMore bool
tokenState int tokenState int
tokenStack []int tokenStack []int
@ -48,7 +49,12 @@ func (dec *Decoder) DisallowUnknownFields() { dec.d.disallowUnknownFields = true
// the conversion of JSON into a Go value. // the conversion of JSON into a Go value.
func (dec *Decoder) Decode(v any) error { func (dec *Decoder) Decode(v any) error {
if dec.err != nil { if dec.err != nil {
return dec.err err := dec.err
if dec.errFromMore {
dec.err = nil
dec.errFromMore = false
}
return err
} }
if err := dec.tokenPrepareForDecode(); err != nil { if err := dec.tokenPrepareForDecode(); err != nil {
@ -365,6 +371,13 @@ func (d Delim) String() string {
// to mark the start and end of arrays and objects. // to mark the start and end of arrays and objects.
// Commas and colons are elided. // Commas and colons are elided.
func (dec *Decoder) Token() (Token, error) { func (dec *Decoder) Token() (Token, error) {
if dec.err != nil && dec.errFromMore {
err := dec.err
dec.err = nil
dec.errFromMore = false
return nil, err
}
for { for {
c, err := dec.peek() c, err := dec.peek()
if err != nil { if err != nil {
@ -481,7 +494,17 @@ func (dec *Decoder) tokenError(c byte) (Token, error) {
// current array or object being parsed. // current array or object being parsed.
func (dec *Decoder) More() bool { func (dec *Decoder) More() bool {
c, err := dec.peek() c, err := dec.peek()
return err == nil && c != ']' && c != '}' if err != nil {
if err == io.EOF {
dec.err = nil
dec.errFromMore = false
return false
}
dec.err = err
dec.errFromMore = true
return true
}
return c != ']' && c != '}'
} }
func (dec *Decoder) peek() (byte, error) { func (dec *Decoder) peek() (byte, error) {

View File

@ -6,6 +6,7 @@ package json
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -520,3 +521,64 @@ func TestHTTPDecoding(t *testing.T) {
t.Errorf("Decode error:\n\tgot: %v\n\twant: io.EOF", err) t.Errorf("Decode error:\n\tgot: %v\n\twant: io.EOF", err)
} }
} }
type failingDecoderTestReader struct {
t *testing.T
i int
err error
}
func (c *failingDecoderTestReader) Read(b []byte) (n int, err error) {
i := c.i
c.i++
defer func() {
c.t.Logf("%v, %v, %v, %v\n", i, len(b), n, err)
// Decoder always passes a buffer with size that has at least 512 Bytes. This test
// depends on that behaviour, so that the reader does not get unnecessarily complicated.
if len(b) == n {
c.t.Fatal("small buffer passed to Read")
}
}()
switch i {
case 0:
return copy(b, `[{ "test": 1 }`), nil
case 1:
return 0, c.err
default:
return 0, io.EOF
}
}
func TestDecoderMore(t *testing.T) {
type Message struct{ Test int }
notIgnoredError := errors.New("not ignored error")
dec := NewDecoder(&failingDecoderTestReader{t: t, err: notIgnoredError})
if val, err := dec.Token(); err != nil || val != Delim('[') {
t.Fatalf("(*Decoder).Token() = (%v, %v); want = ([, <nil>)", val, err)
}
if err := dec.Decode(new(Message)); err != nil {
t.Fatalf("(*Decoder).Decode() = %v; want = <nil>", err)
}
if !dec.More() {
t.Fatalf("(*Decoder).More() = false; want = true")
}
if err := dec.Decode(new(Message)); err != notIgnoredError {
t.Fatalf("(*Decoder).Decode() = %v; want = %v", err, notIgnoredError)
}
if dec.More() {
t.Fatalf("(*Decoder).More() = true; want = false")
}
if err := dec.Decode(new(Message)); err != io.EOF {
t.Fatalf("(*Decoder).Decode() = %v; want = %v", err, io.EOF)
}
}