Skip to content

Commit 15548fd

Browse files
authored
Merge pull request #116 from plokhotnyuk/master
fix of parsing zero & min values: iterator head should point on next non-parsed byte
2 parents 07d21c2 + eb25f2d commit 15548fd

File tree

3 files changed

+65
-32
lines changed

3 files changed

+65
-32
lines changed

src/main/java/com/jsoniter/IterImpl.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,8 @@ public static int updateStringCopyBound(final JsonIterator iter, final int bound
307307

308308
static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException {
309309
int ind = IterImplNumber.intDigits[c];
310-
if (ind == 0) {
311-
throw iter.reportError("readPositiveInt", "leading zero is invalid for int");
312-
}
313310
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
314-
throw iter.reportError("readPositiveInt", "expect 1~9");
311+
throw iter.reportError("readPositiveInt", "expect 0~9");
315312
}
316313
if (iter.tail - iter.head > 9) {
317314
int i = iter.head;
@@ -320,6 +317,9 @@ static final int readPositiveInt(final JsonIterator iter, byte c) throws IOExcep
320317
iter.head = i;
321318
return ind;
322319
}
320+
if (ind == 0) {
321+
throw iter.reportError("readPositiveInt", "leading zero is invalid for int");
322+
}
323323
int ind3 = IterImplNumber.intDigits[iter.buf[++i]];
324324
if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
325325
iter.head = i;
@@ -362,11 +362,8 @@ static final int readPositiveInt(final JsonIterator iter, byte c) throws IOExcep
362362

363363
static final long readPositiveLong(final JsonIterator iter, byte c) throws IOException {
364364
long ind = IterImplNumber.intDigits[c];
365-
if (ind == 0) {
366-
throw iter.reportError("readPositiveLong", "leading zero is invalid for long");
367-
}
368365
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
369-
throw iter.reportError("readPositiveLong", "expect 1~9");
366+
throw iter.reportError("readPositiveLong", "expect 0~9");
370367
}
371368
if (iter.tail - iter.head > 9) {
372369
int i = iter.head;
@@ -375,6 +372,9 @@ static final long readPositiveLong(final JsonIterator iter, byte c) throws IOExc
375372
iter.head = i;
376373
return ind;
377374
}
375+
if (ind == 0) {
376+
throw iter.reportError("readPositiveLong", "leading zero is invalid for long");
377+
}
378378
int ind3 = IterImplNumber.intDigits[iter.buf[++i]];
379379
if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
380380
iter.head = i;

src/main/java/com/jsoniter/IterImplForStreaming.java

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -476,16 +476,14 @@ static long readLongSlowPath(JsonIterator iter, long value) throws IOException {
476476
iter.head = i;
477477
return value;
478478
}
479+
if (value == 0) {
480+
throw iter.reportError("readLongSlowPath", "leading zero is invalid for long");
481+
} else if (value == Long.MIN_VALUE) {
482+
throw iter.reportError("readLongSlowPath", "value is too large for long");
483+
}
479484
value = (value << 3) + (value << 1) + ind;
480-
if (value < 0) {
481-
// overflow
482-
if (value == Long.MIN_VALUE) {
483-
// if there is more number following, subsequent read will fail anyway
484-
iter.head = i + 1;
485-
return value;
486-
} else {
487-
throw iter.reportError("readPositiveLong", "value is too large for long");
488-
}
485+
if (value < 0 && value != Long.MIN_VALUE) {
486+
throw iter.reportError("readLongSlowPath", "value is too large for long");
489487
}
490488
}
491489
if (!IterImpl.loadMore(iter)) {
@@ -503,16 +501,14 @@ static int readIntSlowPath(JsonIterator iter, int value) throws IOException {
503501
iter.head = i;
504502
return value;
505503
}
504+
if (value == 0) {
505+
throw iter.reportError("readIntSlowPath", "leading zero is invalid for int");
506+
} else if (value == Integer.MIN_VALUE) {
507+
throw iter.reportError("readIntSlowPath", "value is too large for int");
508+
}
506509
value = (value << 3) + (value << 1) + ind;
507-
if (value < 0) {
508-
// overflow
509-
if (value == Integer.MIN_VALUE) {
510-
// if there is more number following, subsequent read will fail anyway
511-
iter.head = i + 1;
512-
return value;
513-
} else {
514-
throw iter.reportError("readPositiveInt", "value is too large for int");
515-
}
510+
if (value < 0 && value != Integer.MIN_VALUE) {
511+
throw iter.reportError("readIntSlowPath", "value is too large for int");
516512
}
517513
}
518514
if (!IterImpl.loadMore(iter)) {

src/test/java/com/jsoniter/TestInteger.java

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import java.io.ByteArrayInputStream;
88
import java.io.IOException;
9+
//import java.math.BigDecimal;
10+
//import java.math.BigInteger;
911

1012
public class TestInteger extends TestCase {
1113

@@ -21,25 +23,29 @@ public void test_char() throws IOException {
2123
}
2224

2325
public void test_positive_negative_int() throws IOException {
26+
assertEquals(0, parseInt("0"));
2427
assertEquals(4321, parseInt("4321"));
2528
assertEquals(54321, parseInt("54321"));
2629
assertEquals(654321, parseInt("654321"));
2730
assertEquals(7654321, parseInt("7654321"));
2831
assertEquals(87654321, parseInt("87654321"));
2932
assertEquals(987654321, parseInt("987654321"));
33+
assertEquals(2147483647, parseInt("2147483647"));
3034
assertEquals(-4321, parseInt("-4321"));
35+
assertEquals(-2147483648, parseInt("-2147483648"));
3136
}
3237

3338
public void test_positive_negative_long() throws IOException {
3439
assertEquals(0L, parseLong("0"));
35-
assertEquals(1L, parseLong("01"));
3640
assertEquals(4321L, parseLong("4321"));
3741
assertEquals(54321L, parseLong("54321"));
3842
assertEquals(654321L, parseLong("654321"));
3943
assertEquals(7654321L, parseLong("7654321"));
4044
assertEquals(87654321L, parseLong("87654321"));
4145
assertEquals(987654321L, parseLong("987654321"));
46+
assertEquals(9223372036854775807L, parseLong("9223372036854775807"));
4247
assertEquals(-4321L, parseLong("-4321"));
48+
assertEquals(-9223372036854775808L, parseLong("-9223372036854775808"));
4349
}
4450

4551
public void test_max_min_int() throws IOException {
@@ -88,20 +94,47 @@ public void test_streaming() throws IOException {
8894

8995
public void test_leading_zero() throws IOException {
9096
try {
91-
JsonIterator.deserialize("001", int.class);
97+
JsonIterator.deserialize("01", int.class);
9298
fail();
9399
} catch (JsonException e) {
94100
}
95101
try {
96-
JsonIterator.deserialize("001", long.class);
102+
JsonIterator.deserialize("02147483647", int.class);
97103
fail();
98104
} catch (JsonException e) {
99105
}
100106
try {
101-
JsonIterator.deserialize("001");
107+
JsonIterator.deserialize("01", long.class);
102108
fail();
103109
} catch (JsonException e) {
104110
}
111+
try {
112+
JsonIterator.deserialize("09223372036854775807", long.class);
113+
fail();
114+
} catch (JsonException e) {
115+
}
116+
/* FIXME if we should fail on parsing of leading zeroes for other numbers
117+
try {
118+
JsonIterator.deserialize("01", double.class);
119+
fail();
120+
} catch (JsonException e) {
121+
}
122+
try {
123+
JsonIterator.deserialize("01", float.class);
124+
fail();
125+
} catch (JsonException e) {
126+
}
127+
try {
128+
JsonIterator.deserialize("01", BigInteger.class);
129+
fail();
130+
} catch (JsonException e) {
131+
}
132+
try {
133+
JsonIterator.deserialize("01", BigDecimal.class);
134+
fail();
135+
} catch (JsonException e) {
136+
}
137+
*/
105138
}
106139

107140
public void test_max_int() throws IOException {
@@ -116,7 +149,9 @@ private int parseInt(String input) throws IOException {
116149
return iter.readInt();
117150
} else {
118151
JsonIterator iter = JsonIterator.parse(input);
119-
return iter.readInt();
152+
int v = iter.readInt();
153+
assertEquals(input.length(), iter.head); // iterator head should point on next non-parsed byte
154+
return v;
120155
}
121156
}
122157

@@ -126,7 +161,9 @@ private long parseLong(String input) throws IOException {
126161
return iter.readLong();
127162
} else {
128163
JsonIterator iter = JsonIterator.parse(input);
129-
return iter.readLong();
164+
long v = iter.readLong();
165+
assertEquals(input.length(), iter.head); // iterator head should point on next non-parsed byte
166+
return v;
130167
}
131168
}
132169
}

0 commit comments

Comments
 (0)