Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON "INF" handling question / bug (?) #1405

Open
alzimmermsft opened this issue Feb 26, 2025 · 2 comments
Open

JSON "INF" handling question / bug (?) #1405

alzimmermsft opened this issue Feb 26, 2025 · 2 comments

Comments

@alzimmermsft
Copy link

alzimmermsft commented Feb 26, 2025

If non-numeric numbers are allowed while reading JSON, when the JSON value is exactly INF it results in a parsing exception.

This appears to be due to how ReaderBasedJsonParser._handleOddValue(int) and UTF8StreamJsonParser._handleUnexpectedValue(int) handle I being the integer value passed. When I is the leading character both methods explicitly look for Infinity only, and do not support INF. But if +INF is the JSON value this is handled without exception as both methods call into their internal _handleInvalidNumberStart(int, boolean) method which checks for leading I and then checks for both INF and Infinity.

Here is a small sample application:

public static void main(String[] args) {
    JsonFactory factory = JsonFactory.builder()
        .enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS)
        .build();

    try (JsonParser parser = factory.createParser(new StringReader("INF"))) {
        parser.nextToken();
        System.out.println(parser.getDoubleValue());
    } catch (Exception e) {
        e.printStackTrace();
    }

    try (JsonParser parser = factory.createParser("INF".getBytes(StandardCharsets.UTF_8))) {
        parser.nextToken();
        System.out.println(parser.getDoubleValue());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Both will result in the catch block being triggered and printing out the stack traces. Those will be something along the lines of:

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'INF': was expecting (JSON String, Number (or 'NaN'/'+INF'/'-INF'), Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 4]
	at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2584)
	at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2610)
	at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2618)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:825)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:3017)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2995)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken2(ReaderBasedJsonParser.java:2776)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2754)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue(ReaderBasedJsonParser.java:2035)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:780)
	at org.example.Main.main(Main.java:19)

and

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'INF': was expecting (JSON String, Number (or 'NaN'/'+INF'/'-INF'), Array, Object or token 'null', 'true' or 'false')
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 4]
	at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2584)
	at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2610)
	at com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2618)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:825)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3662)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidToken(UTF8StreamJsonParser.java:3635)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._matchToken2(UTF8StreamJsonParser.java:2976)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._matchToken(UTF8StreamJsonParser.java:2954)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleUnexpectedValue(UTF8StreamJsonParser.java:2733)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:867)
	at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:753)
	at org.example.Main.main(Main.java:26)

It seems a bit odd that Infinity, +Infinity, and -Infinity are supported but only +INF and -INF are supported but INF isn't.

A quick change to ReaderBasedJsonParser._handleOddValue(int) and UTF8StreamJsonParser._handleUnexpectedValue(int) to have I handling be:

case 'I':
    return _handleInvalidNumberStart(c, false);
//    _matchToken("Infinity", 1);
//    if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
//        return resetAsNaN("Infinity", Double.POSITIVE_INFINITY);
//    }
//    _reportError(
//        "Non-standard token 'Infinity': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
//    break;

Allows for INF to be handled without exception. Though I don't know if that change is 100% safe.

@pjfanning
Copy link
Member

code expects +INF or -INF, not INF.

return "(JSON String, Number (or 'NaN'/'+INF'/'-INF'), Array, Object or token 'null', 'true' or 'false')";

@alzimmermsft
Copy link
Author

alzimmermsft commented Feb 26, 2025

Yeah, I think this issue was more a question on why INF isn't supported where Infinity is, as both forms support their leading + and - cases. I stumbled upon this question when adding some tests and blindly added Infinity, +Infinity and -Infinity and the same for the shorthand INF, +INF, and -INF.'

I'm also fine with closing this as Works as expected if no changes should be made to support INF.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants