diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index d5b08eb7..52ea55d7 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -244,3 +244,9 @@ Peter Haumer (phaumer@github) * Reported #404: (yaml) Cannot serialize YAML with Deduction-Based Polymorphism (2.15.1) + +Arthur Chan (arthurscchan@github) + +* Contributed fix for #445: `YAMLParser` throws unexpected `NullPointerException` in certain + number parsing cases + (2.16.1) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 8546b8f7..9906fd12 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -18,6 +18,12 @@ Active Maintainers: - +2.16.1 (not yet released) + +#445: `YAMLParser` throws unexpected `NullPointerException` in certain + number parsing cases + (fix contributed by Arthur C) + 2.16.0 (15-Nov-2023) #198: (csv) Support writing numbers as quoted Strings with diff --git a/yaml/src/main/java/tools/jackson/dataformat/yaml/YAMLParser.java b/yaml/src/main/java/tools/jackson/dataformat/yaml/YAMLParser.java index e85e1fcd..ab761643 100644 --- a/yaml/src/main/java/tools/jackson/dataformat/yaml/YAMLParser.java +++ b/yaml/src/main/java/tools/jackson/dataformat/yaml/YAMLParser.java @@ -920,10 +920,18 @@ public Object getNumberValueDeferred() throws JacksonException { // due to refactoring. So let's try to cobble something together if (_currToken == JsonToken.VALUE_NUMBER_INT) { - // For integrals, use eager decoding for all ints, longs (and - // some cheaper BigIntegers) - if (_cleanedTextValue.length() <= 18) { - return getNumberValue(); + // We might already have suitable value? + if ((_numTypesValid & NR_INT) != 0) { + return _numberInt; + } + if ((_numTypesValid & NR_LONG) != 0) { + return _numberLong; + } + if ((_numTypesValid & NR_BIGINT) != 0) { + return _getBigInteger(); + } + if (_cleanedTextValue == null) { + _reportError("Internal number decoding error: `_cleanedTextValue` null when nothing decoded for `JsonToken.VALUE_NUMBER_INT`"); } return _cleanedTextValue; } diff --git a/yaml/src/test/java/tools/jackson/dataformat/yaml/deser/FuzzYAMLReadTest.java b/yaml/src/test/java/tools/jackson/dataformat/yaml/deser/FuzzYAMLReadTest.java index f78dea8e..65e47387 100644 --- a/yaml/src/test/java/tools/jackson/dataformat/yaml/deser/FuzzYAMLReadTest.java +++ b/yaml/src/test/java/tools/jackson/dataformat/yaml/deser/FuzzYAMLReadTest.java @@ -1,5 +1,9 @@ package tools.jackson.dataformat.yaml.deser; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import tools.jackson.core.JacksonException; import tools.jackson.core.JsonToken; import tools.jackson.core.exc.StreamReadException; @@ -88,4 +92,28 @@ public void testNumberDecoding61823() throws Exception verifyException(e, "Invalid number"); } } + + // [dataformats-text#445]: NPE + static class ModelContainer445 + { + public String string; + + @JsonCreator + public ModelContainer445(@JsonProperty(value = "string") String string) { + this.string = string; + } + } + + // [dataformats-text#445]: NPE + // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=64662 + public void testNullPointerException445_64662() throws Exception + { + // Content itself odd, generated by Fuzz; but needs to trigger buffering to work + try { + YAML_MAPPER.readValue(" :: ! 0000000000000000000000000000", ModelContainer445.class); + fail("Should not pass"); + } catch (JacksonException e) { + verifyException(e, "Unrecognized property"); + } + } }