Index: icu/trunk/source/common/locid.cpp =================================================================== --- icu/source/common/locid.cpp (revision 39282) +++ icu/source/common/locid.cpp (revision 39384) @@ -45,4 +45,5 @@ #include "ucln_cmn.h" #include "ustr_imp.h" +#include "charstr.h" U_CDECL_BEGIN @@ -59,4 +60,10 @@ static UHashtable *gDefaultLocalesHashT = NULL; static Locale *gDefaultLocale = NULL; + +/** + * \def ULOC_STRING_LIMIT + * strings beyond this value crash in CharString + */ +#define ULOC_STRING_LIMIT 357913941 U_NAMESPACE_END @@ -286,5 +293,5 @@ else { - MaybeStackArray togo; + UErrorCode status = U_ZERO_ERROR; int32_t size = 0; int32_t lsize = 0; @@ -292,5 +299,4 @@ int32_t vsize = 0; int32_t ksize = 0; - char *p; // Calculate the size of the resulting string. @@ -300,6 +306,12 @@ { lsize = (int32_t)uprv_strlen(newLanguage); + if ( lsize < 0 || lsize > ULOC_STRING_LIMIT ) { // int32 wrap + setToBogus(); + return; + } size = lsize; } + + CharString togo(newLanguage, lsize, status); // start with newLanguage // _Country @@ -307,4 +319,8 @@ { csize = (int32_t)uprv_strlen(newCountry); + if ( csize < 0 || csize > ULOC_STRING_LIMIT ) { // int32 wrap + setToBogus(); + return; + } size += csize; } @@ -321,4 +337,8 @@ // remove trailing _'s vsize = (int32_t)uprv_strlen(newVariant); + if ( vsize < 0 || vsize > ULOC_STRING_LIMIT ) { // int32 wrap + setToBogus(); + return; + } while( (vsize>1) && (newVariant[vsize-1] == SEP_CHAR) ) { @@ -345,48 +365,30 @@ { ksize = (int32_t)uprv_strlen(newKeywords); + if ( ksize < 0 || ksize > ULOC_STRING_LIMIT ) { + setToBogus(); + return; + } size += ksize + 1; } - // NOW we have the full locale string.. - - /*if the whole string is longer than our internal limit, we need - to go to the heap for temporary buffers*/ - if (size >= togo.getCapacity()) - { - // If togo_heap could not be created, initialize with default settings. - if (togo.resize(size+1) == NULL) { - init(NULL, FALSE); - } - } - - togo[0] = 0; - // Now, copy it back. - p = togo.getAlias(); - if ( lsize != 0 ) - { - uprv_strcpy(p, newLanguage); - p += lsize; - } + + // newLanguage is already copied if ( ( vsize != 0 ) || (csize != 0) ) // at least: __v { // ^ - *p++ = SEP_CHAR; + togo.append(SEP_CHAR, status); } if ( csize != 0 ) { - uprv_strcpy(p, newCountry); - p += csize; + togo.append(newCountry, status); } if ( vsize != 0) { - *p++ = SEP_CHAR; // at least: __v - - uprv_strncpy(p, newVariant, vsize); // Must use strncpy because - p += vsize; // of trimming (above). - *p = 0; // terminate + togo.append(SEP_CHAR, status) + .append(newVariant, vsize, status); } @@ -394,19 +396,23 @@ { if (uprv_strchr(newKeywords, '=')) { - *p++ = '@'; /* keyword parsing */ + togo.append('@', status); /* keyword parsing */ } else { - *p++ = '_'; /* Variant parsing with a script */ + togo.append('_', status); /* Variant parsing with a script */ if ( vsize == 0) { - *p++ = '_'; /* No country found */ + togo.append('_', status); /* No country found */ } } - uprv_strcpy(p, newKeywords); - p += ksize; - } - + togo.append(newKeywords, status); + } + + if (U_FAILURE(status)) { + // Something went wrong with appending, etc. + setToBogus(); + return; + } // Parse it, because for example 'language' might really be a complete // string. - init(togo.getAlias(), FALSE); + init(togo.data(), FALSE); } }