Skip to content

Commit 65e6540

Browse files
committed
Merge branch '2.9' into 2.10
2 parents 51c63d3 + b6c54cf commit 65e6540

File tree

4 files changed

+165
-40
lines changed

4 files changed

+165
-40
lines changed

release-notes/VERSION-2.x

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ JSON library.
2222
#484: Implement `UTF8JsonGenerator.writeRawValue(SerializableString)` (and
2323
`writeRaw(..)`) more efficiently
2424

25-
2.9.7 (not yet released)
25+
2.9.7 (19-Sep-2018)
2626

2727
#476: Problem with `BufferRecycler` via async parser (or when sharing parser
2828
across threads)

src/main/java/com/fasterxml/jackson/core/base/ParserBase.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ private void _parseSlowFloat(int expType) throws IOException
827827
_wrapError("Malformed numeric value '"+_textBuffer.contentsAsString()+"'", nex);
828828
}
829829
}
830-
830+
831831
private void _parseSlowInt(int expType) throws IOException
832832
{
833833
String numStr = _textBuffer.contentsAsString();
@@ -844,16 +844,42 @@ private void _parseSlowInt(int expType) throws IOException
844844
_numberLong = Long.parseLong(numStr);
845845
_numTypesValid = NR_LONG;
846846
} else {
847-
// nope, need the heavy guns... (rare case)
848-
_numberBigInt = new BigInteger(numStr);
849-
_numTypesValid = NR_BIGINT;
847+
// 16-Oct-2018, tatu: Need to catch "too big" early due to [jackson-core#488]
848+
if ((expType == NR_INT) || (expType == NR_LONG)) {
849+
_reportTooLongInt(expType, numStr);
850+
}
851+
if ((expType == NR_DOUBLE) || (expType == NR_FLOAT)) {
852+
_numberDouble = NumberInput.parseDouble(numStr);
853+
_numTypesValid = NR_DOUBLE;
854+
} else {
855+
// nope, need the heavy guns... (rare case)
856+
_numberBigInt = new BigInteger(numStr);
857+
_numTypesValid = NR_BIGINT;
858+
}
850859
}
851860
} catch (NumberFormatException nex) {
852861
// Can this ever occur? Due to overflow, maybe?
853862
_wrapError("Malformed numeric value '"+numStr+"'", nex);
854863
}
855864
}
856-
865+
866+
// @since 2.9.8
867+
protected void _reportTooLongInt(int expType, String rawNum) throws IOException
868+
{
869+
int rawLen = rawNum.length();
870+
final String numDesc;
871+
if (rawLen < 1000) {
872+
numDesc = rawNum;
873+
} else {
874+
if (rawNum.startsWith("-")) {
875+
rawLen -= 1;
876+
}
877+
numDesc = String.format("[Integer with %d digits]", rawLen);
878+
}
879+
_reportError("Numeric value (%s) out of range of %s", numDesc,
880+
(expType == NR_LONG) ? "long" : "int");
881+
}
882+
857883
/*
858884
/**********************************************************
859885
/* Numeric conversions
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.fasterxml.jackson.core.read;
2+
3+
import java.math.BigInteger;
4+
5+
import com.fasterxml.jackson.core.*;
6+
7+
public class NumberOverflowTest
8+
extends com.fasterxml.jackson.core.BaseTest
9+
{
10+
private final JsonFactory FACTORY = new JsonFactory();
11+
12+
// NOTE: this should be long enough to trigger perf problems
13+
private final static int BIG_NUM_LEN = 199999;
14+
private final static String BIG_POS_INTEGER;
15+
static {
16+
StringBuilder sb = new StringBuilder(BIG_NUM_LEN);
17+
for (int i = 0; i < BIG_NUM_LEN; ++i) {
18+
sb.append('9');
19+
}
20+
BIG_POS_INTEGER = sb.toString();
21+
}
22+
23+
private final static String BIG_POS_DOC = "["+BIG_POS_INTEGER+"]";
24+
private final static String BIG_NEG_DOC = "[ -"+BIG_POS_INTEGER+"]";
25+
26+
public void testSimpleLongOverflow() throws Exception
27+
{
28+
BigInteger below = BigInteger.valueOf(Long.MIN_VALUE);
29+
below = below.subtract(BigInteger.ONE);
30+
BigInteger above = BigInteger.valueOf(Long.MAX_VALUE);
31+
above = above.add(BigInteger.ONE);
32+
33+
String DOC_BELOW = below.toString() + " ";
34+
String DOC_ABOVE = below.toString() + " ";
35+
36+
for (int mode : ALL_MODES) {
37+
JsonParser p = createParser(FACTORY, mode, DOC_BELOW);
38+
p.nextToken();
39+
try {
40+
long x = p.getLongValue();
41+
fail("Expected an exception for underflow (input "+p.getText()+"): instead, got long value: "+x);
42+
} catch (JsonParseException e) {
43+
verifyException(e, "out of range of long");
44+
}
45+
p.close();
46+
47+
p = createParser(mode, DOC_ABOVE);
48+
p.nextToken();
49+
try {
50+
long x = p.getLongValue();
51+
fail("Expected an exception for underflow (input "+p.getText()+"): instead, got long value: "+x);
52+
} catch (JsonParseException e) {
53+
verifyException(e, "out of range of long");
54+
}
55+
p.close();
56+
57+
}
58+
}
59+
60+
// Note: only 4 cardinal types; `short`, `byte` and `char` use same code paths
61+
// Note: due to [jackson-core#493], we'll skip DataInput-backed parser
62+
63+
// [jackson-core#488]
64+
public void testMaliciousLongOverflow() throws Exception
65+
{
66+
for (int mode : ALL_STREAMING_MODES) {
67+
for (String doc : new String[] { BIG_POS_DOC, BIG_NEG_DOC }) {
68+
JsonParser p = createParser(mode, doc);
69+
assertToken(JsonToken.START_ARRAY, p.nextToken());
70+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
71+
try {
72+
p.getLongValue();
73+
fail("Should not pass");
74+
} catch (JsonParseException e) {
75+
verifyException(e, "out of range of long");
76+
verifyException(e, "Integer with "+BIG_NUM_LEN+" digits");
77+
}
78+
p.close();
79+
}
80+
}
81+
}
82+
83+
// [jackson-core#488]
84+
public void testMaliciousIntOverflow() throws Exception
85+
{
86+
for (int mode : ALL_STREAMING_MODES) {
87+
for (String doc : new String[] { BIG_POS_DOC, BIG_NEG_DOC }) {
88+
JsonParser p = createParser(mode, doc);
89+
assertToken(JsonToken.START_ARRAY, p.nextToken());
90+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
91+
try {
92+
p.getIntValue();
93+
fail("Should not pass");
94+
} catch (JsonParseException e) {
95+
verifyException(e, "out of range of int");
96+
verifyException(e, "Integer with "+BIG_NUM_LEN+" digits");
97+
}
98+
p.close();
99+
}
100+
}
101+
}
102+
103+
// [jackson-core#488]
104+
public void testMaliciousBigIntToDouble() throws Exception
105+
{
106+
for (int mode : ALL_STREAMING_MODES) {
107+
final String doc = BIG_POS_DOC;
108+
JsonParser p = createParser(mode, doc);
109+
assertToken(JsonToken.START_ARRAY, p.nextToken());
110+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
111+
double d = p.getDoubleValue();
112+
assertEquals(Double.valueOf(BIG_POS_INTEGER), d);
113+
assertToken(JsonToken.END_ARRAY, p.nextToken());
114+
p.close();
115+
}
116+
}
117+
118+
// [jackson-core#488]
119+
public void testMaliciousBigIntToFloat() throws Exception
120+
{
121+
for (int mode : ALL_STREAMING_MODES) {
122+
final String doc = BIG_POS_DOC;
123+
JsonParser p = createParser(mode, doc);
124+
assertToken(JsonToken.START_ARRAY, p.nextToken());
125+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
126+
float f = p.getFloatValue();
127+
assertEquals(Float.valueOf(BIG_POS_INTEGER), f);
128+
assertToken(JsonToken.END_ARRAY, p.nextToken());
129+
p.close();
130+
}
131+
}
132+
}

src/test/java/com/fasterxml/jackson/core/read/NumberParsingTest.java

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public void testSimpleLong() throws Exception
109109
_testSimpleLong(MODE_READER);
110110
_testSimpleLong(MODE_DATA_INPUT);
111111
}
112-
112+
113113
private void _testSimpleLong(int mode) throws Exception
114114
{
115115
long EXP_L = 12345678907L;
@@ -310,39 +310,6 @@ private void _testNumbers(int mode) throws Exception
310310
p.close();
311311
}
312312

313-
public void testLongOverflow() throws Exception
314-
{
315-
BigInteger below = BigInteger.valueOf(Long.MIN_VALUE);
316-
below = below.subtract(BigInteger.ONE);
317-
BigInteger above = BigInteger.valueOf(Long.MAX_VALUE);
318-
above = above.add(BigInteger.ONE);
319-
320-
String DOC_BELOW = below.toString() + " ";
321-
String DOC_ABOVE = below.toString() + " ";
322-
323-
for (int mode : ALL_MODES) {
324-
JsonParser p = createParser(mode, DOC_BELOW);
325-
p.nextToken();
326-
try {
327-
long x = p.getLongValue();
328-
fail("Expected an exception for underflow (input "+p.getText()+"): instead, got long value: "+x);
329-
} catch (JsonParseException e) {
330-
verifyException(e, "out of range of long");
331-
}
332-
p.close();
333-
334-
p = createParser(mode, DOC_ABOVE);
335-
p.nextToken();
336-
try {
337-
long x = p.getLongValue();
338-
fail("Expected an exception for underflow (input "+p.getText()+"): instead, got long value: "+x);
339-
} catch (JsonParseException e) {
340-
verifyException(e, "out of range of long");
341-
}
342-
p.close();
343-
344-
}
345-
}
346313

347314
/**
348315
* Method that tries to test that number parsing works in cases where

0 commit comments

Comments
 (0)