From 1d3d2c3717c4e0671caa74818300bbdc104ec54f Mon Sep 17 00:00:00 2001 From: Matthew Nibecker Date: Thu, 29 Feb 2024 08:42:42 -0700 Subject: [PATCH 1/2] jsonio: Fix parse errors on EOF Fix an issue with jsonio.Reader where parse errors occurring at the end of an input (EOF) are often ignored or return an ambiguous EOF error. --- pkg/jsonlexer/lexer.go | 3 +++ zio/jsonio/reader.go | 7 +++++- zio/jsonio/ztests/unexpected-input-end.yaml | 28 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 zio/jsonio/ztests/unexpected-input-end.yaml diff --git a/pkg/jsonlexer/lexer.go b/pkg/jsonlexer/lexer.go index 9b2ab7da34..75728cb341 100644 --- a/pkg/jsonlexer/lexer.go +++ b/pkg/jsonlexer/lexer.go @@ -160,6 +160,9 @@ func (l *Lexer) readString() Token { c, err := l.br.ReadByte() if err != nil { l.err = err + if err == io.EOF { + l.err = errors.New("unexpected end of JSON input") + } return TokenErr } l.buf = append(l.buf, c) diff --git a/zio/jsonio/reader.go b/zio/jsonio/reader.go index d44da87c06..c3b653a475 100644 --- a/zio/jsonio/reader.go +++ b/zio/jsonio/reader.go @@ -2,6 +2,7 @@ package jsonio import ( "bufio" + "errors" "fmt" "io" @@ -149,7 +150,11 @@ func (r *Reader) readNameValuePair(t jsonlexer.Token) error { func (r *Reader) error(t jsonlexer.Token, msg string) error { if t == jsonlexer.TokenErr { - return r.lexer.Err() + err := r.lexer.Err() + if err == io.EOF { + return errors.New("unexpected end of JSON input") + } + return err } return fmt.Errorf("invalid character %q %s", r.lexer.Buf()[0], msg) } diff --git a/zio/jsonio/ztests/unexpected-input-end.yaml b/zio/jsonio/ztests/unexpected-input-end.yaml new file mode 100644 index 0000000000..8f7fca273e --- /dev/null +++ b/zio/jsonio/ztests/unexpected-input-end.yaml @@ -0,0 +1,28 @@ +script: | + while IFS= read -r line; do + ! echo "$line" | zq -i json - + done < errors.txt + +inputs: + - name: errors.txt + data: | + "3 + ["3", + ["3" + {"foo": + {"foo":"bar", + {"foo":"bar" + {"foo":"bar + +outputs: + - name: stderr + data: | + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + - name: stdout + data: "" From 626840af598dd32f7d9e2a061a2b23e364472ae1 Mon Sep 17 00:00:00 2001 From: Matthew Nibecker Date: Thu, 29 Feb 2024 11:58:08 -0700 Subject: [PATCH 2/2] handle primitives --- pkg/jsonlexer/lexer.go | 5 ++++- zio/jsonio/reader.go | 4 ++-- zio/jsonio/ztests/unexpected-input-end.yaml | 8 +++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pkg/jsonlexer/lexer.go b/pkg/jsonlexer/lexer.go index 75728cb341..72e361a0c3 100644 --- a/pkg/jsonlexer/lexer.go +++ b/pkg/jsonlexer/lexer.go @@ -93,6 +93,9 @@ func (l *Lexer) readLiteral(s string, t Token) Token { for i := range s { c, err := l.br.ReadByte() if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } l.err = err return TokenErr } @@ -161,7 +164,7 @@ func (l *Lexer) readString() Token { if err != nil { l.err = err if err == io.EOF { - l.err = errors.New("unexpected end of JSON input") + l.err = io.ErrUnexpectedEOF } return TokenErr } diff --git a/zio/jsonio/reader.go b/zio/jsonio/reader.go index c3b653a475..de357e0554 100644 --- a/zio/jsonio/reader.go +++ b/zio/jsonio/reader.go @@ -36,7 +36,7 @@ func (r *Reader) Read() (*zed.Value, error) { if err == io.EOF { return nil, nil } - return nil, err + return nil, r.error(t, "") } r.builder.reset() if err := r.handleToken("", t); err != nil { @@ -151,7 +151,7 @@ func (r *Reader) readNameValuePair(t jsonlexer.Token) error { func (r *Reader) error(t jsonlexer.Token, msg string) error { if t == jsonlexer.TokenErr { err := r.lexer.Err() - if err == io.EOF { + if err == io.EOF || err == io.ErrUnexpectedEOF { return errors.New("unexpected end of JSON input") } return err diff --git a/zio/jsonio/ztests/unexpected-input-end.yaml b/zio/jsonio/ztests/unexpected-input-end.yaml index 8f7fca273e..24415c3221 100644 --- a/zio/jsonio/ztests/unexpected-input-end.yaml +++ b/zio/jsonio/ztests/unexpected-input-end.yaml @@ -1,11 +1,14 @@ script: | while IFS= read -r line; do - ! echo "$line" | zq -i json - + ! printf "$line" | zq -i json - done < errors.txt inputs: - name: errors.txt data: | + tru + fal + nu "3 ["3", ["3" @@ -24,5 +27,8 @@ outputs: stdio:stdin: unexpected end of JSON input stdio:stdin: unexpected end of JSON input stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input + stdio:stdin: unexpected end of JSON input - name: stdout data: ""