ICU-13823 Merged #13840 number parser memory overflow fix (r41541) to maint-62 for 62.1 GA.
X-SVN-Rev: 41542
diff --git a/icu4c/source/i18n/number_decimalquantity.cpp b/icu4c/source/i18n/number_decimalquantity.cpp
index 8830419..9d80e33 100644
--- a/icu4c/source/i18n/number_decimalquantity.cpp
+++ b/icu4c/source/i18n/number_decimalquantity.cpp
@@ -1058,7 +1058,7 @@
auto bcd1 = static_cast<int8_t*>(uprv_malloc(capacity * 2 * sizeof(int8_t)));
uprv_memcpy(bcd1, fBCD.bcdBytes.ptr, oldCapacity * sizeof(int8_t));
// Initialize the rest of the byte array to zeros (this is done automatically in Java)
- uprv_memset(fBCD.bcdBytes.ptr + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t));
+ uprv_memset(bcd1 + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t));
uprv_free(fBCD.bcdBytes.ptr);
fBCD.bcdBytes.ptr = bcd1;
fBCD.bcdBytes.len = capacity * 2;
diff --git a/icu4c/source/test/intltest/numfmtst.cpp b/icu4c/source/test/intltest/numfmtst.cpp
index f5fb64e..b718429 100644
--- a/icu4c/source/test/intltest/numfmtst.cpp
+++ b/icu4c/source/test/intltest/numfmtst.cpp
@@ -215,6 +215,7 @@
TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
+ TESTCASE_AUTO(Test13840_ParseLongStringCrash);
TESTCASE_AUTO_END;
}
@@ -9154,4 +9155,34 @@
}
}
+void NumberFormatTest::Test13840_ParseLongStringCrash() {
+ IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");
+
+ LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
+ if (status.errIfFailureAndReset()) { return; }
+
+ Formattable result;
+ static const char16_t* bigString =
+ u"111111111111111111111111111111111111111111111111111111111111111111111"
+ u"111111111111111111111111111111111111111111111111111111111111111111111"
+ u"111111111111111111111111111111111111111111111111111111111111111111111"
+ u"111111111111111111111111111111111111111111111111111111111111111111111"
+ u"111111111111111111111111111111111111111111111111111111111111111111111"
+ u"111111111111111111111111111111111111111111111111111111111111111111111";
+ nf->parse(bigString, result, status);
+
+ // Normalize the input string:
+ CharString expectedChars;
+ expectedChars.appendInvariantChars(bigString, status);
+ DecimalQuantity expectedDQ;
+ expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
+ UnicodeString expectedUString = expectedDQ.toScientificString();
+
+ // Get the output string:
+ StringPiece actualChars = result.getDecimalNumber(status);
+ UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);
+
+ assertEquals("Should round-trip without crashing", expectedUString, actualUString);
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/icu4c/source/test/intltest/numfmtst.h b/icu4c/source/test/intltest/numfmtst.h
index 1c7c862..b51e752 100644
--- a/icu4c/source/test/intltest/numfmtst.h
+++ b/icu4c/source/test/intltest/numfmtst.h
@@ -279,6 +279,7 @@
void Test13763_FieldPositionIteratorOffset();
void Test13777_ParseLongNameNonCurrencyMode();
void Test13804_EmptyStringsWhenParsing();
+ void Test13840_ParseLongStringCrash();
private:
UBool testFormattableAsUFormattable(const char *file, int line, Formattable &f);
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java
index 78bf6b5..effd33f 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java
@@ -6223,4 +6223,27 @@
df.parse("1E+2.3", ppos);
}
}
+
+ @Test
+ public void test13840_ParseLongStringCrash() throws ParseException {
+ NumberFormat nf = NumberFormat.getInstance(ULocale.ENGLISH);
+ String bigString =
+ "111111111111111111111111111111111111111111111111111111111111111111111" +
+ "111111111111111111111111111111111111111111111111111111111111111111111" +
+ "111111111111111111111111111111111111111111111111111111111111111111111" +
+ "111111111111111111111111111111111111111111111111111111111111111111111" +
+ "111111111111111111111111111111111111111111111111111111111111111111111" +
+ "111111111111111111111111111111111111111111111111111111111111111111111";
+ Number result = nf.parse(bigString);
+
+ // Normalize the input string:
+ BigDecimal expectedBigDecimal = new BigDecimal(bigString);
+ String expectedUString = expectedBigDecimal.toString();
+
+ // Get the output string:
+ BigDecimal actualBigDecimal = (BigDecimal) result;
+ String actualUString = actualBigDecimal.toString();
+
+ assertEquals("Should round-trip without crashing", expectedUString, actualUString);
+ }
}