diff --git a/src/main/java/com/jsoniter/IterImpl.java b/src/main/java/com/jsoniter/IterImpl.java index 4ef677ac..0d9cd356 100644 --- a/src/main/java/com/jsoniter/IterImpl.java +++ b/src/main/java/com/jsoniter/IterImpl.java @@ -307,11 +307,8 @@ public static int updateStringCopyBound(final JsonIterator iter, final int bound static final int readPositiveInt(final JsonIterator iter, byte c) throws IOException { int ind = IterImplNumber.intDigits[c]; - if (ind == 0) { - throw iter.reportError("readPositiveInt", "leading zero is invalid for int"); - } if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { - throw iter.reportError("readPositiveInt", "expect 1~9"); + throw iter.reportError("readPositiveInt", "expect 0~9"); } if (iter.tail - iter.head > 9) { int i = iter.head; @@ -320,6 +317,9 @@ static final int readPositiveInt(final JsonIterator iter, byte c) throws IOExcep iter.head = i; return ind; } + if (ind == 0) { + throw iter.reportError("readPositiveInt", "leading zero is invalid for int"); + } int ind3 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; @@ -362,11 +362,8 @@ static final int readPositiveInt(final JsonIterator iter, byte c) throws IOExcep static final long readPositiveLong(final JsonIterator iter, byte c) throws IOException { long ind = IterImplNumber.intDigits[c]; - if (ind == 0) { - throw iter.reportError("readPositiveLong", "leading zero is invalid for long"); - } if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { - throw iter.reportError("readPositiveLong", "expect 1~9"); + throw iter.reportError("readPositiveLong", "expect 0~9"); } if (iter.tail - iter.head > 9) { int i = iter.head; @@ -375,6 +372,9 @@ static final long readPositiveLong(final JsonIterator iter, byte c) throws IOExc iter.head = i; return ind; } + if (ind == 0) { + throw iter.reportError("readPositiveLong", "leading zero is invalid for long"); + } int ind3 = IterImplNumber.intDigits[iter.buf[++i]]; if (ind3 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) { iter.head = i; diff --git a/src/main/java/com/jsoniter/IterImplForStreaming.java b/src/main/java/com/jsoniter/IterImplForStreaming.java index 0706ff6b..651bfd93 100644 --- a/src/main/java/com/jsoniter/IterImplForStreaming.java +++ b/src/main/java/com/jsoniter/IterImplForStreaming.java @@ -476,16 +476,14 @@ static long readLongSlowPath(JsonIterator iter, long value) throws IOException { iter.head = i; return value; } + if (value == 0) { + throw iter.reportError("readLongSlowPath", "leading zero is invalid for long"); + } else if (value == Long.MIN_VALUE) { + throw iter.reportError("readLongSlowPath", "value is too large for long"); + } value = (value << 3) + (value << 1) + ind; - if (value < 0) { - // overflow - if (value == Long.MIN_VALUE) { - // if there is more number following, subsequent read will fail anyway - iter.head = i + 1; - return value; - } else { - throw iter.reportError("readPositiveLong", "value is too large for long"); - } + if (value < 0 && value != Long.MIN_VALUE) { + throw iter.reportError("readLongSlowPath", "value is too large for long"); } } if (!IterImpl.loadMore(iter)) { @@ -503,16 +501,14 @@ static int readIntSlowPath(JsonIterator iter, int value) throws IOException { iter.head = i; return value; } + if (value == 0) { + throw iter.reportError("readIntSlowPath", "leading zero is invalid for int"); + } else if (value == Integer.MIN_VALUE) { + throw iter.reportError("readIntSlowPath", "value is too large for int"); + } value = (value << 3) + (value << 1) + ind; - if (value < 0) { - // overflow - if (value == Integer.MIN_VALUE) { - // if there is more number following, subsequent read will fail anyway - iter.head = i + 1; - return value; - } else { - throw iter.reportError("readPositiveInt", "value is too large for int"); - } + if (value < 0 && value != Integer.MIN_VALUE) { + throw iter.reportError("readIntSlowPath", "value is too large for int"); } } if (!IterImpl.loadMore(iter)) { diff --git a/src/test/java/com/jsoniter/TestInteger.java b/src/test/java/com/jsoniter/TestInteger.java index 9b528bcc..72cda2e9 100644 --- a/src/test/java/com/jsoniter/TestInteger.java +++ b/src/test/java/com/jsoniter/TestInteger.java @@ -6,6 +6,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +//import java.math.BigDecimal; +//import java.math.BigInteger; public class TestInteger extends TestCase { @@ -21,25 +23,29 @@ public void test_char() throws IOException { } public void test_positive_negative_int() throws IOException { + assertEquals(0, parseInt("0")); assertEquals(4321, parseInt("4321")); assertEquals(54321, parseInt("54321")); assertEquals(654321, parseInt("654321")); assertEquals(7654321, parseInt("7654321")); assertEquals(87654321, parseInt("87654321")); assertEquals(987654321, parseInt("987654321")); + assertEquals(2147483647, parseInt("2147483647")); assertEquals(-4321, parseInt("-4321")); + assertEquals(-2147483648, parseInt("-2147483648")); } public void test_positive_negative_long() throws IOException { assertEquals(0L, parseLong("0")); - assertEquals(1L, parseLong("01")); assertEquals(4321L, parseLong("4321")); assertEquals(54321L, parseLong("54321")); assertEquals(654321L, parseLong("654321")); assertEquals(7654321L, parseLong("7654321")); assertEquals(87654321L, parseLong("87654321")); assertEquals(987654321L, parseLong("987654321")); + assertEquals(9223372036854775807L, parseLong("9223372036854775807")); assertEquals(-4321L, parseLong("-4321")); + assertEquals(-9223372036854775808L, parseLong("-9223372036854775808")); } public void test_max_min_int() throws IOException { @@ -88,20 +94,47 @@ public void test_streaming() throws IOException { public void test_leading_zero() throws IOException { try { - JsonIterator.deserialize("001", int.class); + JsonIterator.deserialize("01", int.class); fail(); } catch (JsonException e) { } try { - JsonIterator.deserialize("001", long.class); + JsonIterator.deserialize("02147483647", int.class); fail(); } catch (JsonException e) { } try { - JsonIterator.deserialize("001"); + JsonIterator.deserialize("01", long.class); fail(); } catch (JsonException e) { } + try { + JsonIterator.deserialize("09223372036854775807", long.class); + fail(); + } catch (JsonException e) { + } +/* FIXME if we should fail on parsing of leading zeroes for other numbers + try { + JsonIterator.deserialize("01", double.class); + fail(); + } catch (JsonException e) { + } + try { + JsonIterator.deserialize("01", float.class); + fail(); + } catch (JsonException e) { + } + try { + JsonIterator.deserialize("01", BigInteger.class); + fail(); + } catch (JsonException e) { + } + try { + JsonIterator.deserialize("01", BigDecimal.class); + fail(); + } catch (JsonException e) { + } +*/ } public void test_max_int() throws IOException { @@ -116,7 +149,9 @@ private int parseInt(String input) throws IOException { return iter.readInt(); } else { JsonIterator iter = JsonIterator.parse(input); - return iter.readInt(); + int v = iter.readInt(); + assertEquals(input.length(), iter.head); // iterator head should point on next non-parsed byte + return v; } } @@ -126,7 +161,9 @@ private long parseLong(String input) throws IOException { return iter.readLong(); } else { JsonIterator iter = JsonIterator.parse(input); - return iter.readLong(); + long v = iter.readLong(); + assertEquals(input.length(), iter.head); // iterator head should point on next non-parsed byte + return v; } } }