diff --git a/src/main/java/org/apache/commons/cli/Converter.java b/src/main/java/org/apache/commons/cli/Converter.java index fcb9c43b5..7b684c9a6 100644 --- a/src/main/java/org/apache/commons/cli/Converter.java +++ b/src/main/java/org/apache/commons/cli/Converter.java @@ -17,6 +17,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more package org.apache.commons.cli; import java.io.File; +import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.InvalidPathException; @@ -60,7 +61,16 @@ public interface Converter { /** * Converts a String to a {@link Number}. Converts to a Double if a decimal point ('.') is in the string or a Long otherwise. */ - Converter NUMBER = s -> s.indexOf('.') != -1 ? (Number) Double.valueOf(s) : (Number) Long.valueOf(s); + Converter NUMBER = s -> { + if (s.indexOf('.') != -1) { + // Double.valueOf() also accepts hexadecimal floating point (0x1.8p1), type suffixes (1.0d, 1.0f) + // and surrounding whitespace; validate with a strict BigDecimal parse so those are rejected like + // the Long branch already rejects them. + new BigDecimal(s); + return Double.valueOf(s); + } + return Long.valueOf(s); + }; /** * Converts a class name to an instance of the class. Uses the Class converter to find the class and then call the default constructor. diff --git a/src/test/java/org/apache/commons/cli/ConverterTests.java b/src/test/java/org/apache/commons/cli/ConverterTests.java index 1f5efad55..f47838e22 100644 --- a/src/test/java/org/apache/commons/cli/ConverterTests.java +++ b/src/test/java/org/apache/commons/cli/ConverterTests.java @@ -56,9 +56,15 @@ private static Stream numberTestParameters() { lst.add(Arguments.of("-12.3", Double.valueOf("-12.3"))); lst.add(Arguments.of(".3", Double.valueOf("0.3"))); lst.add(Arguments.of("-.3", Double.valueOf("-0.3"))); + lst.add(Arguments.of("1.2e3", Double.valueOf("1.2e3"))); lst.add(Arguments.of("0x5F", null)); lst.add(Arguments.of("2,3", null)); lst.add(Arguments.of("1.2.3", null)); + // Double.valueOf() accepts these, but a decimal number does not; the Long branch already rejects the same junk. + lst.add(Arguments.of("1.0d", null)); + lst.add(Arguments.of("1.0f", null)); + lst.add(Arguments.of("0x1.8p1", null)); + lst.add(Arguments.of(" 1.2 ", null)); return lst.stream(); }