Skip to content

Commit dae16ea

Browse files
authored
Fix issue where the parser can read back old number state when parsing later numbers (#1391)
1 parent 3ec9738 commit dae16ea

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

Diff for: release-notes/VERSION-2.x

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ a pure JSON library.
1414
=== Releases ===
1515
------------------------------------------------------------------------
1616

17+
2.17.4 (not yet released)
18+
19+
#1391: Fix issue where the parser can read back old number state when
20+
parsing later numbers
21+
(fix contributed by @pjfanning)
22+
1723
2.17.3 (01-Nov-2024)
1824

1925
#1331: Update to FastDoubleParser v1.0.1 to fix `BigDecimal` decoding problem
@@ -23,7 +29,6 @@ a pure JSON library.
2329
#1352: Fix infinite loop due to integer overflow when reading large strings
2430
(reported by Adam J.S)
2531
(fix contributed by @pjfanning)
26-
2732

2833
2.17.2 (05-Jul-2024)
2934

Diff for: src/main/java/com/fasterxml/jackson/core/base/ParserBase.java

+4
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,7 @@ public BigInteger getBigIntegerValue() throws IOException
818818
}
819819
if ((_numTypesValid & NR_BIGINT) == 0) {
820820
convertNumberToBigInteger();
821+
return _numberBigInt;
821822
}
822823
}
823824
return _getBigInteger();
@@ -840,6 +841,7 @@ public float getFloatValue() throws IOException
840841
}
841842
if ((_numTypesValid & NR_FLOAT) == 0) {
842843
convertNumberToFloat();
844+
return _numberFloat;
843845
}
844846
}
845847
return _getNumberFloat();
@@ -854,6 +856,7 @@ public double getDoubleValue() throws IOException
854856
}
855857
if ((_numTypesValid & NR_DOUBLE) == 0) {
856858
convertNumberToDouble();
859+
return _numberDouble;
857860
}
858861
}
859862
return _getNumberDouble();
@@ -868,6 +871,7 @@ public BigDecimal getDecimalValue() throws IOException
868871
}
869872
if ((_numTypesValid & NR_BIGDECIMAL) == 0) {
870873
convertNumberToBigDecimal();
874+
return _numberBigDecimal;
871875
}
872876
}
873877
return _getBigDecimal();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.fasterxml.jackson.core.read;
2+
3+
import java.math.BigDecimal;
4+
import java.math.BigInteger;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
import com.fasterxml.jackson.core.JUnit5TestBase;
9+
import com.fasterxml.jackson.core.JsonParser;
10+
import com.fasterxml.jackson.core.JsonToken;
11+
import com.fasterxml.jackson.core.TokenStreamFactory;
12+
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
15+
class NumberParsingDb4917Test extends JUnit5TestBase
16+
{
17+
private TokenStreamFactory JSON_F = newStreamFactory();
18+
19+
final String INPUT_JSON = a2q("{'decimalHolder':100.00,'number':50}");
20+
21+
// [jackson-databind#4917]
22+
@Test
23+
public void bigDecimal4917Integers() throws Exception
24+
{
25+
for (int mode : ALL_MODES) {
26+
testBigDecimal4917(JSON_F, mode, INPUT_JSON, true, JsonParser.NumberType.BIG_INTEGER);
27+
testBigDecimal4917(JSON_F, mode, INPUT_JSON, true, JsonParser.NumberType.INT);
28+
testBigDecimal4917(JSON_F, mode, INPUT_JSON, true, JsonParser.NumberType.LONG);
29+
}
30+
}
31+
32+
@Test
33+
public void bigDecimal4917Floats() throws Exception
34+
{
35+
for (int mode : ALL_MODES) {
36+
testBigDecimal4917(JSON_F, mode, INPUT_JSON, false, JsonParser.NumberType.DOUBLE);
37+
testBigDecimal4917(JSON_F, mode, INPUT_JSON, true, JsonParser.NumberType.DOUBLE);
38+
testBigDecimal4917(JSON_F, mode, INPUT_JSON, true, JsonParser.NumberType.FLOAT);
39+
testBigDecimal4917(JSON_F, mode, INPUT_JSON, true, JsonParser.NumberType.BIG_DECIMAL);
40+
}
41+
}
42+
43+
private void testBigDecimal4917(final TokenStreamFactory jsonF,
44+
final int mode,
45+
final String json,
46+
final boolean checkFirstNumValues,
47+
final JsonParser.NumberType secondNumTypeCheck) throws Exception
48+
{
49+
// checkFirstNumValues=false reproduces the issue in https://github.com/FasterXML/jackson-databind/issues/4917
50+
// it is useful to check the second number value while requesting different number types
51+
// but the call adjusts state of the parser, so it is better to redo the test and then test w
52+
try (JsonParser p = createParser(jsonF, mode, json)) {
53+
assertToken(JsonToken.START_OBJECT, p.nextToken());
54+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
55+
assertEquals("decimalHolder", p.currentName());
56+
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
57+
assertEquals(JsonParser.NumberType.DOUBLE, p.getNumberType());
58+
if (checkFirstNumValues) {
59+
assertEquals(Double.valueOf(100.0), p.getNumberValueDeferred());
60+
assertEquals(new BigDecimal("100.00"), p.getDecimalValue());
61+
}
62+
assertEquals("100.00", p.getText());
63+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
64+
assertEquals("number", p.currentName());
65+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
66+
assertEquals(JsonParser.NumberType.INT, p.getNumberType());
67+
assertEquals(Integer.valueOf(50), p.getNumberValueDeferred());
68+
if (secondNumTypeCheck == JsonParser.NumberType.BIG_DECIMAL) {
69+
assertEquals(new BigDecimal("50"), p.getDecimalValue());
70+
} else if (secondNumTypeCheck == JsonParser.NumberType.BIG_INTEGER) {
71+
assertEquals(new BigInteger("50"), p.getBigIntegerValue());
72+
} else if (secondNumTypeCheck == JsonParser.NumberType.FLOAT) {
73+
assertEquals(50.0f, p.getFloatValue());
74+
} else if (secondNumTypeCheck == JsonParser.NumberType.LONG) {
75+
assertEquals(50L, p.getLongValue());
76+
} else if (secondNumTypeCheck == JsonParser.NumberType.INT) {
77+
assertEquals(50, p.getIntValue());
78+
} else {
79+
assertEquals(50.0d, p.getDoubleValue());
80+
}
81+
assertEquals(50, p.getIntValue());
82+
assertToken(JsonToken.END_OBJECT, p.nextToken());
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)