Uploaded image for project: 'Commons Lang'
  1. Commons Lang
  2. LANG-1645

NumberUtils.createNumber/createBigInteger fails on hexidecimal integers prefixed with +

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 3.12.0
    • 3.13.0
    • lang.math.*
    • None

    Description

      The Java Language Specification allows an optional sign prefix for a number as + or -.

      A + sign before a hex integer is not recognised by createNumber and createBigInteger but is recognised by isCreatable, createInteger and createLong. The two later functions delegate to Java's decode() function that handles an optional leading +.

      The following demonstrates the tests that fail but would pass if the leading '+' is removed.

          @Test
          void testCreatePositiveHexInteger() {
              // Hex is only supported for integers so no test for hex floating point formats
              assertTrue(NumberUtils.isCreatable("+0xF"));
              assertTrue(NumberUtils.isCreatable("+0xFFFFFFFF"));
              assertTrue(NumberUtils.isCreatable("+0xFFFFFFFFFFFFFFFFF"));
      
              assertEquals(Integer.decode("+0xF"), NumberUtils.createInteger("+0xF"));
              assertEquals(Long.decode("+0xFFFFFFFF"), NumberUtils.createLong("+0xFFFFFFFF"));
      
              assertEquals(new BigInteger("+FFFFFFFFFFFFFFFF", 16),
                           NumberUtils.createBigInteger("0xFFFFFFFFFFFFFFFF"));
              try {
                  assertEquals(new BigInteger("+FFFFFFFFFFFFFFFF", 16),
                               NumberUtils.createBigInteger("+0xFFFFFFFFFFFFFFFF"));
                  Assertions.fail("This should be possible but it is not");
              } catch (NumberFormatException ex) {
                  // This should not happen
              }
      
              assertEquals(Integer.decode("+0xF"),
                           NumberUtils.createNumber("0xF"));
              try {
                  assertEquals(Integer.decode("+0xF"),
                               NumberUtils.createNumber("+0xF"));
                  Assertions.fail("This should be possible but it is not");
              } catch (NumberFormatException ex) {
                  // This should not happen
              }
      
              assertEquals(Long.decode("+0xFFFFFFFF"),
                           NumberUtils.createNumber("0xFFFFFFFF"));
              try {
                  assertEquals(Long.decode("+0xFFFFFFFF"),
                               NumberUtils.createNumber("+0xFFFFFFFF"));
                  Assertions.fail("This should be possible but it is not");
              } catch (NumberFormatException ex) {
                  // This should not happen
              }
      
              assertEquals(new BigInteger("+FFFFFFFFFFFFFFFF", 16),
                           NumberUtils.createNumber("0xFFFFFFFFFFFFFFFF"));
              try {
                  assertEquals(new BigInteger("+FFFFFFFFFFFFFFFF", 16),
                               NumberUtils.createNumber("+0xFFFFFFFFFFFFFFFF"));
                  Assertions.fail("This should be possible but it is not");
              } catch (NumberFormatException ex) {
                  // This should not happen
              }
          }
      

      A simple fix is to check for a leading '+' character and advance all processing past this character.
       

      Attachments

        Activity

          People

            aherbert Alex Herbert
            aherbert Alex Herbert
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0h
                0h
                Logged:
                Time Spent - 0.5h
                0.5h