Skip to content

Commit 301ed10

Browse files
committed
Fix messages of errors when parsing invalid java.time.Duration values
1 parent 8192daf commit 301ed10

File tree

4 files changed

+149
-164
lines changed

4 files changed

+149
-164
lines changed

jsoniter-scala-core/js/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReader.scala

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,7 +1720,7 @@ final class JsonReader private[jsoniter_scala](
17201720
}
17211721
head = pos + 1
17221722
if (b1 == '-' && year == 0 || yearDigits == 10 && year > 1000000000) yearError(pos - 1)
1723-
if (b != t) yearError(t, maxDigits, pos, b1 == '-', yearDigits)
1723+
if (b != t) yearError(t, maxDigits, pos, b1, yearDigits)
17241724
if (b1 == '-') year = -year
17251725
if (year >= 0 && year < 10000) digitError(pos)
17261726
year
@@ -2922,28 +2922,27 @@ final class JsonReader private[jsoniter_scala](
29222922
if (x < -153722867280912930L || x > 153722867280912930L) durationError(pos) // -153722867280912930L == Long.MinValue / 60
29232923
seconds = sumSeconds(x * 60, seconds, pos)
29242924
state = 2
2925-
} else if (b == '.') {
2926-
pos += 1
2925+
} else if (b == 'S' || b == '.') {
29272926
seconds = sumSeconds(x, seconds, pos)
2928-
var nanoDigitWeight = 100000000
2929-
while ({
2930-
if (pos >= tail) {
2931-
pos = loadMoreOrError(pos)
2932-
buf = this.buf
2933-
}
2934-
b = buf(pos)
2935-
(b >= '0' && b <= '9') && nanoDigitWeight != 0
2936-
}) {
2937-
nano += (b - '0') * nanoDigitWeight
2938-
nanoDigitWeight /= 10
2927+
state = 3
2928+
if (b == '.') {
29392929
pos += 1
2930+
var nanoDigitWeight = 100000000
2931+
while ({
2932+
if (pos >= tail) {
2933+
pos = loadMoreOrError(pos)
2934+
buf = this.buf
2935+
}
2936+
b = buf(pos)
2937+
(b >= '0' && b <= '9') && nanoDigitWeight != 0
2938+
}) {
2939+
nano += (b - '0') * nanoDigitWeight
2940+
nanoDigitWeight /= 10
2941+
pos += 1
2942+
}
2943+
if (b != 'S') nanoError(nanoDigitWeight, 'S', pos)
2944+
nano = (nano ^ sx) - sx
29402945
}
2941-
if (b != 'S') nanoError(nanoDigitWeight, 'S', pos)
2942-
nano = (nano ^ sx) - sx
2943-
state = 3
2944-
} else if (b == 'S') {
2945-
seconds = sumSeconds(x, seconds, pos)
2946-
state = 3
29472946
} else durationError(state, pos)
29482947
b = nextByte(pos + 1)
29492948
b != '"'
@@ -3170,10 +3169,8 @@ final class JsonReader private[jsoniter_scala](
31703169
}) periodError(pos)
31713170
pos += 1
31723171
}
3173-
if (sx == 0) {
3174-
if (x == -2147483648) periodError(pos)
3175-
x = -x
3176-
}
3172+
x = sx - (x ^ sx)
3173+
if ((sx | x) == -2147483648) periodError(pos)
31773174
if (b == 'Y' && state <= 0) {
31783175
years = x
31793176
state = 1
@@ -3390,13 +3387,13 @@ final class JsonReader private[jsoniter_scala](
33903387

33913388
private[this] def durationError(state: Int, pos: Int): Nothing = decodeError(state match {
33923389
case -1 => "expected 'D' or digit"
3393-
case 0 => "expected 'H' or 'M' or 'S or '.' or digit"
3394-
case 1 => "expected 'M' or 'S or '.' or digit"
3395-
case _ => "expected 'S or '.' or digit"
3390+
case 0 => "expected 'H' or 'M' or 'S' or '.' or digit"
3391+
case 1 => "expected 'M' or 'S' or '.' or digit"
3392+
case _ => "expected 'S' or '.' or digit"
33963393
}, pos)
33973394

3398-
private[this] def yearError(t: Byte, maxDigits: Int, pos: Int, isNeg: Boolean, yearDigits: Int): Nothing = {
3399-
if (!isNeg && yearDigits == 4) digitError(pos)
3395+
private[this] def yearError(t: Byte, maxDigits: Int, pos: Int, b: Byte, yearDigits: Int): Nothing = {
3396+
if (b != '-' && yearDigits == 4) digitError(pos)
34003397
if (yearDigits == maxDigits) tokenError(t, pos)
34013398
tokenOrDigitError(t, pos)
34023399
}

jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReader.scala

Lines changed: 60 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,7 +1745,7 @@ final class JsonReader private[jsoniter_scala](
17451745
}
17461746
head = pos + 1
17471747
if (b1 == '-' && year == 0 || yearDigits == 10 && year > 1000000000) yearError(pos - 1)
1748-
if (b != t) yearError(t, maxDigits, pos, b1 == '-', yearDigits)
1748+
if (b != t) yearError(t, maxDigits, pos, b1, yearDigits)
17491749
if (b1 == '-') year = -year
17501750
if (year >= 0 && year < 10000) digitError(pos)
17511751
year
@@ -2883,12 +2883,12 @@ final class JsonReader private[jsoniter_scala](
28832883

28842884
private[this] def parseDuration(): Duration = {
28852885
var b = nextByte(head)
2886-
var s = 0
2886+
var s = 0L
28872887
if (b == '-') {
28882888
b = nextByte(head)
2889-
s = -1
2889+
s = ~s
28902890
}
2891-
if (b != 'P') durationOrPeriodStartError(s)
2891+
if (b != 'P') durationOrPeriodStartError(s.toInt)
28922892
b = nextByte(head)
28932893
var state = -1
28942894
if (b == 'T') {
@@ -2903,7 +2903,7 @@ final class JsonReader private[jsoniter_scala](
29032903
b = nextByte(head)
29042904
sx = ~sx
29052905
}
2906-
if (b < '0' || b > '9') durationOrPeriodDigitError(s, sx, state)
2906+
if (b < '0' || b > '9') durationOrPeriodDigitError(s.toInt, sx.toInt, state)
29072907
var x = ('0' - b).toLong
29082908
var pos = head
29092909
var buf = this.buf
@@ -2921,67 +2921,63 @@ final class JsonReader private[jsoniter_scala](
29212921
}) durationError(pos)
29222922
pos += 1
29232923
}
2924-
if (sx == 0) {
2925-
if (x == -9223372036854775808L) durationError(pos)
2926-
x = -x
2927-
}
29282924
if (b == 'D' && state < 0) {
2929-
if (x < -106751991167300L || x > 106751991167300L) durationError(pos) // -106751991167300L == Long.MinValue / 86400
2930-
seconds = x * 86400
2925+
if (x < -106751991167300L) durationError(pos) // -106751991167300L == Long.MinValue / 86400
2926+
seconds = (sx - (x ^ sx)) * 86400
29312927
state = 0
29322928
} else if (b == 'H' && state <= 0) {
2933-
if (x < -2562047788015215L || x > 2562047788015215L) durationError(pos) // -2562047788015215L == Long.MinValue / 3600
2934-
seconds = sumSeconds(x * 3600, seconds, pos)
2929+
if (x < -2562047788015215L) durationError(pos) // -2562047788015215L == Long.MinValue / 3600
2930+
seconds = sumSeconds((sx - (x ^ sx)) * 3600, seconds, pos)
29352931
state = 1
29362932
} else if (b == 'M' && state <= 1) {
2937-
if (x < -153722867280912930L || x > 153722867280912930L) durationError(pos) // -153722867280912930L == Long.MinValue / 60
2938-
seconds = sumSeconds(x * 60, seconds, pos)
2933+
if (x < -153722867280912930L) durationError(pos) // -153722867280912930L == Long.MinValue / 60
2934+
seconds = sumSeconds((sx - (x ^ sx)) * 60, seconds, pos)
29392935
state = 2
2940-
} else if (b == '.') {
2941-
pos += 1
2942-
seconds = sumSeconds(x, seconds, pos)
2943-
var nanoDigitWeight = 100000000
2944-
var bs = 0
2945-
if (pos + 9 < tail && {
2946-
bs = ByteArrayAccess.getInt(buf, pos) - 0x303030
2947-
((bs + 0x767676 | bs) & 0x808080) == 0
2948-
} && {
2949-
nano = ((bs * 2561 & 0xFF00FF) * 6553601 >> 16) * 1000000
2950-
pos += 3
2951-
bs = ByteArrayAccess.getInt(buf, pos) - 0x303030
2952-
nanoDigitWeight = 100000
2953-
((bs + 0x767676 | bs) & 0x808080) == 0
2954-
} && {
2955-
nano += ((bs * 2561 & 0xFF00FF) * 6553601 >> 16) * 1000
2956-
pos += 3
2957-
bs = ByteArrayAccess.getInt(buf, pos) - 0x303030
2958-
nanoDigitWeight = 100
2959-
((bs + 0x767676 | bs) & 0x808080) == 0
2960-
}) {
2961-
nano += (bs * 2561 & 0xFF00FF) * 6553601 >> 16
2962-
pos += 3
2963-
b = (bs >> 24).toByte
2964-
nanoDigitWeight = 0
2965-
} else {
2966-
while ({
2967-
if (pos >= tail) {
2968-
pos = loadMoreOrError(pos)
2969-
buf = this.buf
2970-
}
2971-
b = buf(pos)
2972-
(b >= '0' && b <= '9') && nanoDigitWeight != 0
2936+
} else if (b == 'S' || b == '.') {
2937+
if ((x | sx) == -9223372036854775808L) durationError(pos)
2938+
seconds = sumSeconds(sx - (x ^ sx), seconds, pos)
2939+
state = 3
2940+
if (b == '.') {
2941+
pos += 1
2942+
var nanoDigitWeight = 100000000
2943+
var bs = 0
2944+
if (pos + 9 < tail && {
2945+
bs = ByteArrayAccess.getInt(buf, pos) - 0x303030
2946+
((bs + 0x767676 | bs) & 0x808080) == 0
2947+
} && {
2948+
nano = ((bs * 2561 & 0xFF00FF) * 6553601 >> 16) * 1000000
2949+
pos += 3
2950+
bs = ByteArrayAccess.getInt(buf, pos) - 0x303030
2951+
nanoDigitWeight = 100000
2952+
((bs + 0x767676 | bs) & 0x808080) == 0
2953+
} && {
2954+
nano += ((bs * 2561 & 0xFF00FF) * 6553601 >> 16) * 1000
2955+
pos += 3
2956+
bs = ByteArrayAccess.getInt(buf, pos) - 0x303030
2957+
nanoDigitWeight = 100
2958+
((bs + 0x767676 | bs) & 0x808080) == 0
29732959
}) {
2974-
nano += (b - '0') * nanoDigitWeight
2975-
nanoDigitWeight = (nanoDigitWeight * 429496730L >> 32).toInt // divide a small positive int by 10
2976-
pos += 1
2960+
nano += (bs * 2561 & 0xFF00FF) * 6553601 >> 16
2961+
pos += 3
2962+
b = (bs >> 24).toByte
2963+
nanoDigitWeight = 0
2964+
} else {
2965+
while ({
2966+
if (pos >= tail) {
2967+
pos = loadMoreOrError(pos)
2968+
buf = this.buf
2969+
}
2970+
b = buf(pos)
2971+
(b >= '0' && b <= '9') && nanoDigitWeight != 0
2972+
}) {
2973+
nano += (b - '0') * nanoDigitWeight
2974+
nanoDigitWeight = (nanoDigitWeight * 429496730L >> 32).toInt // divide a small positive int by 10
2975+
pos += 1
2976+
}
29772977
}
2978+
if (b != 'S') nanoError(nanoDigitWeight, 'S', pos)
2979+
nano = ((nano ^ sx) - sx).toInt
29782980
}
2979-
if (b != 'S') nanoError(nanoDigitWeight, 'S', pos)
2980-
nano = (nano ^ sx) - sx
2981-
state = 3
2982-
} else if (b == 'S') {
2983-
seconds = sumSeconds(x, seconds, pos)
2984-
state = 3
29852981
} else durationError(state, pos)
29862982
b = nextByte(pos + 1)
29872983
b != '"'
@@ -3516,10 +3512,8 @@ final class JsonReader private[jsoniter_scala](
35163512
}) periodError(pos)
35173513
pos += 1
35183514
}
3519-
if (sx == 0) {
3520-
if (x == -2147483648) periodError(pos)
3521-
x = -x
3522-
}
3515+
x = sx - (x ^ sx)
3516+
if ((sx | x) == -2147483648) periodError(pos)
35233517
if (b == 'Y' && state <= 0) {
35243518
years = x
35253519
state = 1
@@ -3824,13 +3818,13 @@ final class JsonReader private[jsoniter_scala](
38243818

38253819
private[this] def durationError(state: Int, pos: Int): Nothing = decodeError(state match {
38263820
case -1 => "expected 'D' or digit"
3827-
case 0 => "expected 'H' or 'M' or 'S or '.' or digit"
3828-
case 1 => "expected 'M' or 'S or '.' or digit"
3829-
case _ => "expected 'S or '.' or digit"
3821+
case 0 => "expected 'H' or 'M' or 'S' or '.' or digit"
3822+
case 1 => "expected 'M' or 'S' or '.' or digit"
3823+
case _ => "expected 'S' or '.' or digit"
38303824
}, pos)
38313825

3832-
private[this] def yearError(t: Byte, maxDigits: Int, pos: Int, isNeg: Boolean, yearDigits: Int): Nothing = {
3833-
if (!isNeg && yearDigits == 4) digitError(pos)
3826+
private[this] def yearError(t: Byte, maxDigits: Int, pos: Int, b: Byte, yearDigits: Int): Nothing = {
3827+
if (b != '-' && yearDigits == 4) digitError(pos)
38343828
if (yearDigits == maxDigits) tokenError(t, pos)
38353829
tokenOrDigitError(t, pos)
38363830
}

0 commit comments

Comments
 (0)