Skip to content

Commit

Permalink
Fixes #1173: column/offset locations wrong for many error conditions (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder authored Dec 28, 2023
1 parent 170b33a commit 0c715d1
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 2 deletions.
5 changes: 5 additions & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -405,3 +405,8 @@ David Schlosnagle (@schlosna)
Mario Fusco (@mariofusco)
* Contributed #1064: Add full set of `BufferRecyclerPool` implementations
(2.16.0)

Paul Bunyan (@hal7df)
* Reported #1173: `JsonLocation` consistently off by one character for many invalid
JSON parsing cases
(2.16.2)
6 changes: 6 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ a pure JSON library.
=== Releases ===
------------------------------------------------------------------------

2.16.2 (not yet released)

#1173: `JsonLocation` consistently off by one character for many invalid JSON
parsing cases
(reported by Paul B)

2.16.1 (24-Dec-2023)

#1141: NPE in `Version.equals()` if snapshot-info `null`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ public final JsonToken nextToken() throws IOException
case '}':
// Error: } is not valid at this point; valid closers have
// been handled earlier
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "expected a value");
case 't':
_matchTrue();
Expand Down Expand Up @@ -1455,6 +1456,7 @@ private final JsonToken _parseFloat(int ch, int startPtr, int ptr, boolean neg,
// must be followed by sequence of ints, one minimum
if (fractLen == 0) {
if (!isEnabled(JsonReadFeature.ALLOW_TRAILING_DECIMAL_POINT_FOR_NUMBERS.mappedFeature())) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(ch, "Decimal point not followed by a digit");
}
}
Expand Down Expand Up @@ -1484,6 +1486,7 @@ private final JsonToken _parseFloat(int ch, int startPtr, int ptr, boolean neg,
}
// must be followed by sequence of ints, one minimum
if (expLen == 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(ch, "Exponent indicator not followed by a digit");
}
}
Expand Down Expand Up @@ -1644,6 +1647,7 @@ private final JsonToken _parseNumber2(boolean neg, int startPtr) throws IOExcept
// must be followed by sequence of ints, one minimum
if (fractLen == 0) {
if (!isEnabled(JsonReadFeature.ALLOW_TRAILING_DECIMAL_POINT_FOR_NUMBERS.mappedFeature())) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(c, "Decimal point not followed by a digit");
}
}
Expand Down Expand Up @@ -1688,6 +1692,7 @@ private final JsonToken _parseNumber2(boolean neg, int startPtr) throws IOExcept
}
// must be followed by sequence of ints, one minimum
if (expLen == 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(c, "Exponent indicator not followed by a digit");
}
}
Expand Down Expand Up @@ -1788,11 +1793,13 @@ protected JsonToken _handleInvalidNumberStart(int ch, final boolean negative, fi
}
}
if (!isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature()) && hasSign && !negative) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar('+', "JSON spec does not allow numbers to have plus signs: enable `JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS` to allow");
}
final String message = negative ?
"expected digit (0-9) to follow minus sign, for valid numeric value" :
"expected digit (0-9) for valid numeric value";
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(ch, message);
return null;
}
Expand Down Expand Up @@ -1940,6 +1947,7 @@ protected String _handleOddName(int i) throws IOException
}
// [JACKSON-69]: allow unquoted names if feature enabled:
if ((_features & FEAT_MASK_ALLOW_UNQUOTED_NAMES) == 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting double-quote to start field name");
}
final int[] codes = CharTypes.getInputCodeLatin1JsNames();
Expand All @@ -1954,6 +1962,7 @@ protected String _handleOddName(int i) throws IOException
firstOk = Character.isJavaIdentifierPart((char) i);
}
if (!firstOk) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting either valid name character (for unquoted name) or double-quote (for quoted) to start field name");
}
int ptr = _inputPtr;
Expand Down Expand Up @@ -2085,6 +2094,7 @@ protected JsonToken _handleOddValue(int i) throws IOException
_reportInvalidToken(""+((char) i), _validJsonTokenList());
}
// but if it doesn't look like a token:
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "expected a valid value "+_validJsonValueList());
return null;
}
Expand Down Expand Up @@ -2387,6 +2397,7 @@ private final int _skipColon2(boolean gotColon) throws IOException
return i;
}
if (i != INT_COLON) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting a colon to separate field name and value");
}
gotColon = true;
Expand Down Expand Up @@ -2460,6 +2471,7 @@ private final int _skipColonFast(int ptr) throws IOException
private final int _skipComma(int i) throws IOException
{
if (i != INT_COMMA) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.typeDesc()+" entries");
}
while (_inputPtr < _inputEnd) {
Expand Down Expand Up @@ -2602,6 +2614,7 @@ private int _skipWSOrEnd2() throws IOException
private void _skipComment() throws IOException
{
if ((_features & FEAT_MASK_ALLOW_JAVA_COMMENTS) == 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)");
}
// First: check which comment (if either) it is:
Expand All @@ -2614,6 +2627,7 @@ private void _skipComment() throws IOException
} else if (c == '*') {
_skipCComment();
} else {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(c, "was expecting either '*' or '/' for a comment");
}
}
Expand Down Expand Up @@ -2725,6 +2739,7 @@ protected char _decodeEscaped() throws IOException
int ch = (int) _inputBuffer[_inputPtr++];
int digit = CharTypes.charToHex(ch);
if (digit < 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(ch, "expected a hex-digit for character escape sequence");
}
value = (value << 4) | digit;
Expand Down Expand Up @@ -3052,6 +3067,7 @@ private void _closeScope(int i) throws JsonParseException {
if (i == INT_RBRACKET) {
_updateLocation();
if (!_parsingContext.inArray()) {
--_inputPtr; // for correct error reporting
_reportMismatchedEndMarker(i, '}');
}
_parsingContext = _parsingContext.clearAndGetParent();
Expand All @@ -3060,6 +3076,7 @@ private void _closeScope(int i) throws JsonParseException {
if (i == INT_RCURLY) {
_updateLocation();
if (!_parsingContext.inObject()) {
--_inputPtr; // for correct error reporting
_reportMismatchedEndMarker(i, ']');
}
_parsingContext = _parsingContext.clearAndGetParent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ public JsonToken nextToken() throws IOException
// Nope: do we then expect a comma?
if (_parsingContext.expectComma()) {
if (i != INT_COMMA) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.typeDesc()+" entries");
}
i = _skipWS();
Expand Down Expand Up @@ -977,6 +978,7 @@ public boolean nextFieldName(SerializableString str) throws IOException
// Nope: do we then expect a comma?
if (_parsingContext.expectComma()) {
if (i != INT_COMMA) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.typeDesc()+" entries");
}
i = _skipWS();
Expand Down Expand Up @@ -1062,6 +1064,7 @@ public String nextFieldName() throws IOException
// Nope: do we then expect a comma?
if (_parsingContext.expectComma()) {
if (i != INT_COMMA) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.typeDesc()+" entries");
}
i = _skipWS();
Expand Down Expand Up @@ -1685,6 +1688,7 @@ private final JsonToken _parseFloat(char[] outBuf, int outPtr, int c,
// must be followed by sequence of ints, one minimum
if (fractLen == 0) {
if (!isEnabled(JsonReadFeature.ALLOW_TRAILING_DECIMAL_POINT_FOR_NUMBERS.mappedFeature())) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(c, "Decimal point not followed by a digit");
}
}
Expand Down Expand Up @@ -1732,6 +1736,7 @@ private final JsonToken _parseFloat(char[] outBuf, int outPtr, int c,
}
// must be followed by sequence of ints, one minimum
if (expLen == 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(c, "Exponent indicator not followed by a digit");
}
}
Expand Down Expand Up @@ -2144,6 +2149,7 @@ protected String _handleOddName(int ch) throws IOException
// Allow unquoted names if feature enabled:
if ((_features & FEAT_MASK_ALLOW_UNQUOTED_NAMES) == 0) {
char c = (char) _decodeCharForError(ch);
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(c, "was expecting double-quote to start field name");
}
/* Also: note that although we use a different table here,
Expand All @@ -2153,6 +2159,7 @@ protected String _handleOddName(int ch) throws IOException
final int[] codes = CharTypes.getInputCodeUtf8JsNames();
// Also: must start with a valid character...
if (codes[ch] != 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(ch, "was expecting either valid name character (for unquoted name) or double-quote (for quoted) to start field name");
}

Expand Down Expand Up @@ -2758,6 +2765,7 @@ protected JsonToken _handleUnexpectedValue(int c) throws IOException
case '}':
// Error: neither is valid at this point; valid closers have
// been handled earlier
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(c, "expected a value");
case '\'':
if ((_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
Expand Down Expand Up @@ -2791,6 +2799,7 @@ protected JsonToken _handleUnexpectedValue(int c) throws IOException
_reportInvalidToken(""+((char) c), _validJsonTokenList());
}
// but if it doesn't look like a token:
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(c, "expected a valid value "+_validJsonValueList());
return null;
}
Expand Down Expand Up @@ -2923,11 +2932,13 @@ protected JsonToken _handleInvalidNumberStart(int ch, final boolean neg, final b
match);
}
if (!isEnabled(JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS.mappedFeature()) && hasSign && !neg) {
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar('+', "JSON spec does not allow numbers to have plus signs: enable `JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS` to allow");
}
final String message = neg ?
"expected digit (0-9) to follow minus sign, for valid numeric value" :
"expected digit (0-9) for valid numeric value";
--_inputPtr; // for correct error reporting
_reportUnexpectedNumberChar(ch, message);
return null;
}
Expand Down Expand Up @@ -3253,6 +3264,7 @@ private final int _skipColon2(boolean gotColon) throws IOException
return i;
}
if (i != INT_COLON) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(i, "was expecting a colon to separate field name and value");
}
gotColon = true;
Expand All @@ -3275,6 +3287,7 @@ private final int _skipColon2(boolean gotColon) throws IOException
private final void _skipComment() throws IOException
{
if ((_features & FEAT_MASK_ALLOW_JAVA_COMMENTS) == 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)");
}
// First: check which comment (if either) it is:
Expand All @@ -3287,6 +3300,7 @@ private final void _skipComment() throws IOException
} else if (c == INT_ASTERISK) {
_skipCComment();
} else {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(c, "was expecting either '*' or '/' for a comment");
}
}
Expand Down Expand Up @@ -3432,6 +3446,7 @@ protected char _decodeEscaped() throws IOException
int ch = _inputBuffer[_inputPtr++];
int digit = CharTypes.charToHex(ch);
if (digit < 0) {
--_inputPtr; // for correct error reporting
_reportUnexpectedChar(ch & 0xFF, "expected a hex-digit for character escape sequence");
}
value = (value << 4) | digit;
Expand Down Expand Up @@ -3923,6 +3938,7 @@ private final JsonToken _closeScope(int i) throws JsonParseException {
private final void _closeArrayScope() throws JsonParseException {
_updateLocation();
if (!_parsingContext.inArray()) {
--_inputPtr; // for correct error reporting
_reportMismatchedEndMarker(']', '}');
}
_parsingContext = _parsingContext.clearAndGetParent();
Expand All @@ -3931,6 +3947,7 @@ private final void _closeArrayScope() throws JsonParseException {
private final void _closeObjectScope() throws JsonParseException {
_updateLocation();
if (!_parsingContext.inObject()) {
--_inputPtr; // for correct error reporting
_reportMismatchedEndMarker('}', ']');
}
_parsingContext = _parsingContext.clearAndGetParent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ protected final JsonToken _startObjectScope() throws IOException
protected final JsonToken _closeArrayScope() throws IOException
{
if (!_parsingContext.inArray()) {
--_inputPtr; // for correct error reporting
_reportMismatchedEndMarker(']', '}');
}
JsonReadContext ctxt = _parsingContext.getParent();
Expand All @@ -617,6 +618,7 @@ protected final JsonToken _closeArrayScope() throws IOException
protected final JsonToken _closeObjectScope() throws IOException
{
if (!_parsingContext.inObject()) {
--_inputPtr; // for correct error reporting
_reportMismatchedEndMarker('}', ']');
}
JsonReadContext ctxt = _parsingContext.getParent();
Expand Down
Loading

0 comments on commit 0c715d1

Please sign in to comment.