]> granicus.if.org Git - icu/commitdiff
ICU-20246 Fixing another integer overflow in number parsing.
authorShane Carr <shane@unicode.org>
Tue, 30 Oct 2018 06:52:44 +0000 (23:52 -0700)
committerShane F. Carr <shane@unicode.org>
Wed, 31 Oct 2018 20:37:09 +0000 (13:37 -0700)
icu4c/source/i18n/fmtable.cpp
icu4c/source/i18n/number_decimalquantity.cpp
icu4c/source/test/intltest/numfmtst.cpp
icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_DualStorageBCD.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java

index 45c7024fc29e30733c7d67a2e23ab30eff4ed5e2..8601d95f4a6ed8490af7e3d259ddb14b830609c8 100644 (file)
@@ -734,7 +734,7 @@ CharString *Formattable::internalGetCharString(UErrorCode &status) {
       // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?).
       if (fDecimalQuantity->isZero()) {
         fDecimalStr->append("0", -1, status);
-      } else if (std::abs(fDecimalQuantity->getMagnitude()) < 5) {
+      } else if (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5) {
         fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status);
       } else {
         fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status);
index 47b930a564bf82f645399115e3c405f42e4dff06..d5dd7ae694c760d78fa66a0d8b7e51bad6b312cf 100644 (file)
@@ -898,7 +898,10 @@ UnicodeString DecimalQuantity::toScientificString() const {
     }
     result.append(u'E');
     int32_t _scale = upperPos + scale;
-    if (_scale < 0) {
+    if (_scale == INT32_MIN) {
+        result.append({u"-2147483648", -1});
+        return result;
+    } else if (_scale < 0) {
         _scale *= -1;
         result.append(u'-');
     } else {
index 34355939113b83738784a00e5be4eb215b19d5c0..8d52dc122bf6ef087498c78ad4f9f1e998360946 100644 (file)
@@ -9226,6 +9226,14 @@ void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
     assertEquals(u"Should not overflow and should parse only the first exponent",
                  u"1E-2147483647",
                  {sp.data(), sp.length(), US_INV});
+
+    // Test edge case overflow of exponent
+    result = Formattable();
+    nf->parse(u".0003e-2147483644", result, status);
+    sp = result.getDecimalNumber(status);
+    assertEquals(u"Should not overflow",
+                 u"3E-2147483648",
+                 {sp.data(), sp.length(), US_INV});
 }
 
 void NumberFormatTest::Test13840_ParseLongStringCrash() {
index f5fb4278e1f2682a11090dc2a219568870380cbf..138c2e9acf7af823d07c2e94dc22ec07047bff93 100644 (file)
@@ -1067,7 +1067,10 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity {
         }
         result.append('E');
         int _scale = upperPos + scale;
-        if (_scale < 0) {
+        if (_scale == Integer.MIN_VALUE) {
+            result.append("-2147483648");
+            return;
+        } else if (_scale < 0) {
             _scale *= -1;
             result.append('-');
         } else {
index 42cc2c48ecf07a82af7c3522236ae325eab728ff..faa46281a1d6c5f8dd05d2281ef6d383f1be10fa 100644 (file)
@@ -239,7 +239,15 @@ public final class DecimalQuantity_DualStorageBCD extends DecimalQuantity_Abstra
                 tempLong = tempLong * 10 + getDigitPos(shift);
             }
             BigDecimal result = BigDecimal.valueOf(tempLong);
-            result = result.scaleByPowerOfTen(scale);
+            try {
+                result = result.scaleByPowerOfTen(scale);
+            } catch (ArithmeticException e) {
+                if (e.getMessage().contains("Underflow")) {
+                    result = BigDecimal.ZERO;
+                } else {
+                    throw e;
+                }
+            }
             if (isNegative())
                 result = result.negate();
             return result;
index ce6b3666aa0b158e016cd60edce01697823c312c..fe0d77cca29db6399ab3d67b75e8ac3451b793ca 100644 (file)
@@ -6325,6 +6325,11 @@ public class NumberFormatTest extends TestFmwk {
         result = nf.parse("1E-547483647");
         assertEquals("Should *not* snap to zero",
                 "1E-547483647", result.toString());
+
+        // Test edge case overflow of exponent
+        result = nf.parse(".0003e-2147483644");
+        assertEquals("Should not overflow",
+                "0", result.toString());
     }
 
     @Test