From: Jungshik Shin Date: Tue, 20 Sep 2011 00:12:55 +0000 (+0000) Subject: ICU-8561 DigitList::set(double) breaks in some locales and generates NaN X-Git-Tag: milestone-59-0-1~4501 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0140e29ece080fdddd50f53abf76d8ee1fc6deff;p=icu ICU-8561 DigitList::set(double) breaks in some locales and generates NaN X-SVN-Rev: 30689 --- diff --git a/icu4c/source/i18n/digitlst.cpp b/icu4c/source/i18n/digitlst.cpp index 1ae9027c747..d00163ef772 100644 --- a/icu4c/source/i18n/digitlst.cpp +++ b/icu4c/source/i18n/digitlst.cpp @@ -60,6 +60,18 @@ static const char I64_MIN_REP[] = "9223372036854775808"; U_NAMESPACE_BEGIN +static void +loadDecimalChar() { + if (gDecimal == 0) { + char rep[MAX_DIGITS]; + // For machines that decide to change the decimal on you, + // and try to be too smart with localization. + // This normally should be just a '.'. + sprintf(rep, "%+1.1f", 1.0); + gDecimal = rep[2]; + } +} + // ------------------------------------- // default constructor @@ -408,15 +420,6 @@ DigitList::getDouble() const } DigitList *nonConstThis = const_cast(this); - if (gDecimal == 0) { - char rep[MAX_DIGITS]; - // For machines that decide to change the decimal on you, - // and try to be too smart with localization. - // This normally should be just a '.'. - sprintf(rep, "%+1.1f", 1.0); - gDecimal = rep[2]; - } - if (isZero()) { nonConstThis->fDouble = 0.0; if (decNumberIsNegative(fDecNumber)) { @@ -451,6 +454,7 @@ DigitList::getDouble() const } U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); + loadDecimalChar(); if (gDecimal != '.') { char *decimalPt = strchr(s, '.'); if (decimalPt != NULL) { @@ -741,6 +745,17 @@ DigitList::set(double source) sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source); U_ASSERT(uprv_strlen(rep) < sizeof(rep)); + // uprv_decNumberFromString() will parse the string expecting '.' as a + // decimal separator, however sprintf() can use ',' in certain locales. + // Overwrite a different decimal separator with '.' here before proceeding. + loadDecimalChar(); + if (gDecimal != '.') { + char *decimalPt = strchr(rep, gDecimal); + if (decimalPt != NULL) { + *decimalPt = '.'; + } + } + // Create a decNumber from the string. uprv_decNumberFromString(fDecNumber, rep, &fContext); uprv_decNumberTrim(fDecNumber);