Skip to content

Commit dd1a55d

Browse files
author
francois.parquet
committed
fix bug on escape sequence when skiping object or array
1 parent f4c5a97 commit dd1a55d

File tree

4 files changed

+34
-12
lines changed

4 files changed

+34
-12
lines changed

decode_array.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,26 +79,34 @@ func (dec *Decoder) skipArray() (int, error) {
7979
arraysOpen++
8080
case '"':
8181
j++
82-
for ; j < dec.length; j++ {
82+
var isInEscapeSeq bool
83+
var isFirstQuote = true
84+
for ; j < dec.length || dec.read(); j++ {
8385
if dec.data[j] != '"' {
8486
continue
8587
}
86-
if dec.data[j-1] != '\\' {
88+
if dec.data[j-1] != '\\' || (!isInEscapeSeq && !isFirstQuote) {
8789
break
90+
} else {
91+
isInEscapeSeq = false
92+
}
93+
if isFirstQuote {
94+
isFirstQuote = false
8895
}
8996
// loop backward and count how many anti slash found
9097
// to see if string is effectively escaped
91-
ct := 1
92-
for i := j - 2; i > 0; i-- {
98+
ct := 0
99+
for i := j - 1; i > 0; i-- {
93100
if dec.data[i] != '\\' {
94101
break
95102
}
96103
ct++
97104
}
98-
// is even number of slashes, quote is not escaped
105+
// is pair number of slashes, quote is not escaped
99106
if ct&1 == 0 {
100107
break
101108
}
109+
isInEscapeSeq = true
102110
}
103111
default:
104112
continue

decode_array_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,24 +510,28 @@ func TestUnmarshalJSONArrays(t *testing.T) {
510510

511511
func TestSkipArray(t *testing.T) {
512512
testCases := []struct {
513+
name string
513514
json string
514515
expectations func(*testing.T, int, error)
515516
}{
516517
{
518+
name: "basic",
517519
json: `"testbasic"]`,
518520
expectations: func(t *testing.T, i int, err error) {
519521
assert.Equal(t, len(`"testbasic"]`), i)
520522
assert.Nil(t, err)
521523
},
522524
},
523525
{
526+
name: "complex escape string",
524527
json: `"test \\\\\" escape"]`,
525528
expectations: func(t *testing.T, i int, err error) {
526529
assert.Equal(t, len(`"test \\\\\" escape"]`), i)
527530
assert.Nil(t, err)
528531
},
529532
},
530533
{
534+
name: "complex escape slash",
531535
json: `"test \\\\\\"]`,
532536
expectations: func(t *testing.T, i int, err error) {
533537
assert.Equal(t, len(`"test \\\\\\"]`), i)
@@ -537,9 +541,11 @@ func TestSkipArray(t *testing.T) {
537541
}
538542

539543
for _, test := range testCases {
540-
dec := NewDecoder(strings.NewReader(test.json))
541-
i, err := dec.skipArray()
542-
test.expectations(t, i, err)
544+
t.Run(test.name, func(t *testing.T) {
545+
dec := NewDecoder(strings.NewReader(test.json))
546+
i, err := dec.skipArray()
547+
test.expectations(t, i, err)
548+
})
543549
}
544550
}
545551

decode_object.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,23 @@ func (dec *Decoder) skipObject() (int, error) {
116116
objectsOpen++
117117
case '"':
118118
j++
119+
var isInEscapeSeq bool
120+
var isFirstQuote = true
119121
for ; j < dec.length || dec.read(); j++ {
120122
if dec.data[j] != '"' {
121123
continue
122124
}
123-
if dec.data[j-1] != '\\' {
125+
if dec.data[j-1] != '\\' || (!isInEscapeSeq && !isFirstQuote) {
124126
break
127+
} else {
128+
isInEscapeSeq = false
129+
}
130+
if isFirstQuote {
131+
isFirstQuote = false
125132
}
126133
// loop backward and count how many anti slash found
127134
// to see if string is effectively escaped
128-
ct := 1
135+
ct := 0
129136
for i := j - 1; i > 0; i-- {
130137
if dec.data[i] != '\\' {
131138
break
@@ -134,8 +141,9 @@ func (dec *Decoder) skipObject() (int, error) {
134141
}
135142
// is pair number of slashes, quote is not escaped
136143
if ct&1 == 0 {
137-
continue
144+
break
138145
}
146+
isInEscapeSeq = true
139147
}
140148
default:
141149
continue

decode_object_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,7 @@ func TestSkipObject(t *testing.T) {
13701370
},
13711371
{
13721372
name: "basic-escaped",
1373-
json: `"key":"value\\\\\\" hello"}`,
1373+
json: `"key":"value\\\\\\\" hello"}`,
13741374
},
13751375
{
13761376
name: "basic-err",

0 commit comments

Comments
 (0)