Kaydet (Commit) a3c627fe authored tarafından Eike Rathke's avatar Eike Rathke

resolve crashes with ICU 53.1 in locales with collator data, fdo#77071

ICU 53.1 changed API behavior:
https://ssl.icu-project.org/apiref/icu4c/classicu_1_1RuleBasedCollator.html#a2f4c7eeaf020ad68e3bd9722dd272357
isn't correct anymore:

length: size of the image. If negative, the API will try to figure out the
        length of the image

        NO, IT WILL NOT! It bails out with an error instead.
        Introduced a function to obtain the length for each collator data.

base:  collator, usually root. The base is required to be present through the
       lifetime of the collator. Currently it cannot be NULL.

       NOT "usually root"! There's a check now that bails out if
       if(base->tailoring != CollationRoot::getRoot(errorCode))
       So using an instance created with icu::Locale::getRoot()

Change-Id: Ia9c4e27d5ef4f8083bbe57e4e2f4b3ff63bb42ed
üst cbb9efa6
...@@ -121,6 +121,7 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: ...@@ -121,6 +121,7 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang::
} }
if (!collator && OUString::createFromAscii(LOCAL_RULE_LANGS).indexOf(rLocale.Language) >= 0) { if (!collator && OUString::createFromAscii(LOCAL_RULE_LANGS).indexOf(rLocale.Language) >= 0) {
const sal_uInt8* (*func)() = NULL; const sal_uInt8* (*func)() = NULL;
size_t (*funclen)() = NULL;
#ifndef DISABLE_DYNLOADING #ifndef DISABLE_DYNLOADING
OUStringBuffer aBuf; OUStringBuffer aBuf;
...@@ -133,11 +134,21 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: ...@@ -133,11 +134,21 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang::
aBuf.appendAscii("get_").append(rLocale.Language).appendAscii("_"); aBuf.appendAscii("get_").append(rLocale.Language).appendAscii("_");
if ( rLocale.Language == "zh" ) { if ( rLocale.Language == "zh" ) {
OUString func_base = aBuf.makeStringAndClear(); OUString func_base = aBuf.makeStringAndClear();
OUString funclen_base = func_base + "_length";
if (OUString("TW HK MO").indexOf(rLocale.Country) >= 0) if (OUString("TW HK MO").indexOf(rLocale.Country) >= 0)
func=(const sal_uInt8* (*)()) osl_getFunctionSymbol(hModule, {
func = (const sal_uInt8* (*)()) osl_getFunctionSymbol(hModule,
OUString(func_base + "TW_" + rAlgorithm).pData); OUString(func_base + "TW_" + rAlgorithm).pData);
funclen = (size_t (*)()) osl_getFunctionSymbol(hModule,
OUString(funclen_base + "TW_" + rAlgorithm).pData);
}
if (!func) if (!func)
func=(const sal_uInt8* (*)()) osl_getFunctionSymbol(hModule, OUString(func_base + rAlgorithm).pData); {
func = (const sal_uInt8* (*)()) osl_getFunctionSymbol(
hModule, OUString(func_base + rAlgorithm).pData);
funclen = (size_t (*)()) osl_getFunctionSymbol(
hModule, OUString(funclen_base + rAlgorithm).pData);
}
} else { } else {
if ( rLocale.Language == "ja" ) { if ( rLocale.Language == "ja" ) {
// replace algorithm name to implementation name. // replace algorithm name to implementation name.
...@@ -150,7 +161,10 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: ...@@ -150,7 +161,10 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang::
} else { } else {
aBuf.append(rAlgorithm); aBuf.append(rAlgorithm);
} }
func=(const sal_uInt8* (*)()) osl_getFunctionSymbol(hModule, aBuf.makeStringAndClear().pData); OUString func_base = aBuf.makeStringAndClear();
OUString funclen_base = func_base + "_length";
func = (const sal_uInt8* (*)()) osl_getFunctionSymbol(hModule, func_base.pData);
funclen = (size_t (*)()) osl_getFunctionSymbol(hModule, funclen_base.pData);
} }
} }
#else #else
...@@ -159,87 +173,159 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: ...@@ -159,87 +173,159 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang::
#if WITH_LOCALE_ALL || WITH_LOCALE_ca #if WITH_LOCALE_ALL || WITH_LOCALE_ca
} else if ( rLocale.Language == "ca" ) { } else if ( rLocale.Language == "ca" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_ca_charset; func = get_collator_data_ca_charset;
funclen = get_collator_data_ca_charset_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_dz #if WITH_LOCALE_ALL || WITH_LOCALE_dz
} else if ( rLocale.Language == "dz" || rLocale.Language == "bo" ) { } else if ( rLocale.Language == "dz" || rLocale.Language == "bo" ) {
// 'bo' Tibetan uses the same collation rules as 'dz' Dzongkha // 'bo' Tibetan uses the same collation rules as 'dz' Dzongkha
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_dz_charset; func = get_collator_data_dz_charset;
funclen = get_collator_data_dz_charset_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_hu #if WITH_LOCALE_ALL || WITH_LOCALE_hu
} else if ( rLocale.Language == "hu" ) { } else if ( rLocale.Language == "hu" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_hu_charset; func = get_collator_data_hu_charset;
funclen = get_collator_data_hu_charset_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_ja #if WITH_LOCALE_ALL || WITH_LOCALE_ja
} else if ( rLocale.Language == "ja" ) { } else if ( rLocale.Language == "ja" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_ja_charset; func = get_collator_data_ja_charset;
funclen = get_collator_data_ja_charset_length;
}
else if ( rAlgorithm == "phonetic (alphanumeric first)" ) else if ( rAlgorithm == "phonetic (alphanumeric first)" )
{
func = get_collator_data_ja_phonetic_alphanumeric_first; func = get_collator_data_ja_phonetic_alphanumeric_first;
funclen = get_collator_data_ja_phonetic_alphanumeric_first_length;
}
else if ( rAlgorithm == "phonetic (alphanumeric last)" ) else if ( rAlgorithm == "phonetic (alphanumeric last)" )
{
func = get_collator_data_ja_phonetic_alphanumeric_last; func = get_collator_data_ja_phonetic_alphanumeric_last;
funclen = get_collator_data_ja_phonetic_alphanumeric_last_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_ko #if WITH_LOCALE_ALL || WITH_LOCALE_ko
#if (U_ICU_VERSION_MAJOR_NUM < 53) #if (U_ICU_VERSION_MAJOR_NUM < 53)
} else if ( rLocale.Language == "ko" ) { } else if ( rLocale.Language == "ko" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_ko_charset; func = get_collator_data_ko_charset;
funclen = get_collator_data_ko_charset_length;
}
#endif #endif
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_ku #if WITH_LOCALE_ALL || WITH_LOCALE_ku
} else if ( rLocale.Language == "ku" ) { } else if ( rLocale.Language == "ku" ) {
if ( rAlgorithm == "alphanumeric" ) if ( rAlgorithm == "alphanumeric" )
{
func = get_collator_data_ku_alphanumeric; func = get_collator_data_ku_alphanumeric;
funclen = get_collator_data_ku_alphanumeric_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_ln #if WITH_LOCALE_ALL || WITH_LOCALE_ln
} else if ( rLocale.Language == "ln" ) { } else if ( rLocale.Language == "ln" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_ln_charset; func = get_collator_data_ln_charset;
funclen = get_collator_data_ln_charset_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_my #if WITH_LOCALE_ALL || WITH_LOCALE_my
} else if ( rLocale.Language == "my" ) { } else if ( rLocale.Language == "my" ) {
if ( rAlgorithm == "dictionary" ) if ( rAlgorithm == "dictionary" )
{
func = get_collator_data_my_dictionary; func = get_collator_data_my_dictionary;
funclen = get_collator_data_my_dictionary_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_ne #if WITH_LOCALE_ALL || WITH_LOCALE_ne
} else if ( rLocale.Language == "ne" ) { } else if ( rLocale.Language == "ne" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_ne_charset; func = get_collator_data_ne_charset;
funclen = get_collator_data_ne_charset_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_sid #if WITH_LOCALE_ALL || WITH_LOCALE_sid
} else if ( rLocale.Language == "sid" ) { } else if ( rLocale.Language == "sid" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_sid_charset; func = get_collator_data_sid_charset;
funclen = get_collator_data_sid_charset_length;
}
#endif #endif
#if WITH_LOCALE_ALL || WITH_LOCALE_zh #if WITH_LOCALE_ALL || WITH_LOCALE_zh
} else if ( rLocale.Language == "zh" && (rLocale.Country == "TW" || rLocale.Country == "HK" || rLocale.Country == "MO") ) { } else if ( rLocale.Language == "zh" && (rLocale.Country == "TW" || rLocale.Country == "HK" || rLocale.Country == "MO") ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_zh_TW_charset; func = get_collator_data_zh_TW_charset;
funclen = get_collator_data_zh_TW_charset_length;
}
else if ( rAlgorithm == "radical" ) else if ( rAlgorithm == "radical" )
{
func = get_collator_data_zh_TW_radical; func = get_collator_data_zh_TW_radical;
funclen = get_collator_data_zh_TW_radical_length;
}
else if ( rAlgorithm == "stroke" ) else if ( rAlgorithm == "stroke" )
{
func = get_collator_data_zh_TW_stroke; func = get_collator_data_zh_TW_stroke;
funclen = get_collator_data_zh_TW_stroke_length;
}
} else if ( rLocale.Language == "zh" ) { } else if ( rLocale.Language == "zh" ) {
if ( rAlgorithm == "charset" ) if ( rAlgorithm == "charset" )
{
func = get_collator_data_zh_charset; func = get_collator_data_zh_charset;
funclen = get_collator_data_zh_charset_length;
}
else if ( rAlgorithm == "pinyin" ) else if ( rAlgorithm == "pinyin" )
{
func = get_collator_data_zh_pinyin; func = get_collator_data_zh_pinyin;
funclen = get_collator_data_zh_pinyin_length;
}
else if ( rAlgorithm == "radical" ) else if ( rAlgorithm == "radical" )
{
func = get_collator_data_zh_radical; func = get_collator_data_zh_radical;
funclen = get_collator_data_zh_radical_length;
}
else if ( rAlgorithm == "stroke" ) else if ( rAlgorithm == "stroke" )
{
func = get_collator_data_zh_stroke; func = get_collator_data_zh_stroke;
funclen = get_collator_data_zh_stroke_length;
}
else if ( rAlgorithm == "zhuyin" ) else if ( rAlgorithm == "zhuyin" )
{
func = get_collator_data_zh_zhuyin; func = get_collator_data_zh_zhuyin;
funclen = get_collator_data_zh_zhuyin_length;
}
#endif #endif
} }
#endif // DISABLE_DYNLOADING #endif // DISABLE_DYNLOADING
if (func) { if (func && funclen) {
const sal_uInt8* ruleImage=func(); const sal_uInt8* ruleImage=func();
uca_base = new RuleBasedCollator(static_cast<UChar*>(NULL), status); size_t ruleImageSize = funclen();
// Not only changed ICU 53.1 the API behavior that a negative
// length (ruleImageSize) now leads to failure, but also that
// the base RuleBasedCollator passed as uca_base here needs to
// have a base->tailoring == CollationRoot::getRoot() otherwise
// the init bails out as well, as it does for the previously
// used "empty" RuleBasedCollator.
// The default collator of the en-US locale would also fulfill
// the requirement. The collator of the actual locale or the
// NULL (default) locale does not.
uca_base = static_cast<RuleBasedCollator*>(icu::Collator::createInstance(
icu::Locale::getRoot(), status));
if (! U_SUCCESS(status)) throw RuntimeException(); if (! U_SUCCESS(status)) throw RuntimeException();
collator = new RuleBasedCollator(reinterpret_cast<const uint8_t*>(ruleImage), -1, uca_base, status); collator = new RuleBasedCollator(
reinterpret_cast<const uint8_t*>(ruleImage), ruleImageSize, uca_base, status);
if (! U_SUCCESS(status)) throw RuntimeException(); if (! U_SUCCESS(status)) throw RuntimeException();
} }
} }
......
...@@ -65,8 +65,10 @@ void data_write(char* file, char* name, sal_uInt8 *data, sal_Int32 len) ...@@ -65,8 +65,10 @@ void data_write(char* file, char* name, sal_uInt8 *data, sal_Int32 len)
fprintf(fp, "#ifndef DISABLE_DYNLOADING\n"); fprintf(fp, "#ifndef DISABLE_DYNLOADING\n");
fprintf(fp, "SAL_DLLPUBLIC_EXPORT const sal_uInt8* get_%s() { return %s; }\n", name, name); fprintf(fp, "SAL_DLLPUBLIC_EXPORT const sal_uInt8* get_%s() { return %s; }\n", name, name);
fprintf(fp, "SAL_DLLPUBLIC_EXPORT size_t get_%s_length() { return sizeof(%s); }\n", name, name);
fprintf(fp, "#else\n"); fprintf(fp, "#else\n");
fprintf(fp, "SAL_DLLPUBLIC_EXPORT const sal_uInt8* get_collator_data_%s() { return %s; }\n", name, name); fprintf(fp, "SAL_DLLPUBLIC_EXPORT const sal_uInt8* get_collator_data_%s() { return %s; }\n", name, name);
fprintf(fp, "SAL_DLLPUBLIC_EXPORT size_t get_collator_data_%s_length() { return sizeof(%s); }\n", name, name);
fprintf(fp, "#endif\n"); fprintf(fp, "#endif\n");
fprintf(fp, "\n"); fprintf(fp, "\n");
fprintf (fp, "}\n"); fprintf (fp, "}\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment