ICU-6153 Prevent crash for large ChoiceFormat values by using the correct printf specification.
X-SVN-Rev: 23276
This commit is contained in:
parent
4999616984
commit
e8e7c73d8a
@ -232,7 +232,7 @@ ChoiceFormat::dtos(double value,
|
||||
char *itrPtr = temp;
|
||||
char *startPtr;
|
||||
|
||||
sprintf(temp, "%.*f", DBL_DIG, value);
|
||||
sprintf(temp, "%.*g", DBL_DIG, value);
|
||||
|
||||
/* Find and convert the decimal point.
|
||||
Using setlocale on some machines will cause sprintf to use a comma for certain locales.
|
||||
@ -240,18 +240,19 @@ ChoiceFormat::dtos(double value,
|
||||
while (*itrPtr && (*itrPtr == '-' || isdigit(*itrPtr))) {
|
||||
itrPtr++;
|
||||
}
|
||||
if (*itrPtr) {
|
||||
/* Have we reached something that looks like a decimal point? */
|
||||
if (*itrPtr != 0 && *itrPtr != 'e') {
|
||||
*itrPtr = '.';
|
||||
}
|
||||
|
||||
/* remove trailing zeros, except the one after '.' */
|
||||
startPtr = itrPtr + 1;
|
||||
itrPtr = uprv_strchr(startPtr, 0);
|
||||
while(--itrPtr > startPtr){
|
||||
if(*itrPtr == '0'){
|
||||
*itrPtr = 0;
|
||||
}else{
|
||||
break;
|
||||
/* remove trailing zeros, except the one after '.' */
|
||||
startPtr = itrPtr + 1;
|
||||
itrPtr = uprv_strchr(startPtr, 0);
|
||||
while(--itrPtr > startPtr){
|
||||
if(*itrPtr == '0'){
|
||||
*itrPtr = 0;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
string = UnicodeString(temp, -1, US_INV); /* invariant codepage */
|
||||
@ -490,56 +491,6 @@ ChoiceFormat::toPattern(UnicodeString& result) const
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef U_USE_CHOICE_FORMAT_DEPRECATES
|
||||
// -------------------------------------
|
||||
// Adopts the limit and format arrays.
|
||||
|
||||
void
|
||||
ChoiceFormat::adoptChoices(double *limits,
|
||||
UnicodeString *formats,
|
||||
int32_t cnt )
|
||||
{
|
||||
adoptChoices(limits, (UBool *)0, formats, cnt);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Adopts the limit and format arrays.
|
||||
|
||||
void
|
||||
ChoiceFormat::adoptChoices(double *limits,
|
||||
UBool *closures,
|
||||
UnicodeString *formats,
|
||||
int32_t cnt )
|
||||
{
|
||||
if(limits == 0 || formats == 0)
|
||||
return;
|
||||
|
||||
if (fChoiceLImits) {
|
||||
uprv_free(fChoiceLimits);
|
||||
}
|
||||
if (fClosures) {
|
||||
uprv_free(fClosures);
|
||||
}
|
||||
if (fChoiceFormats) {
|
||||
delete [] fChoiceFormats;
|
||||
}
|
||||
fChoiceLimits = limits;
|
||||
fClosures = closures;
|
||||
fChoiceFormats = formats;
|
||||
fCount = cnt;
|
||||
|
||||
if (fClosures == 0) {
|
||||
fClosures = (UBool*) uprv_malloc( sizeof(UBool) * fCount);
|
||||
if (fClosures != NULL) {
|
||||
int32_t i;
|
||||
for (i=0; i<fCount; ++i) {
|
||||
fClosures[i] = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// -------------------------------------
|
||||
// Sets the limit and format arrays.
|
||||
void
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 1997-2005, International Business Machines
|
||||
* Copyright (C) 1997-2008, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
********************************************************************************
|
||||
*
|
||||
@ -382,40 +382,6 @@ public:
|
||||
*/
|
||||
virtual UnicodeString& toPattern(UnicodeString &pattern) const;
|
||||
|
||||
#ifdef U_USE_CHOICE_FORMAT_DEPRECATES
|
||||
/**
|
||||
* Set the choices to be used in formatting. The arrays are adopted and
|
||||
* should not be deleted by the caller.
|
||||
*
|
||||
* @param limitsToAdopt Contains the top value that you want
|
||||
* parsed with that format,and should be in
|
||||
* ascending sorted order. When formatting X,
|
||||
* the choice will be the i, where limit[i]
|
||||
* <= X < limit[i+1].
|
||||
* @param formatsToAdopt The format strings you want to use for each limit.
|
||||
* @param count The size of the above arrays.
|
||||
* @obsolete ICU 2.6. Use setChoices instead since this API will be removed in that release.
|
||||
*/
|
||||
virtual void adoptChoices(double* limitsToAdopt,
|
||||
UnicodeString* formatsToAdopt,
|
||||
int32_t count );
|
||||
|
||||
/**
|
||||
* Set the choices to be used in formatting. The arrays are adopted
|
||||
* and should not be deleted by the caller. See class description
|
||||
* for documenatation of the limits, closures, and formats arrays.
|
||||
* @param limitsToAdopt Array of limits to adopt
|
||||
* @param closuresToAdopt Array of limit booleans to adopt
|
||||
* @param formatsToAdopt Array of format string to adopt
|
||||
* @param count The size of the above arrays
|
||||
* @obsolete ICU 2.6. Use setChoices instead since this API will be removed in that release.
|
||||
*/
|
||||
virtual void adoptChoices(double* limitsToAdopt,
|
||||
UBool* closuresToAdopt,
|
||||
UnicodeString* formatsToAdopt,
|
||||
int32_t count);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the choices to be used in formatting.
|
||||
*
|
||||
|
@ -1,6 +1,6 @@
|
||||
/***********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2005, International Business Machines Corporation
|
||||
* Copyright (c) 1997-2008, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
***********************************************************************/
|
||||
|
||||
@ -153,7 +153,7 @@ void MessageFormatRegressionTest::Test4058973()
|
||||
|
||||
UnicodeString pat;
|
||||
pat = fmt->toPattern(pat);
|
||||
UnicodeString exp("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}");
|
||||
UnicodeString exp("{0,choice,0#no files|1#one file|1< {0,number,integer} files}");
|
||||
if (pat != exp) {
|
||||
errln("MessageFormat.toPattern failed");
|
||||
errln("Exp: " + exp);
|
||||
@ -628,7 +628,7 @@ void MessageFormatRegressionTest::Test4094906()
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UnicodeString pattern("-");
|
||||
pattern += (UChar) 0x221E;
|
||||
pattern += "<are negative|0.0<are no or fraction|1.0#is one|1.0<is 1+|";
|
||||
pattern += "<are negative|0<are no or fraction|1#is one|1<is 1+|";
|
||||
pattern += (UChar) 0x221E;
|
||||
pattern += "<are many.";
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2005, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2008, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
@ -26,6 +26,7 @@ void TestChoiceFormat::runIndexedTest(int32_t index, UBool exec,
|
||||
TESTCASE(1,TestComplexExample);
|
||||
TESTCASE(2,TestClosures);
|
||||
TESTCASE(3,TestPatterns);
|
||||
TESTCASE(4,TestChoiceFormatToPatternOverflow);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
@ -78,21 +79,6 @@ TestChoiceFormat::TestSimpleExample( void )
|
||||
errln("ERROR: ==operator failed\n");
|
||||
}
|
||||
delete formequal;
|
||||
|
||||
#ifdef U_USE_CHOICE_FORMAT_DEPRECATES
|
||||
//Testing adoptChoices()
|
||||
double *limitsToAdopt = (double *)uprv_malloc(7 * sizeof(double));
|
||||
UnicodeString *monthNamesToAdopt = new UnicodeString[7];
|
||||
|
||||
uprv_arrayCopy(monthNames, monthNamesToAdopt, 7);
|
||||
uprv_memcpy(limitsToAdopt, limits, (size_t)(7 * sizeof(limits[0])));
|
||||
|
||||
formnew->adoptChoices(limitsToAdopt, monthNamesToAdopt, 7);
|
||||
if(!(*formnew == *form)){
|
||||
errln("ERROR: ==Operator or adoptChoices failed\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
delete formnew;
|
||||
|
||||
//Testing getLimits()
|
||||
@ -179,7 +165,7 @@ TestChoiceFormat::TestComplexExample( void )
|
||||
it_logln("MessageFormat toPattern: " + res1);
|
||||
fileform->toPattern( res1 );
|
||||
it_logln("ChoiceFormat toPattern: " + res1);
|
||||
if (res1 == "-1.0#are corrupted files|0.0#are no files|1.0#is one file|2.0#are {2} files") {
|
||||
if (res1 == "-1#are corrupted files|0#are no files|1#is one file|2#are {2} files") {
|
||||
it_logln("toPattern tested!");
|
||||
}else{
|
||||
it_errln("*** ChoiceFormat to Pattern result!");
|
||||
@ -348,38 +334,19 @@ TestChoiceFormat::TestComplexExample( void )
|
||||
}
|
||||
|
||||
form_pat.toPattern( res1 );
|
||||
if (res1 == "0.0#none|1.0#one|2.0#many") {
|
||||
if (res1 == "0#none|1#one|2#many") {
|
||||
it_logln("ChoiceFormat contructor( newPattern, status) tested");
|
||||
}else{
|
||||
it_errln("*** ChoiceFormat contructor( newPattern, status) or toPattern result!");
|
||||
}
|
||||
|
||||
#ifdef U_USE_CHOICE_FORMAT_DEPRECATES
|
||||
double* d_a = (double *)uprv_malloc(2 * sizeof(double));
|
||||
if (!d_a) { it_errln("*** allocation error."); return; }
|
||||
d_a[0] = 1.0; d_a[1] = 2.0;
|
||||
|
||||
UnicodeString* s_a = new UnicodeString[2];
|
||||
if (!s_a) { it_errln("*** allocation error."); return; }
|
||||
s_a[0] = "first"; s_a[1] = "second";
|
||||
|
||||
form_pat.adoptChoices( d_a, s_a, 2 );
|
||||
form_pat.toPattern( res1 );
|
||||
it_out << "ChoiceFormat adoptChoices toPattern: " << res1 << endl;
|
||||
if (res1 == "1.0#first|2.0#second") {
|
||||
it_logln("ChoiceFormat adoptChoices tested");
|
||||
}else{
|
||||
it_errln("*** ChoiceFormat adoptChoices result!");
|
||||
}
|
||||
#endif
|
||||
|
||||
double d_a2[] = { 3.0, 4.0 };
|
||||
UnicodeString s_a2[] = { "third", "forth" };
|
||||
|
||||
form_pat.setChoices( d_a2, s_a2, 2 );
|
||||
form_pat.toPattern( res1 );
|
||||
it_logln(UnicodeString("ChoiceFormat adoptChoices toPattern: ") + res1);
|
||||
if (res1 == "3.0#third|4.0#forth") {
|
||||
if (res1 == "3#third|4#forth") {
|
||||
it_logln("ChoiceFormat adoptChoices tested");
|
||||
}else{
|
||||
it_errln("*** ChoiceFormat adoptChoices result!");
|
||||
@ -497,7 +464,7 @@ void TestChoiceFormat::TestClosures(void) {
|
||||
|
||||
// 'fmt2' is created using a pattern; it should be equivalent
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
const char* PAT = "0.0#,1)|1.0#[1,2]|2.0<(2,3]|3.0<(3,4)|4.0#[4,5)|5.0#[5,";
|
||||
const char* PAT = "0#,1)|1#[1,2]|2<(2,3]|3<(3,4)|4#[4,5)|5#[5,";
|
||||
ChoiceFormat fmt2(PAT, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("FAIL: ChoiceFormat constructor failed");
|
||||
@ -649,4 +616,16 @@ void TestChoiceFormat::TestPatterns(void) {
|
||||
0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void TestChoiceFormat::TestChoiceFormatToPatternOverflow()
|
||||
{
|
||||
static const double limits[] = {0.1e-78, 1e13, 0.1e78};
|
||||
UnicodeString monthNames[] = { "one", "two", "three" };
|
||||
ChoiceFormat fmt(limits, monthNames, sizeof(limits)/sizeof(limits[0]));
|
||||
UnicodeString patStr, expectedPattern("1e-079#one|10000000000000#two|1e+077#three");
|
||||
fmt.toPattern(patStr);
|
||||
if (patStr != expectedPattern) {
|
||||
errln("ChoiceFormat returned \"" + patStr + "\" instead of \"" + expectedPattern + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2003, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2008, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
@ -40,6 +40,7 @@ class TestChoiceFormat: public IntlTest {
|
||||
* Test applyPattern
|
||||
*/
|
||||
void TestPatterns(void);
|
||||
void TestChoiceFormatToPatternOverflow(void);
|
||||
|
||||
void _testPattern(const char* pattern,
|
||||
UBool isValid,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/********************************************************************
|
||||
* Copyright (c) 1997-2007, International Business Machines
|
||||
* Copyright (c) 1997-2008, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
********************************************************************
|
||||
* File TMSGFMT.CPP
|
||||
@ -162,7 +162,7 @@ void TestMessageFormat::testBug2()
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UnicodeString result;
|
||||
// {sfb} use double format in pattern, so result will match (not strictly necessary)
|
||||
const UnicodeString pattern = "There {0,choice,0.0#are no files|1.0#is one file|1.0<are {0, number} files} on disk {1}. ";
|
||||
const UnicodeString pattern = "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
|
||||
logln("The input pattern : " + pattern);
|
||||
MessageFormat *fmt = new MessageFormat(pattern, status);
|
||||
if (U_FAILURE(status)) {
|
||||
|
Loading…
Reference in New Issue
Block a user