diff options
author | Eike Rathke <erack@redhat.com> | 2014-04-30 17:51:05 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2014-04-30 17:58:06 +0100 |
commit | a3c627fe38236e82bc6008075d862b3cbfbd9ce3 (patch) | |
tree | 3fc274ef9110fe04c2be4bbd4a9044305bda18f3 /i18npool/source | |
parent | cbb9efa642ec3a7418136547c04eb2455ba1c821 (diff) |
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
Diffstat (limited to 'i18npool/source')
-rw-r--r-- | i18npool/source/collator/collator_unicode.cxx | 98 | ||||
-rw-r--r-- | i18npool/source/collator/gencoll_rule.cxx | 2 |
2 files changed, 94 insertions, 6 deletions
diff --git a/i18npool/source/collator/collator_unicode.cxx b/i18npool/source/collator/collator_unicode.cxx index 425b84a1bb56..a0851d783ffb 100644 --- a/i18npool/source/collator/collator_unicode.cxx +++ b/i18npool/source/collator/collator_unicode.cxx @@ -121,6 +121,7 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: } if (!collator && OUString::createFromAscii(LOCAL_RULE_LANGS).indexOf(rLocale.Language) >= 0) { const sal_uInt8* (*func)() = NULL; + size_t (*funclen)() = NULL; #ifndef DISABLE_DYNLOADING OUStringBuffer aBuf; @@ -133,11 +134,21 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: aBuf.appendAscii("get_").append(rLocale.Language).appendAscii("_"); if ( rLocale.Language == "zh" ) { OUString func_base = aBuf.makeStringAndClear(); + OUString funclen_base = func_base + "_length"; 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); + funclen = (size_t (*)()) osl_getFunctionSymbol(hModule, + OUString(funclen_base + "TW_" + rAlgorithm).pData); + } 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 { if ( rLocale.Language == "ja" ) { // replace algorithm name to implementation name. @@ -150,7 +161,10 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: } else { 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 @@ -159,87 +173,159 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang:: #if WITH_LOCALE_ALL || WITH_LOCALE_ca } else if ( rLocale.Language == "ca" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_ca_charset; + funclen = get_collator_data_ca_charset_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_dz } else if ( rLocale.Language == "dz" || rLocale.Language == "bo" ) { // 'bo' Tibetan uses the same collation rules as 'dz' Dzongkha if ( rAlgorithm == "charset" ) + { func = get_collator_data_dz_charset; + funclen = get_collator_data_dz_charset_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_hu } else if ( rLocale.Language == "hu" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_hu_charset; + funclen = get_collator_data_hu_charset_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_ja } else if ( rLocale.Language == "ja" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_ja_charset; + funclen = get_collator_data_ja_charset_length; + } else if ( rAlgorithm == "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)" ) + { func = get_collator_data_ja_phonetic_alphanumeric_last; + funclen = get_collator_data_ja_phonetic_alphanumeric_last_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_ko #if (U_ICU_VERSION_MAJOR_NUM < 53) } else if ( rLocale.Language == "ko" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_ko_charset; + funclen = get_collator_data_ko_charset_length; + } #endif #endif #if WITH_LOCALE_ALL || WITH_LOCALE_ku } else if ( rLocale.Language == "ku" ) { if ( rAlgorithm == "alphanumeric" ) + { func = get_collator_data_ku_alphanumeric; + funclen = get_collator_data_ku_alphanumeric_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_ln } else if ( rLocale.Language == "ln" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_ln_charset; + funclen = get_collator_data_ln_charset_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_my } else if ( rLocale.Language == "my" ) { if ( rAlgorithm == "dictionary" ) + { func = get_collator_data_my_dictionary; + funclen = get_collator_data_my_dictionary_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_ne } else if ( rLocale.Language == "ne" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_ne_charset; + funclen = get_collator_data_ne_charset_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_sid } else if ( rLocale.Language == "sid" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_sid_charset; + funclen = get_collator_data_sid_charset_length; + } #endif #if WITH_LOCALE_ALL || WITH_LOCALE_zh } else if ( rLocale.Language == "zh" && (rLocale.Country == "TW" || rLocale.Country == "HK" || rLocale.Country == "MO") ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_zh_TW_charset; + funclen = get_collator_data_zh_TW_charset_length; + } else if ( rAlgorithm == "radical" ) + { func = get_collator_data_zh_TW_radical; + funclen = get_collator_data_zh_TW_radical_length; + } else if ( rAlgorithm == "stroke" ) + { func = get_collator_data_zh_TW_stroke; + funclen = get_collator_data_zh_TW_stroke_length; + } } else if ( rLocale.Language == "zh" ) { if ( rAlgorithm == "charset" ) + { func = get_collator_data_zh_charset; + funclen = get_collator_data_zh_charset_length; + } else if ( rAlgorithm == "pinyin" ) + { func = get_collator_data_zh_pinyin; + funclen = get_collator_data_zh_pinyin_length; + } else if ( rAlgorithm == "radical" ) + { func = get_collator_data_zh_radical; + funclen = get_collator_data_zh_radical_length; + } else if ( rAlgorithm == "stroke" ) + { func = get_collator_data_zh_stroke; + funclen = get_collator_data_zh_stroke_length; + } else if ( rAlgorithm == "zhuyin" ) + { func = get_collator_data_zh_zhuyin; + funclen = get_collator_data_zh_zhuyin_length; + } #endif } #endif // DISABLE_DYNLOADING - if (func) { + if (func && funclen) { 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(); - 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(); } } diff --git a/i18npool/source/collator/gencoll_rule.cxx b/i18npool/source/collator/gencoll_rule.cxx index a80154556d73..5ba9f5d31c10 100644 --- a/i18npool/source/collator/gencoll_rule.cxx +++ b/i18npool/source/collator/gencoll_rule.cxx @@ -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, "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, "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, "\n"); fprintf (fp, "}\n"); |