Skip to content

Commit

Permalink
ICU-13823 Merged #13840 number parser memory overflow fix (r41541) to…
Browse files Browse the repository at this point in the history
… maint-62 for 62.1 GA.

X-SVN-Rev: 41542
  • Loading branch information
yumaoka committed Jun 20, 2018
1 parent 1a2d4ce commit 4a3ba8e
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 1 deletion.
2 changes: 1 addition & 1 deletion icu4c/source/i18n/number_decimalquantity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ void DecimalQuantity::ensureCapacity(int32_t capacity) {
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;
Expand Down
31 changes: 31 additions & 0 deletions icu4c/source/test/intltest/numfmtst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
TESTCASE_AUTO(Test13840_ParseLongStringCrash);
TESTCASE_AUTO_END;
}

Expand Down Expand Up @@ -9154,4 +9155,34 @@ void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
}
}

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 */
1 change: 1 addition & 0 deletions icu4c/source/test/intltest/numfmtst.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
void Test13763_FieldPositionIteratorOffset();
void Test13777_ParseLongNameNonCurrencyMode();
void Test13804_EmptyStringsWhenParsing();
void Test13840_ParseLongStringCrash();

private:
UBool testFormattableAsUFormattable(const char *file, int line, Formattable &f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6223,4 +6223,27 @@ public void test13804_EmptyStringsWhenParsing() {
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);
}
}

0 comments on commit 4a3ba8e

Please sign in to comment.