ICU-12407 Prevent parse crash in DECIMAL-style formatter with applied currency pattern

X-SVN-Rev: 39236
This commit is contained in:
Peter Edberg 2016-09-15 03:55:22 +00:00
parent 4e29392bdd
commit e02cfd9eac
3 changed files with 58 additions and 7 deletions

View File

@ -447,13 +447,25 @@ DecimalFormat::construct(UErrorCode& status,
if (patternUsed->indexOf(kCurrencySign) != -1) {
// initialize for currency, not only for plural format,
// but also for mix parsing
if (fCurrencyPluralInfo == NULL) {
fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
if (U_FAILURE(status)) {
return;
}
}
// need it for mix parsing
handleCurrencySignInPattern(status);
}
}
void
DecimalFormat::handleCurrencySignInPattern(UErrorCode& status) {
// initialize for currency, not only for plural format,
// but also for mix parsing
if (U_FAILURE(status)) {
return;
}
if (fCurrencyPluralInfo == NULL) {
fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
if (U_FAILURE(status)) {
return;
}
}
// need it for mix parsing
if (fAffixPatternsForCurrency == NULL) {
setupCurrencyAffixPatterns(status);
}
}
@ -2817,6 +2829,9 @@ DecimalFormat::toLocalizedPattern(UnicodeString& result) const
void
DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
{
if (pattern.indexOf(kCurrencySign) != -1) {
handleCurrencySignInPattern(status);
}
fImpl->applyPattern(pattern, status);
}
@ -2827,6 +2842,9 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
UParseError& parseError,
UErrorCode& status)
{
if (pattern.indexOf(kCurrencySign) != -1) {
handleCurrencySignInPattern(status);
}
fImpl->applyPattern(pattern, parseError, status);
}
//------------------------------------------------------------------------------
@ -2834,6 +2852,9 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
void
DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
{
if (pattern.indexOf(kCurrencySign) != -1) {
handleCurrencySignInPattern(status);
}
fImpl->applyLocalizedPattern(pattern, status);
}
@ -2844,6 +2865,9 @@ DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
UParseError& parseError,
UErrorCode& status)
{
if (pattern.indexOf(kCurrencySign) != -1) {
handleCurrencySignInPattern(status);
}
fImpl->applyLocalizedPattern(pattern, parseError, status);
}

View File

@ -2103,6 +2103,8 @@ private:
DecimalFormatSymbols* symbolsToAdopt = 0
);
void handleCurrencySignInPattern(UErrorCode& status);
void parse(const UnicodeString& text,
Formattable& result,
ParsePosition& pos,

View File

@ -62,6 +62,7 @@ static void TestContext(void);
static void TestCurrencyUsage(void);
static void TestCurrFmtNegSameAsPositive(void);
static void TestVariousStylesAndAttributes(void);
static void TestParseCurrPatternWithDecStyle(void);
#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
@ -91,6 +92,7 @@ void addNumForTest(TestNode** root)
TESTCASE(TestCurrencyUsage);
TESTCASE(TestCurrFmtNegSameAsPositive);
TESTCASE(TestVariousStylesAndAttributes);
TESTCASE(TestParseCurrPatternWithDecStyle);
}
/* test Parse int 64 */
@ -2862,4 +2864,27 @@ static void TestVariousStylesAndAttributes(void) {
}
}
static const UChar currpat[] = { 0xA4,0x23,0x2C,0x23,0x23,0x30,0x2E,0x30,0x30,0}; /* ¤#,##0.00 */
static const UChar parsetxt[] = { 0x78,0x30,0x79,0x24,0 }; /* x0y$ */
static void TestParseCurrPatternWithDecStyle() {
UErrorCode status = U_ZERO_ERROR;
UNumberFormat *unumfmt = unum_open(UNUM_DECIMAL, NULL, 0, "en_US", NULL, &status);
if (U_FAILURE(status)) {
log_data_err("unum_open DECIMAL failed for en_US: %s (Are you missing data?)\n", u_errorName(status));
} else {
unum_applyPattern(unumfmt, FALSE, currpat, -1, NULL, &status);
if (U_FAILURE(status)) {
log_err_status(status, "unum_applyPattern failed: %s\n", u_errorName(status));
} else {
int32_t pos = 0;
double value = unum_parseDouble(unumfmt, parsetxt, -1, &pos, &status);
if (U_SUCCESS(status)) {
log_err_status(status, "unum_parseDouble expected to fail but got status %s, value %f\n", u_errorName(status), value);
}
}
unum_close(unumfmt);
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */