CVE: CVE-2018-18928
Upstream-Status: Backport
Signed-off-by: Ross Burton <ross.burton@intel.com>

From 53d8c8f3d181d87a6aa925b449b51c4a2c922a51 Mon Sep 17 00:00:00 2001
From: Shane Carr <shane@unicode.org>
Date: Mon, 29 Oct 2018 23:52:44 -0700
Subject: [PATCH] ICU-20246 Fixing another integer overflow in number parsing.

---
 i18n/fmtable.cpp                          |  2 +-
 i18n/number_decimalquantity.cpp           |  5 ++++-
 test/intltest/numfmtst.cpp                |  8 ++++++++
 6 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/i18n/fmtable.cpp b/i18n/fmtable.cpp
index 45c7024fc29..8601d95f4a6 100644
--- a/i18n/fmtable.cpp
+++ b/i18n/fmtable.cpp
@@ -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);
diff --git a/i18n/number_decimalquantity.cpp b/i18n/number_decimalquantity.cpp
index 47b930a564b..d5dd7ae694c 100644
--- a/i18n/number_decimalquantity.cpp
+++ b/i18n/number_decimalquantity.cpp
@@ -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 {
diff --git a/test/intltest/numfmtst.cpp b/test/intltest/numfmtst.cpp
index 34355939113..8d52dc122bf 100644
--- a/test/intltest/numfmtst.cpp
+++ b/test/intltest/numfmtst.cpp
@@ -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() {
