diff options
author | Rich Megginson <rmeggins@redhat.com> | 2008-08-28 16:54:43 +0000 |
---|---|---|
committer | Rich Megginson <rmeggins@redhat.com> | 2008-08-28 16:54:43 +0000 |
commit | 4a86db73ad8ee0fa37307415616df050ac0a2f7c (patch) | |
tree | a8ecc3be64d29b05dbf5b657fc8ed615d3d842cb | |
parent | c6b81ccab7205fac0858af897c9931223d518516 (diff) | |
download | ds-Directory71RtmBranch.tar.gz ds-Directory71RtmBranch.tar.xz ds-Directory71RtmBranch.zip |
Resolves: bug 413531ds71sp7rc_20080812Directory71Sp7RtmRhelHpuxSolaris_20080812Directory71Sp7RtmRhelHpuxSolarisDirectory71RtmBranch
Bug Description: Web browser accepted languages configuration causes dsgw CGI binaries to segfault
Reviewed by: nhosoi (Thanks!)
Files: ldapserver/lib/libsi18n/acclanglist.c adminserver/lib/libsi18n/acclanglist.c
Branch: Directory71RtmBranch
Fix Description: The CGI code looks for localized files using the following order: /path/lang_co, /path/lang, /path/"en". It uses the HTTP Accept-Language string to look for languages the user wants, in the order that the user wants. The user may specify "fr_CA, fr_FR, fr_BE" for example - the user does not have to specify "fr". But we want to use /path/"fr" in that case, if we don't have /path/"fr_CA" nor any of the other lang_co directories. The code in XP_AccLangList attempts to scan through the parsed list and add the two char lang codes if they are not already in the list. However, the code that appended them did not check for buffer overflow The new code, while not being quite as efficient as the old code, does correctly check for overflow and should be easier to read.
Platforms tested: RHEL5, HP-UX
Flag Day: no
Doc impact: no
QA impact: Yes
New Tests integrated into TET: Yes - we should add something to the Admin Server and DSGW test plans to test this case.
-rw-r--r-- | lib/libsi18n/acclanglist.c | 100 |
1 files changed, 66 insertions, 34 deletions
diff --git a/lib/libsi18n/acclanglist.c b/lib/libsi18n/acclanglist.c index 1fd4f15f..9f910aa6 100644 --- a/lib/libsi18n/acclanglist.c +++ b/lib/libsi18n/acclanglist.c @@ -75,7 +75,7 @@ AcceptLangList(const char* AcceptLanguage, char* cPtr2; int i; int j; - int countLang = 0; + size_t countLang = 0; input = strdup(AcceptLanguage); if (input == (char*)NULL){ @@ -95,8 +95,6 @@ AcceptLangList(const char* AcceptLanguage, } *cPtr2 = '\0'; - countLang = 0; - if (strchr(input,';')) { /* deal with the quality values */ @@ -123,7 +121,7 @@ AcceptLangList(const char* AcceptLanguage, /* sort according to decending qvalue */ /* not a very good algorithm, but count is not likely large */ - for ( i=0 ; i<countLang-1 ; i++ ) { + for ( i=0 ; (countLang>0) && (i<countLang-1) ; i++ ) { for ( j=i+1 ; j<countLang ; j++ ) { if (qvalue[i]<qvalue[j]) { qSwap = qvalue[i]; @@ -158,11 +156,48 @@ AcceptLangList(const char* AcceptLanguage, } /* + See if lang is in the given list. lang should be the two character + lang code. List must contain the exact string, so lang "en" will + match if "en" is in the list, but will not match "en_us" +*/ +static int +langIsInList(const char *lang, size_t listsize, ACCEPT_LANGUAGE_LIST accll) +{ + int retval = 0; + int ii; + + for (ii = 0; !retval && (ii < listsize); ++ii) { + if (!strcmp(lang, accll[ii])) { + retval = 1; + } + } + + return retval; +} + +/* * Get prioritized locale list from NLS_AcceptLangList * * Add additonal language to the list for fallback if locale * name is language_region * + * I think the intention of this code is to take a list sorted + * in q order (by AcceptLangList above) and make sure the list + * has the 2 char lang code if only region codes were given. + * For example, given the list "en_gb, en_us, fr_ca, fr_fr" + * the output list should look like this: + * "en_gb, en_us, fr_ca, fr_fr, en, fr" + * But if the input list is like this: + * "en_gb, en_us, en, fr_ca, fr_fr" - the code should not + * add an "en" since it is already explicitly called out + * in the list + * Also note - the input list may not be well formed - + * It could look like this e.g. + * "en_us, en_gb, fr_ca, en_us, fr_ca, en_gb, fr_fr" + * So we cannot make any assumptions about the list + * having no duplicates or having the languages all + * grouped together. + * */ @@ -170,50 +205,47 @@ int XP_AccLangList(char* AcceptLanguage, ACCEPT_LANGUAGE_LIST AcceptLanguageList) { - int i; - int n; + size_t i; + size_t n; char *defaultLanguage = "en"; ACCEPT_LANGUAGE_LIST curLanguageList; - int index = 0; - char lang[3]; - int k; + size_t maxelems = sizeof(curLanguageList)/sizeof(curLanguageList[0]); + size_t index = 0; + /* parse the given Accept-Language string and sort according + to q values */ n = AcceptLangList(AcceptLanguage, curLanguageList); if (n == 0) return 0; - memset(lang, 0, 3); - for (i = 0; i < n; i++) { - if (*lang && (strncmp(lang, curLanguageList[i], 2) != 0)) { - /* add lang if current language is the last occurence in the list */ - for (k = i+1; (k < n) && strncmp(curLanguageList[k],lang,2); k++); - - if (k == n) { - strcpy(AcceptLanguageList[index++], lang); - *lang = '\0'; - } - } - + /* first, just copy curLanguageList to AcceptLanguageList */ + for (i = 0; (i < n) && (index < maxelems); i++) { strcpy(AcceptLanguageList[index++], curLanguageList[i]); + } - /* Add current language for future appending.,make sure it's not on list */ + /* next, append the lang without the country code in the + order that the country first appears in the list, if + the lang is not already in the list */ + for (i = 0; (i < n) && (index < maxelems); i++) { + /* if current item is a lang + co, grab the lang part */ if ((strlen(curLanguageList[i]) > 2) && (curLanguageList[i][2] == '_')) { - strncpy(lang, curLanguageList[i], 2); - for (k = 0; (k < index) && strcmp(AcceptLanguageList[k], lang); k++); + char lang[3]; + strncpy(lang, curLanguageList[i], 2); + lang[sizeof(lang)-1] = 0; - if (k != index) lang[0] = '\0'; - } + if (!langIsInList(lang, index, AcceptLanguageList)) { + /* lang not already in list - append to list */ + strcpy(AcceptLanguageList[index++], lang); + } + } } - if (lang[0] != '\0') - strcpy(AcceptLanguageList[index++], lang); /* add new lang */ - - /* Append defaultLanguage if it's not in the list */ - for (i = 0; (i < index) && strcmp(AcceptLanguageList[i], defaultLanguage); i++); - - if (i == index) + /* Append defaultLanguage if it's not in the list and we have room */ + if ((index < maxelems) && + !langIsInList(defaultLanguage, index, AcceptLanguageList)) { strcpy(AcceptLanguageList[index++], defaultLanguage); + } - return index; + return (int)index; } |