Skip to content

Commit fb1d64c

Browse files
authored
try to log specific message when positive sign appears (#776)
1 parent ab89bf2 commit fb1d64c

File tree

4 files changed

+66
-39
lines changed

4 files changed

+66
-39
lines changed

src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -777,11 +777,11 @@ public final JsonToken nextToken() throws IOException
777777
break;
778778

779779
case '-':
780-
t = _parsePossibleNumber(true);
780+
t = _parseSignedNumber(true);
781781
break;
782782
case '+':
783783
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
784-
t = _parsePossibleNumber(false);
784+
t = _parseSignedNumber(false);
785785
} else {
786786
t = _handleOddValue(i);
787787
}
@@ -980,11 +980,11 @@ public String nextFieldName() throws IOException
980980

981981
switch (i) {
982982
case '-':
983-
t = _parsePossibleNumber(true);
983+
t = _parseSignedNumber(true);
984984
break;
985985
case '+':
986986
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
987-
t = _parsePossibleNumber(false);
987+
t = _parseSignedNumber(false);
988988
} else {
989989
t = _handleOddValue(i);
990990
}
@@ -1059,11 +1059,11 @@ private final void _isNextTokenNameYes(int i) throws IOException
10591059
_nextToken = JsonToken.VALUE_NULL;
10601060
return;
10611061
case '-':
1062-
_nextToken = _parsePossibleNumber(true);
1062+
_nextToken = _parseSignedNumber(true);
10631063
return;
10641064
case '+':
10651065
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
1066-
_nextToken = _parsePossibleNumber(false);
1066+
_nextToken = _parseSignedNumber(false);
10671067
} else {
10681068
_nextToken = _handleOddValue(i);
10691069
}
@@ -1104,11 +1104,11 @@ protected boolean _isNextTokenNameMaybe(int i, String nameToMatch) throws IOExce
11041104
JsonToken t;
11051105
switch (i) {
11061106
case '-':
1107-
t = _parsePossibleNumber(true);
1107+
t = _parseSignedNumber(true);
11081108
break;
11091109
case '+':
11101110
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
1111-
t = _parsePossibleNumber(false);
1111+
t = _parseSignedNumber(false);
11121112
} else {
11131113
t = _handleOddValue(i);
11141114
}
@@ -1177,7 +1177,7 @@ private final JsonToken _nextTokenNotInObject(int i) throws IOException
11771177
_matchToken("null", 1);
11781178
return (_currToken = JsonToken.VALUE_NULL);
11791179
case '-':
1180-
return (_currToken = _parsePossibleNumber(true));
1180+
return (_currToken = _parseSignedNumber(true));
11811181
/* Should we have separate handling for plus? Although
11821182
* it is not allowed per se, it may be erroneously used,
11831183
* and could be indicated by a more specific error message.
@@ -1477,7 +1477,7 @@ private final JsonToken _parseFloat(int ch, int startPtr, int ptr, boolean neg,
14771477
return resetFloat(neg, intLen, fractLen, expLen);
14781478
}
14791479

1480-
private final JsonToken _parsePossibleNumber(final boolean negative) throws IOException
1480+
private final JsonToken _parseSignedNumber(final boolean negative) throws IOException
14811481
{
14821482
int ptr = _inputPtr;
14831483
int startPtr = negative ? ptr-1 : ptr; // to include sign/digit already read
@@ -1493,7 +1493,7 @@ private final JsonToken _parsePossibleNumber(final boolean negative) throws IOEx
14931493
if (ch == INT_PERIOD) {
14941494
return _parseFloatThatStartsWithPeriod();
14951495
}
1496-
return _handleInvalidNumberStart(ch, negative);
1496+
return _handleInvalidNumberStart(ch, negative, true);
14971497
}
14981498
// One special case, leading zero(es):
14991499
if (ch == INT_0) {
@@ -1722,6 +1722,11 @@ private char _verifyNLZ2() throws IOException
17221722
// Method called if expected numeric value (due to leading sign) does not
17231723
// look like a number
17241724
protected JsonToken _handleInvalidNumberStart(int ch, boolean negative) throws IOException
1725+
{
1726+
return _handleInvalidNumberStart(ch, negative, false);
1727+
}
1728+
1729+
protected JsonToken _handleInvalidNumberStart(int ch, final boolean negative, final boolean hasSign) throws IOException
17251730
{
17261731
if (ch == 'I') {
17271732
if (_inputPtr >= _inputEnd) {
@@ -1746,6 +1751,9 @@ protected JsonToken _handleInvalidNumberStart(int ch, boolean negative) throws I
17461751
_reportError("Non-standard token '"+match+"': enable `JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS` to allow");
17471752
}
17481753
}
1754+
if (!isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature()) && hasSign && !negative) {
1755+
reportUnexpectedNumberChar('+', "JSON spec does not allow numbers to have plus signs: enable `JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS` to allow");
1756+
}
17491757
reportUnexpectedNumberChar(ch, "expected digit (0-9) to follow minus sign, for valid numeric value");
17501758
return null;
17511759
}
@@ -2026,7 +2034,7 @@ protected JsonToken _handleOddValue(int i) throws IOException
20262034
_reportInvalidEOFInValue(JsonToken.VALUE_NUMBER_INT);
20272035
}
20282036
}
2029-
return _handleInvalidNumberStart(_inputBuffer[_inputPtr++], false);
2037+
return _handleInvalidNumberStart(_inputBuffer[_inputPtr++], false, true);
20302038
}
20312039
// [core#77] Try to decode most likely token
20322040
if (Character.isJavaIdentifierStart(i)) {

src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,15 +1082,15 @@ protected JsonToken _parsePosNumber(int c) throws IOException
10821082

10831083
protected final JsonToken _parsePosNumber() throws IOException
10841084
{
1085-
return _parsePossibleNumber(false);
1085+
return _parseSignedNumber(false);
10861086
}
10871087

10881088
protected final JsonToken _parseNegNumber() throws IOException
10891089
{
1090-
return _parsePossibleNumber(true);
1090+
return _parseSignedNumber(true);
10911091
}
10921092

1093-
private final JsonToken _parsePossibleNumber(boolean negative) throws IOException
1093+
private final JsonToken _parseSignedNumber(boolean negative) throws IOException
10941094
{
10951095
char[] outBuf = _textBuffer.emptyAndGetCurrentSegment();
10961096
int outPtr = 0;
@@ -1109,11 +1109,11 @@ private final JsonToken _parsePossibleNumber(boolean negative) throws IOExceptio
11091109
} else if (c == INT_PERIOD) {
11101110
return _parseFloatThatStartsWithPeriod();
11111111
} else {
1112-
return _handleInvalidNumberStart(c, negative);
1112+
return _handleInvalidNumberStart(c, negative, true);
11131113
}
11141114
} else {
11151115
if (c > INT_9) {
1116-
return _handleInvalidNumberStart(c, negative);
1116+
return _handleInvalidNumberStart(c, negative, true);
11171117
}
11181118
c = _inputData.readUnsignedByte();
11191119
}
@@ -2143,7 +2143,7 @@ protected JsonToken _handleUnexpectedValue(int c)
21432143
_reportError("Non-standard token 'Infinity': enable `JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS` to allow");
21442144
break;
21452145
case '+': // note: '-' is taken as number
2146-
return _handleInvalidNumberStart(_inputData.readUnsignedByte(), false);
2146+
return _handleInvalidNumberStart(_inputData.readUnsignedByte(), false, true);
21472147
}
21482148
// [core#77] Try to decode most likely token
21492149
if (Character.isJavaIdentifierStart(c)) {
@@ -2234,8 +2234,12 @@ protected JsonToken _handleApos() throws IOException
22342234
* Method called if expected numeric value (due to leading sign) does not
22352235
* look like a number
22362236
*/
2237-
protected JsonToken _handleInvalidNumberStart(int ch, boolean neg)
2238-
throws IOException
2237+
protected JsonToken _handleInvalidNumberStart(int ch, final boolean neg) throws IOException
2238+
{
2239+
return _handleInvalidNumberStart(ch, neg, false);
2240+
}
2241+
2242+
protected JsonToken _handleInvalidNumberStart(int ch, final boolean neg, final boolean hasSign) throws IOException
22392243
{
22402244
while (ch == 'I') {
22412245
ch = _inputData.readUnsignedByte();
@@ -2253,6 +2257,9 @@ protected JsonToken _handleInvalidNumberStart(int ch, boolean neg)
22532257
}
22542258
_reportError("Non-standard token '"+match+"': enable `JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS` to allow");
22552259
}
2260+
if (!isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature()) && hasSign && !neg) {
2261+
reportUnexpectedNumberChar('+', "JSON spec does not allow numbers to have plus signs: enable `JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS` to allow");
2262+
}
22562263
reportUnexpectedNumberChar(ch, "expected digit (0-9) to follow minus sign, for valid numeric value");
22572264
return null;
22582265
}

src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -812,11 +812,11 @@ public JsonToken nextToken() throws IOException
812812

813813
switch (i) {
814814
case '-':
815-
t = _parsePossibleNumber(true);
815+
t = _parseSignedNumber(true);
816816
break;
817817
case '+':
818818
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
819-
t = _parsePossibleNumber(false);
819+
t = _parseSignedNumber(false);
820820
} else {
821821
t = _handleUnexpectedValue(i);
822822
}
@@ -885,12 +885,12 @@ private final JsonToken _nextTokenNotInObject(int i) throws IOException
885885
_matchNull();
886886
return (_currToken = JsonToken.VALUE_NULL);
887887
case '-':
888-
return (_currToken = _parsePossibleNumber(true));
888+
return (_currToken = _parseSignedNumber(true));
889889
case '+':
890890
if (!isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
891891
return (_currToken = _handleUnexpectedValue(i));
892892
}
893-
return (_currToken = _parsePossibleNumber(false));
893+
return (_currToken = _parseSignedNumber(false));
894894
case '.': // [core#611]:
895895
return (_currToken = _parseFloatThatStartsWithPeriod());
896896
case '0':
@@ -1092,11 +1092,11 @@ public String nextFieldName() throws IOException
10921092
JsonToken t;
10931093
switch (i) {
10941094
case '-':
1095-
t = _parsePossibleNumber(true);
1095+
t = _parseSignedNumber(true);
10961096
break;
10971097
case '+':
10981098
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
1099-
t = _parsePossibleNumber(false);
1099+
t = _parseSignedNumber(false);
11001100
} else {
11011101
t = _handleUnexpectedValue(i);
11021102
}
@@ -1220,11 +1220,11 @@ private final void _isNextTokenNameYes(int i) throws IOException
12201220
_nextToken = JsonToken.VALUE_NULL;
12211221
return;
12221222
case '-':
1223-
_nextToken = _parsePossibleNumber(true);
1223+
_nextToken = _parseSignedNumber(true);
12241224
return;
12251225
case '+':
12261226
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
1227-
_nextToken = _parsePossibleNumber(false);
1227+
_nextToken = _parseSignedNumber(false);
12281228
} else {
12291229
_nextToken = _handleUnexpectedValue(i);
12301230
}
@@ -1287,11 +1287,11 @@ private final boolean _isNextTokenNameMaybe(int i, SerializableString str) throw
12871287
t = JsonToken.VALUE_NULL;
12881288
break;
12891289
case '-':
1290-
t = _parsePossibleNumber(true);
1290+
t = _parseSignedNumber(true);
12911291
break;
12921292
case '+':
12931293
if (isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature())) {
1294-
t = _parsePossibleNumber(false);
1294+
t = _parseSignedNumber(false);
12951295
} else {
12961296
t = _handleUnexpectedValue(i);
12971297
}
@@ -1503,7 +1503,7 @@ protected JsonToken _parsePosNumber(int c) throws IOException
15031503
return resetInt(false, intLen);
15041504
}
15051505

1506-
private final JsonToken _parsePossibleNumber(boolean negative) throws IOException
1506+
private final JsonToken _parseSignedNumber(boolean negative) throws IOException
15071507
{
15081508
char[] outBuf = _textBuffer.emptyAndGetCurrentSegment();
15091509
int outPtr = 0;
@@ -1524,11 +1524,11 @@ private final JsonToken _parsePossibleNumber(boolean negative) throws IOExceptio
15241524
if (c == INT_PERIOD) {
15251525
return _parseFloatThatStartsWithPeriod();
15261526
}
1527-
return _handleInvalidNumberStart(c, negative);
1527+
return _handleInvalidNumberStart(c, negative, true);
15281528
}
15291529
c = _verifyNoLeadingZeroes();
15301530
} else if (c > INT_9) {
1531-
return _handleInvalidNumberStart(c, negative);
1531+
return _handleInvalidNumberStart(c, negative, true);
15321532
}
15331533

15341534
// Ok: we can first just add digit we saw first:
@@ -2761,7 +2761,7 @@ protected JsonToken _handleUnexpectedValue(int c) throws IOException
27612761
_reportInvalidEOFInValue(JsonToken.VALUE_NUMBER_INT);
27622762
}
27632763
}
2764-
return _handleInvalidNumberStart(_inputBuffer[_inputPtr++] & 0xFF, false);
2764+
return _handleInvalidNumberStart(_inputBuffer[_inputPtr++] & 0xFF, false, true);
27652765
}
27662766
// [core#77] Try to decode most likely token
27672767
if (Character.isJavaIdentifierStart(c)) {
@@ -2870,7 +2870,12 @@ protected JsonToken _handleApos() throws IOException
28702870

28712871
// Method called if expected numeric value (due to leading sign) does not
28722872
// look like a number
2873-
protected JsonToken _handleInvalidNumberStart(int ch, boolean neg) throws IOException
2873+
protected JsonToken _handleInvalidNumberStart(int ch, final boolean neg) throws IOException
2874+
{
2875+
return _handleInvalidNumberStart(ch, neg, false);
2876+
}
2877+
2878+
protected JsonToken _handleInvalidNumberStart(int ch, final boolean neg, final boolean hasSign) throws IOException
28742879
{
28752880
while (ch == 'I') {
28762881
if (_inputPtr >= _inputEnd) {
@@ -2894,6 +2899,9 @@ protected JsonToken _handleInvalidNumberStart(int ch, boolean neg) throws IOExce
28942899
_reportError("Non-standard token '%s': enable `JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS` to allow",
28952900
match);
28962901
}
2902+
if (!isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature()) && hasSign && !neg) {
2903+
reportUnexpectedNumberChar('+', "JSON spec does not allow numbers to have plus signs: enable `JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS` to allow");
2904+
}
28972905
reportUnexpectedNumberChar(ch, "expected digit (0-9) to follow minus sign, for valid numeric value");
28982906
return null;
28992907
}

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,18 @@ public void testLeadingDotInDecimal() throws Exception {
3737
*/
3838
public void testLeadingPlusSignInDecimal() throws Exception {
3939
for (int mode : ALL_MODES) {
40-
JsonParser p = createParser(mode, " +123 ");
41-
try {
40+
try (JsonParser p = createParser(mode, " +123 ")) {
4241
p.nextToken();
4342
fail("Should not pass");
4443
} catch (JsonParseException e) {
45-
verifyException(e, "expected digit (0-9) to follow minus sign, for valid numeric value");
44+
verifyException(e, "Unexpected character ('+' (code 43)) in numeric value: JSON spec does not allow numbers to have plus signs: enable `JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS` to allow");
45+
}
46+
try (JsonParser p = createParser(mode, " +0.123 ")) {
47+
p.nextToken();
48+
fail("Should not pass");
49+
} catch (JsonParseException e) {
50+
verifyException(e, "Unexpected character ('+' (code 43)) in numeric value: JSON spec does not allow numbers to have plus signs: enable `JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS` to allow");
4651
}
47-
p.close();
4852
}
4953
}
5054

0 commit comments

Comments
 (0)