diff --git a/src/main/java/org/apache/commons/lang3/math/NumberUtils.java b/src/main/java/org/apache/commons/lang3/math/NumberUtils.java index 1e6ccdc02..70b8d6466 100644 --- a/src/main/java/org/apache/commons/lang3/math/NumberUtils.java +++ b/src/main/java/org/apache/commons/lang3/math/NumberUtils.java @@ -464,11 +464,20 @@ public static Number createNumber(final String str) throws NumberFormatException } } if (pfxLen > 0) { // we have a hex number + char firstSigDigit = 0; // strip leading zeroes + for(int i = pfxLen; i < str.length(); i++) { + firstSigDigit = str.charAt(i); + if (firstSigDigit == '0') { // count leading zeroes + pfxLen++; + } else { + break; + } + } final int hexDigits = str.length() - pfxLen; - if (hexDigits > 16) { // too many for Long + if (hexDigits > 16 || (hexDigits == 16 && firstSigDigit > '7')) { // too many for Long return createBigInteger(str); } - if (hexDigits > 8) { // too many for an int + if (hexDigits > 8 || (hexDigits == 8 && firstSigDigit > '7')) { // too many for an int return createLong(str); } return createInteger(str); diff --git a/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java b/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java index 56b0597e7..bdd2a242e 100644 --- a/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java @@ -246,6 +246,43 @@ public void testCreateNumber() { assertEquals(BigDecimal.class, bigNum.getClass()); } + @Test + public void TestLang747() { + assertEquals(Integer.valueOf(0x8000), NumberUtils.createNumber("0x8000")); + assertEquals(Integer.valueOf(0x80000), NumberUtils.createNumber("0x80000")); + assertEquals(Integer.valueOf(0x800000), NumberUtils.createNumber("0x800000")); + assertEquals(Integer.valueOf(0x8000000), NumberUtils.createNumber("0x8000000")); + assertEquals(Integer.valueOf(0x7FFFFFFF), NumberUtils.createNumber("0x7FFFFFFF")); + assertEquals(Long.valueOf(0x80000000L), NumberUtils.createNumber("0x80000000")); + assertEquals(Long.valueOf(0xFFFFFFFFL), NumberUtils.createNumber("0xFFFFFFFF")); + + // Leading zero tests + assertEquals(Integer.valueOf(0x8000000), NumberUtils.createNumber("0x08000000")); + assertEquals(Integer.valueOf(0x7FFFFFFF), NumberUtils.createNumber("0x007FFFFFFF")); + assertEquals(Long.valueOf(0x80000000L), NumberUtils.createNumber("0x080000000")); + assertEquals(Long.valueOf(0xFFFFFFFFL), NumberUtils.createNumber("0x00FFFFFFFF")); + + assertEquals(Long.valueOf(0x800000000L), NumberUtils.createNumber("0x800000000")); + assertEquals(Long.valueOf(0x8000000000L), NumberUtils.createNumber("0x8000000000")); + assertEquals(Long.valueOf(0x80000000000L), NumberUtils.createNumber("0x80000000000")); + assertEquals(Long.valueOf(0x800000000000L), NumberUtils.createNumber("0x800000000000")); + assertEquals(Long.valueOf(0x8000000000000L), NumberUtils.createNumber("0x8000000000000")); + assertEquals(Long.valueOf(0x80000000000000L), NumberUtils.createNumber("0x80000000000000")); + assertEquals(Long.valueOf(0x800000000000000L), NumberUtils.createNumber("0x800000000000000")); + assertEquals(Long.valueOf(0x7FFFFFFFFFFFFFFFL), NumberUtils.createNumber("0x7FFFFFFFFFFFFFFF")); + // N.B. Cannot use a hex constant such as 0x8000000000000000L here as that is interpreted as a negative long + assertEquals(new BigInteger("8000000000000000", 16), NumberUtils.createNumber("0x8000000000000000")); + assertEquals(new BigInteger("FFFFFFFFFFFFFFFF", 16), NumberUtils.createNumber("0xFFFFFFFFFFFFFFFF")); + + // Leading zero tests + assertEquals(Long.valueOf(0x80000000000000L), NumberUtils.createNumber("0x00080000000000000")); + assertEquals(Long.valueOf(0x800000000000000L), NumberUtils.createNumber("0x0800000000000000")); + assertEquals(Long.valueOf(0x7FFFFFFFFFFFFFFFL), NumberUtils.createNumber("0x07FFFFFFFFFFFFFFF")); + // N.B. Cannot use a hex constant such as 0x8000000000000000L here as that is interpreted as a negative long + assertEquals(new BigInteger("8000000000000000", 16), NumberUtils.createNumber("0x00008000000000000000")); + assertEquals(new BigInteger("FFFFFFFFFFFFFFFF", 16), NumberUtils.createNumber("0x0FFFFFFFFFFFFFFFF")); + } + @Test(expected=NumberFormatException.class) // Check that the code fails to create a valid number when preceeded by -- rather than - public void testCreateNumberFailure_1() {