mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-21 12:40:02 +00:00
ICU-11742 merge r39356,r39384 from #12745 into maint 55.x
X-SVN-Rev: 39569
This commit is contained in:
parent
ac90f10369
commit
a60b54b55a
2 changed files with 48 additions and 37 deletions
|
@ -1,3 +1,5 @@
|
|||
// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) 1997-2015, International Business Machines
|
||||
|
@ -42,6 +44,7 @@
|
|||
#include "uhash.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "ustr_imp.h"
|
||||
#include "charstr.h"
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV locale_cleanup(void);
|
||||
|
@ -57,6 +60,12 @@ static UMutex gDefaultLocaleMutex = U_MUTEX_INITIALIZER;
|
|||
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
|
||||
|
||||
typedef enum ELocalePos {
|
||||
|
@ -283,13 +292,12 @@ Locale::Locale( const char * newLanguage,
|
|||
}
|
||||
else
|
||||
{
|
||||
MaybeStackArray<char, ULOC_FULLNAME_CAPACITY> togo;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t size = 0;
|
||||
int32_t lsize = 0;
|
||||
int32_t csize = 0;
|
||||
int32_t vsize = 0;
|
||||
int32_t ksize = 0;
|
||||
char *p;
|
||||
|
||||
// Calculate the size of the resulting string.
|
||||
|
||||
|
@ -297,13 +305,23 @@ Locale::Locale( const char * newLanguage,
|
|||
if ( newLanguage != NULL )
|
||||
{
|
||||
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
|
||||
if ( newCountry != NULL )
|
||||
{
|
||||
csize = (int32_t)uprv_strlen(newCountry);
|
||||
if ( csize < 0 || csize > ULOC_STRING_LIMIT ) { // int32 wrap
|
||||
setToBogus();
|
||||
return;
|
||||
}
|
||||
size += csize;
|
||||
}
|
||||
|
||||
|
@ -318,6 +336,10 @@ Locale::Locale( const char * newLanguage,
|
|||
|
||||
// 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) )
|
||||
{
|
||||
vsize--;
|
||||
|
@ -342,70 +364,56 @@ Locale::Locale( const char * newLanguage,
|
|||
if ( newKeywords != NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if ( ksize != 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2015, International Business Machines Corporation and
|
||||
|
@ -1974,11 +1976,12 @@ void NumberFormatTest::TestSymbolsWithBadLocale(void) {
|
|||
for (i = 0; i < sizeof(badLocales) / sizeof(char*); i++) {
|
||||
const char *localeName = badLocales[i];
|
||||
Locale locBad(localeName);
|
||||
TEST_ASSERT_TRUE(!locBad.isBogus());
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UnicodeString intlCurrencySymbol((UChar)0xa4);
|
||||
|
||||
intlCurrencySymbol.append((UChar)0xa4);
|
||||
|
||||
|
||||
logln("Current locale is %s", Locale::getDefault().getName());
|
||||
Locale::setDefault(locBad, status);
|
||||
logln("Current locale is %s", Locale::getDefault().getName());
|
||||
|
|
Loading…
Add table
Reference in a new issue