ICU-13840 Fixing memory overflow issue in number_decimalquantity.cpp and adding tests.

X-SVN-Rev: 41541
This commit is contained in:
Shane Carr 2018-06-19 21:52:52 +00:00
parent 733e363203
commit 3f7a4aa202
4 changed files with 56 additions and 1 deletions

View file

@ -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;

View file

@ -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;
}
@ -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 */

View file

@ -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);

View file

@ -6223,4 +6223,27 @@ public class NumberFormatTest extends TestFmwk {
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);
}
}