diff --git a/internal/decoder/string.go b/internal/decoder/string.go index 9e8c737..5c2389e 100644 --- a/internal/decoder/string.go +++ b/internal/decoder/string.go @@ -239,7 +239,15 @@ func stringBytes(s *Stream) ([]byte, error) { fallthrough default: // multi bytes character - r, size := utf8.DecodeRune(s.buf[cursor:]) + if !utf8.FullRune(s.buf[cursor : len(s.buf)-1]) { + s.cursor = cursor + if s.read() { + _, cursor, p = s.stat() + continue + } + goto ERROR + } + r, size := utf8.DecodeRune(s.buf[cursor:]) if r == utf8.RuneError { s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...) cursor += runeErrBytesLen diff --git a/stream_test.go b/stream_test.go index 67c91ba..010b87e 100644 --- a/stream_test.go +++ b/stream_test.go @@ -14,6 +14,7 @@ import ( "net/http" "net/http/httptest" "reflect" + "strconv" "strings" "testing" @@ -502,6 +503,19 @@ func TestGzipStreaming(t *testing.T) { } } +func TestLongUTF8(t *testing.T) { + want := strings.Repeat("あ", 342) + r := strings.NewReader(strconv.Quote(want)) + + var got string + if err := json.NewDecoder(r).Decode(&got); err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if got != want { + t.Errorf("string %q; want = %q", got, want) + } +} + func TestIssue278(t *testing.T) { a := `{"嗷嗷":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\u55f7"}` r := strings.NewReader(a)