gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit 73600a98c556ff2da24a90f556188b676eaaff31
parent ef10bf36a252f8bda1248cedda106996f6512379
Author: Francois Parquet <francois.parquet@gmail.com>
Date:   Wed,  5 Dec 2018 12:08:09 +0800

Merge pull request #91 from francoispqt/fix/skip-unicode-string

Fix error when skipping string with unicode 
Diffstat:
Mdecode_object_test.go | 46++++++++++++++++++++++++++++++++++++++++++++--
Mdecode_string.go | 11+++++++++--
Mdecode_string_test.go | 12++++++++----
3 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/decode_object_test.go b/decode_object_test.go @@ -447,7 +447,7 @@ func TestDecodeObjectBasic(t *testing.T) { err: false, }, { - name: "basic-skip-data", + name: "basic-skip-data-error-uint8-negative", json: `{ "testStr": "hello world!", "testInt": 4535, @@ -469,7 +469,7 @@ func TestDecodeObjectBasic(t *testing.T) { "testUint32": 343443, "testUint64": 545665757, "skipString": "skipping string with escaped \\n new line", - "skipInt": 3, + "skipInt": 3 }`, expectedResult: testObject{ testStr: "hello world!", @@ -488,6 +488,48 @@ func TestDecodeObjectBasic(t *testing.T) { }, err: true, }, + { + name: "skip-data-with-unicode", + json: `{ + "skipString": "hello\u1234\u2123", + "testStr": "hello world!", + "testInt": 4535, + "testBool": true, + "testFloat32": 2.345, + "testFloat64": 123.677, + "testInt8": 23, + "skipObject": { + "escapedString": "string with unicode \u1234\u1234\u1234" + }, + "testInt16": 1245, + "testInt32": 456778, + "testInt64": 1446685358, + "testUint8": 255, + "skipArray": [[],[],{}], + "testUint16": 3455, + "skipBool": true, + "skipNull": null, + "testUint32": 343443, + "testUint64": 545665757, + "skipInt": 3 + }`, + expectedResult: testObject{ + testStr: "hello world!", + testInt: 4535, + testBool: true, + testFloat32: 2.345, + testFloat64: 123.677, + testInt8: 23, + testInt16: 1245, + testInt32: 456778, + testInt64: 1446685358, + testUint8: 255, + testUint16: 3455, + testUint32: 343443, + testUint64: 545665757, + }, + err: false, + }, } for _, testCase := range testCases { diff --git a/decode_string.go b/decode_string.go @@ -178,6 +178,12 @@ func (dec *Decoder) skipEscapedString() error { return dec.raiseInvalidJSONErr(dec.cursor) } return nil + case 'u': // is unicode, we skip the following characters and place the cursor one one byte backward to avoid it breaking when returning to skipString + if err := dec.skipString(); err != nil { + return err + } + dec.cursor-- + return nil case 'n', 'r', 't', '/', 'f', 'b': return nil default: @@ -195,11 +201,12 @@ func (dec *Decoder) skipEscapedString() error { func (dec *Decoder) skipString() error { for dec.cursor < dec.length || dec.read() { switch dec.data[dec.cursor] { - // string found + // found the closing quote + // let's return case '"': dec.cursor = dec.cursor + 1 return nil - // slash found + // solidus found start parsing an escaped string case '\\': dec.cursor = dec.cursor + 1 err := dec.skipEscapedString() diff --git a/decode_string_test.go b/decode_string_test.go @@ -738,10 +738,15 @@ func TestSkipString(t *testing.T) { expectedResult: "", err: false, }, + { + name: "string-unicode", + json: `[2]\u66fe\u5b97\u5357"`, + expectedResult: "", + err: false, + }, } for _, testCase := range testCases { - str := "" dec := NewDecoder(strings.NewReader(testCase.json)) err := dec.skipString() if testCase.err { @@ -749,9 +754,8 @@ func TestSkipString(t *testing.T) { if testCase.errType != nil { assert.IsType(t, testCase.errType, err, "err should be of expected type") } - } else { - assert.Nil(t, err, "err should be nil") + return } - assert.Equal(t, testCase.expectedResult, str, fmt.Sprintf("str should be equal to '%s'", testCase.expectedResult)) + assert.Nil(t, err, "err should be nil") } }