Skip to content

Commit 853eaa1

Browse files
authored
Extend the short strings quote check (#113)
1 parent d2e2596 commit 853eaa1

1 file changed

Lines changed: 14 additions & 6 deletions

File tree

json/parse.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -417,25 +417,33 @@ func (d decoder) parseString(b []byte) ([]byte, []byte, Kind, error) {
417417

418418
var n int
419419
if len(b) >= 9 {
420-
// This is an optimization for short strings. We read 8 bytes,
420+
// This is an optimization for short strings. We read 8/16 bytes,
421421
// and XOR each with 0x22 (") so that these bytes (and only
422422
// these bytes) are now zero. We use the hasless(u,1) trick
423423
// from https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
424424
// to determine whether any bytes are zero. Finally, we CTZ
425425
// to find the index of that byte.
426-
u := binary.LittleEndian.Uint64(b[1:])
427-
u ^= 0x2222222222222222
428-
mask := (u - 0x0101010101010101) & ^u & 0x8080808080808080
429-
if mask != 0 {
426+
const mask1 = 0x2222222222222222
427+
const mask2 = 0x0101010101010101
428+
const mask3 = 0x8080808080808080
429+
u := binary.LittleEndian.Uint64(b[1:]) ^ mask1
430+
if mask := (u - mask2) & ^u & mask3; mask != 0 {
430431
n = bits.TrailingZeros64(mask)/8 + 2
431432
goto found
432433
}
434+
if len(b) >= 17 {
435+
u = binary.LittleEndian.Uint64(b[9:]) ^ mask1
436+
if mask := (u - mask2) & ^u & mask3; mask != 0 {
437+
n = bits.TrailingZeros64(mask)/8 + 10
438+
goto found
439+
}
440+
}
433441
}
434442
n = bytes.IndexByte(b[1:], '"') + 2
435-
found:
436443
if n <= 1 {
437444
return nil, b[len(b):], Undefined, syntaxError(b, "missing '\"' at the end of a string value")
438445
}
446+
found:
439447
if (d.flags.has(noBackslash) || bytes.IndexByte(b[1:n], '\\') < 0) &&
440448
(d.flags.has(validAsciiPrint) || ascii.ValidPrint(b[1:n])) {
441449
return b[:n], b[n:], Unescaped, nil

0 commit comments

Comments
 (0)