From 778d0bd1c904617cd9623c0f2b77c8d798051468 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Sat, 16 Mar 2024 22:14:58 +0100 Subject: [PATCH 1/5] fix regression caused by looksLikeValidNumber --- .../java/com/fasterxml/jackson/core/io/NumberInput.java | 4 ++-- .../java/com/fasterxml/jackson/core/io/NumberInputTest.java | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java index 86c73a8986..9ae5b99661 100644 --- a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java +++ b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java @@ -39,7 +39,7 @@ public final class NumberInput * @since 2.17 */ private final static Pattern PATTERN_FLOAT = Pattern.compile( - "[+-]?[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?"); + "[+-]?([0-9]+)?(\\.[0-9]+)?([eE][+-]?[0-9]+)?"); /** * Fast method for parsing unsigned integers that are known to fit into @@ -578,6 +578,6 @@ public static BigInteger parseBigIntegerWithRadix(final String s, final int radi * @since 2.17 */ public static boolean looksLikeValidNumber(final String s) { - return (s != null) && PATTERN_FLOAT.matcher(s).matches(); + return s != null && PATTERN_FLOAT.matcher(s).matches() && !s.trim().isEmpty(); } } diff --git a/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java b/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java index d7634f8eab..16c32d896d 100644 --- a/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java +++ b/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java @@ -70,6 +70,11 @@ public void testLooksLikeValidNumber() assertTrue(NumberInput.looksLikeValidNumber("-1")); assertTrue(NumberInput.looksLikeValidNumber("0001")); // non-JSON + // https://github.com/FasterXML/jackson-databind/issues/4435 + assertTrue(NumberInput.looksLikeValidNumber(".01")); + assertTrue(NumberInput.looksLikeValidNumber("+.01")); + assertTrue(NumberInput.looksLikeValidNumber("-.01")); + assertTrue(NumberInput.looksLikeValidNumber("0.01")); assertTrue(NumberInput.looksLikeValidNumber("-0.10")); assertTrue(NumberInput.looksLikeValidNumber("+0.25")); // non-JSON @@ -84,6 +89,7 @@ public void testLooksLikeValidNumber() assertFalse(NumberInput.looksLikeValidNumber("")); assertFalse(NumberInput.looksLikeValidNumber(" ")); + assertFalse(NumberInput.looksLikeValidNumber(".")); assertFalse(NumberInput.looksLikeValidNumber("10_000")); } } From 610b83e64632d9c4387b70e74bdb8fb8cb76d903 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Sun, 17 Mar 2024 13:02:10 +0100 Subject: [PATCH 2/5] Update NumberInput.java --- src/main/java/com/fasterxml/jackson/core/io/NumberInput.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java index 9ae5b99661..9382b04412 100644 --- a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java +++ b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java @@ -578,6 +578,7 @@ public static BigInteger parseBigIntegerWithRadix(final String s, final int radi * @since 2.17 */ public static boolean looksLikeValidNumber(final String s) { - return s != null && PATTERN_FLOAT.matcher(s).matches() && !s.trim().isEmpty(); + // the PATTERN_FLOAT match returns true for empty strings, so we need to check for digits separately + return s != null && PATTERN_FLOAT.matcher(s).matches() && s.chars().anyMatch(Character::isDigit); } } From eef1918a0dcdfd2389d94845ff7a2ba09f9bfd8c Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 23 Mar 2024 11:33:04 -0700 Subject: [PATCH 3/5] Minor cleanup pre-merge --- release-notes/VERSION-2.x | 5 +++++ .../com/fasterxml/jackson/core/io/NumberInput.java | 14 ++++++++++++-- .../fasterxml/jackson/core/io/NumberInputTest.java | 9 +++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 34bbd09d50..5c29854ff0 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -14,6 +14,11 @@ a pure JSON library. === Releases === ------------------------------------------------------------------------ +2.17.1 (not yet released) + +#1241: Fix `NumberInput.looksLikeValidNumber()` implementation + (contributed by @pjfanning) + 2.17.0 (12-Mar-2024) #507: Add `JsonWriteFeature.ESCAPE_FORWARD_SLASHES` to allow escaping of '/' for diff --git a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java index 9382b04412..8eafdce67e 100644 --- a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java +++ b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java @@ -39,7 +39,7 @@ public final class NumberInput * @since 2.17 */ private final static Pattern PATTERN_FLOAT = Pattern.compile( - "[+-]?([0-9]+)?(\\.[0-9]+)?([eE][+-]?[0-9]+)?"); + "[+-]?[0-9]*[\\.]?[0-9]+([eE][+-]?[0-9]+)?"); /** * Fast method for parsing unsigned integers that are known to fit into @@ -570,6 +570,9 @@ public static BigInteger parseBigIntegerWithRadix(final String s, final int radi *

* Note: no trimming ({@code String.trim()}) nor null checks are performed * on String passed. + *

+ * Note: this method returning {@code true} DOES NOT GUARANTEE String is valid + * number but just that it looks close enough. * * @param s String to validate * @@ -579,6 +582,13 @@ public static BigInteger parseBigIntegerWithRadix(final String s, final int radi */ public static boolean looksLikeValidNumber(final String s) { // the PATTERN_FLOAT match returns true for empty strings, so we need to check for digits separately - return s != null && PATTERN_FLOAT.matcher(s).matches() && s.chars().anyMatch(Character::isDigit); + if (s == null || s.isEmpty()) { + return false; + } + if (s.length() == 1) { + char c = s.charAt(0); + return (c <= '9') && (c >= '0'); + } + return PATTERN_FLOAT.matcher(s).matches(); } } diff --git a/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java b/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java index 639b4175b7..b949718666 100644 --- a/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java +++ b/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java @@ -78,17 +78,24 @@ void looksLikeValidNumber() assertTrue(NumberInput.looksLikeValidNumber("0")); assertTrue(NumberInput.looksLikeValidNumber("1")); assertTrue(NumberInput.looksLikeValidNumber("-1")); + assertTrue(NumberInput.looksLikeValidNumber("+1")); // non-JSON assertTrue(NumberInput.looksLikeValidNumber("0001")); // non-JSON // https://github.com/FasterXML/jackson-databind/issues/4435 + assertTrue(NumberInput.looksLikeValidNumber(".0")); assertTrue(NumberInput.looksLikeValidNumber(".01")); assertTrue(NumberInput.looksLikeValidNumber("+.01")); assertTrue(NumberInput.looksLikeValidNumber("-.01")); + assertTrue(NumberInput.looksLikeValidNumber("-.0")); assertTrue(NumberInput.looksLikeValidNumber("0.01")); assertTrue(NumberInput.looksLikeValidNumber("-0.10")); assertTrue(NumberInput.looksLikeValidNumber("+0.25")); // non-JSON + assertTrue(NumberInput.looksLikeValidNumber("10.33")); + assertTrue(NumberInput.looksLikeValidNumber("-1.39")); + assertTrue(NumberInput.looksLikeValidNumber("+125.0")); // non-JSON + assertTrue(NumberInput.looksLikeValidNumber("1E10")); assertTrue(NumberInput.looksLikeValidNumber("-1E10")); assertTrue(NumberInput.looksLikeValidNumber("1e-10")); @@ -98,8 +105,10 @@ void looksLikeValidNumber() assertTrue(NumberInput.looksLikeValidNumber("1.4e+45")); assertFalse(NumberInput.looksLikeValidNumber("")); + assertFalse(NumberInput.looksLikeValidNumber(" ")); assertFalse(NumberInput.looksLikeValidNumber(" ")); assertFalse(NumberInput.looksLikeValidNumber(".")); + assertFalse(NumberInput.looksLikeValidNumber("0.")); assertFalse(NumberInput.looksLikeValidNumber("10_000")); } } From eaa386882d4f1ca1a56750f725b5c18a5301de7d Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 23 Mar 2024 11:38:56 -0700 Subject: [PATCH 4/5] fix comment --- src/main/java/com/fasterxml/jackson/core/io/NumberInput.java | 2 +- .../java/com/fasterxml/jackson/core/io/NumberInputTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java index 8eafdce67e..bde9e32a63 100644 --- a/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java +++ b/src/main/java/com/fasterxml/jackson/core/io/NumberInput.java @@ -581,7 +581,7 @@ public static BigInteger parseBigIntegerWithRadix(final String s, final int radi * @since 2.17 */ public static boolean looksLikeValidNumber(final String s) { - // the PATTERN_FLOAT match returns true for empty strings, so we need to check for digits separately + // While PATTERN_FLOAT handles most cases we can optimize some simple ones: if (s == null || s.isEmpty()) { return false; } diff --git a/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java b/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java index b949718666..a84251eda3 100644 --- a/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java +++ b/src/test/java/com/fasterxml/jackson/core/io/NumberInputTest.java @@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.*; class NumberInputTest - extends com.fasterxml.jackson.core.JUnit5TestBase + extends com.fasterxml.jackson.core.JUnit5TestBase { @Test void nastySmallDouble() From 1c60872851893a8994bfa7131edcb13e2e67e4fe Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 23 Mar 2024 11:39:28 -0700 Subject: [PATCH 5/5] warnings cleanup --- .../java/com/fasterxml/jackson/core/JUnit5TestBase.java | 1 - .../com/fasterxml/jackson/core/read/TrailingCommasTest.java | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/core/JUnit5TestBase.java b/src/test/java/com/fasterxml/jackson/core/JUnit5TestBase.java index 983c4381cc..0a71c7d41e 100644 --- a/src/test/java/com/fasterxml/jackson/core/JUnit5TestBase.java +++ b/src/test/java/com/fasterxml/jackson/core/JUnit5TestBase.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.core.testsupport.TestSupport; import com.fasterxml.jackson.core.testsupport.ThrottledInputStream; import com.fasterxml.jackson.core.testsupport.ThrottledReader; -import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; diff --git a/src/test/java/com/fasterxml/jackson/core/read/TrailingCommasTest.java b/src/test/java/com/fasterxml/jackson/core/read/TrailingCommasTest.java index afbb68413a..46be006277 100644 --- a/src/test/java/com/fasterxml/jackson/core/read/TrailingCommasTest.java +++ b/src/test/java/com/fasterxml/jackson/core/read/TrailingCommasTest.java @@ -17,9 +17,9 @@ @SuppressWarnings("resource") public class TrailingCommasTest extends JUnit5TestBase { - private JsonFactory factory; - private Set features; - private int mode; + JsonFactory factory; + Set features; + int mode; public void initTrailingCommasTest(int mode, List features) { this.features = new HashSet<>(features);