From 596a8c33492d713c4ae4b20ecf83f41cf049e978 Mon Sep 17 00:00:00 2001 From: haoqixu Date: Thu, 8 Aug 2024 19:35:45 +0800 Subject: [PATCH] encoding/json: fix location for JSON syntax error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The JSON decoder utilizes `parser.ParseExpr` to parse input data, which could be a valid CUE expression but an invalid JSON. Using the error position returned by `parser.ParseExpr` as output may cause cue to either omit the position or report the wrong position This change uses the offset returned by the JSON parser and recalculate the position to ensure the reported position is accurate. Fixes #3317 Change-Id: I019ab80c275d658f5773501d766ee9d03261ab58 Signed-off-by: haoqixu Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1199094 Reviewed-by: Daniel Martí TryBot-Result: CUEcueckoo --- .../testdata/script/json_syntax_error.txtar | 26 +++++++++++++++++++ encoding/json/json.go | 10 +++++++ 2 files changed, 36 insertions(+) create mode 100644 cmd/cue/cmd/testdata/script/json_syntax_error.txtar diff --git a/cmd/cue/cmd/testdata/script/json_syntax_error.txtar b/cmd/cue/cmd/testdata/script/json_syntax_error.txtar new file mode 100644 index 00000000000..6d40a57a8ce --- /dev/null +++ b/cmd/cue/cmd/testdata/script/json_syntax_error.txtar @@ -0,0 +1,26 @@ +! exec cue export x1.json +stderr 'x1*.json:4:3' + +! exec cue export x2.json +stderr 'x2.json:1:6' + +! exec cue export x3.json +stderr 'x3.json:1:1' + +! exec cue export x4.json +stderr 'x4.json:1:1' + +-- x1.json -- +{ + "foo": true, + "bar": 2 + "baz": false +} + +-- x2.json -- +"baz": false + +-- x3.json -- +baz: false + +-- x4.json -- diff --git a/encoding/json/json.go b/encoding/json/json.go index aaff32506d6..b21828ebce8 100644 --- a/encoding/json/json.go +++ b/encoding/json/json.go @@ -87,6 +87,16 @@ func extract(path string, b []byte) (ast.Expr, error) { } var x interface{} err := json.Unmarshal(b, &x) + + if len(b) > 0 { + var synErr *json.SyntaxError + if errors.As(err, &synErr) { + tokFile := token.NewFile(path, 0, len(b)) + tokFile.SetLinesForContent(b) + p = tokFile.Pos(int(synErr.Offset-1), token.NoRelPos) + } + } + return nil, errors.Wrapf(err, p, "invalid JSON for file %q", path) } return expr, nil