diff options
Diffstat (limited to 'src/encoding/json')
| -rw-r--r-- | src/encoding/json/v2_scanner.go | 5 | ||||
| -rw-r--r-- | src/encoding/json/v2_stream_test.go | 24 |
2 files changed, 29 insertions, 0 deletions
diff --git a/src/encoding/json/v2_scanner.go b/src/encoding/json/v2_scanner.go index aef045f466..f08a0bcce3 100644 --- a/src/encoding/json/v2_scanner.go +++ b/src/encoding/json/v2_scanner.go @@ -56,6 +56,11 @@ var errUnexpectedEnd = errors.New("unexpected end of JSON input") func transformSyntacticError(err error) error { switch serr, ok := err.(*jsontext.SyntacticError); { case serr != nil: + // If the SyntacticError wraps an IO error, unwrap it + // to match v1 behavior which returned IO errors directly. + if export.IsIOError(serr.Err) { + return errors.Unwrap(serr.Err) + } if serr.Err == io.ErrUnexpectedEOF { serr.Err = errUnexpectedEnd } diff --git a/src/encoding/json/v2_stream_test.go b/src/encoding/json/v2_stream_test.go index d7f9f11084..b185b46acb 100644 --- a/src/encoding/json/v2_stream_test.go +++ b/src/encoding/json/v2_stream_test.go @@ -8,6 +8,7 @@ package json import ( "bytes" + "errors" "io" "log" "net" @@ -613,3 +614,26 @@ func TestDecoderInputOffset(t *testing.T) { t.Fatal("unconsumed testdata") } } + +func TestDecoderMaxBytesError(t *testing.T) { + // Verify that Decoder.Decode returns the underlying IO error + // (not wrapped in *SyntaxError) when http.MaxBytesReader + // triggers a read limit, matching v1 behavior. + oversized := strings.Repeat("x", 1<<20+1) + body := `{"name":"` + oversized + `"}` + + req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(body)) + rec := httptest.NewRecorder() + req.Body = http.MaxBytesReader(rec, req.Body, 1<<20) + + var v map[string]any + err := NewDecoder(req.Body).Decode(&v) + if err == nil { + t.Fatal("expected error, got nil") + } + + var maxBytesErr *http.MaxBytesError + if !errors.As(err, &maxBytesErr) { + t.Errorf("errors.As(err, *http.MaxBytesError) = false, want true\nerror type: %T\nerror: %v", err, err) + } +} |
