On Wed, Sep 07, 2016 at 11:07:16AM +0200, Bálint Réczey wrote: > > I have not found however the proposed fix on the list thus I did not > know if you used the upstream fix. > > I think it would be a good idea to send the patch to the list before the > final upload. > Good point. I have attached the patch to this email. I intend to upload tonight or tomorrow (the last few days have been quite busy and I am playing catch up).
Regards, -Roberto -- Roberto C. Sánchez http://people.connexer.com/~roberto http://www.connexer.com
Description: fix for null termination in uloc_acceptLanguageFromHTTP Origin: upstream, http://bugs.icu-project.org/trac/changeset/39109 Index: icu-4.8.1.1/source/test/cintltst/cloctst.c =================================================================== --- icu-4.8.1.1.orig/source/test/cintltst/cloctst.c +++ icu-4.8.1.1/source/test/cintltst/cloctst.c @@ -2568,16 +2568,20 @@ static void TestAcceptLanguage(void) { const char *icuSet; /**< ? */ const char *expect; /**< The expected locale result */ UAcceptResult res; /**< The expected error code */ + UErrorCode expectStatus; /**< expected status */ } tests[] = { - /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID }, - /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID }, - /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK }, - /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED }, - /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID }, - - /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID }, /* XF */ - /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK }, /* XF */ - /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK }, /* XF */ + /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, + /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, + /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, + /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR}, + /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, + /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, /* XF */ + /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */ + /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */ + /*8*/{ 8, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */ + /*9*/{ 9, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */ + /*10*/{10, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */ + /*11*/{11, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */ }; const int32_t numTests = sizeof(tests)/sizeof(tests[0]); static const char *http[] = { @@ -2597,6 +2601,22 @@ static void TestAcceptLanguage(void) { /*5*/ "zh-xx;q=0.9, en;q=0.6", /*6*/ "ja-JA", /*7*/ "zh-xx;q=0.9", + /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", /* 156 */ + /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", /* 157 (this hits U_STRING_NOT_TERMINATED_WARNING ) */ + /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", /* 158 */ + /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", /* 163 bytes */ }; for(i=0;i<numTests;i++) { @@ -2610,17 +2630,22 @@ static void TestAcceptLanguage(void) { rc = uloc_acceptLanguageFromHTTP(tmp, 199, &outResult, http[tests[i].httpSet], available, &status); uenum_close(available); log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status)); - if(outResult != tests[i].res) { - log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i, - acceptResult( tests[i].res), + if(status != tests[i].expectStatus) { + log_err_status(status, "FAIL: expected status %s but got %s\n", u_errorName(tests[i].expectStatus), u_errorName(status)); + } else if(U_SUCCESS(tests[i].expectStatus)) { + /* don't check content if expected failure */ + if(outResult != tests[i].res) { + log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i, + acceptResult( tests[i].res), acceptResult( outResult)); - log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", + log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect,acceptResult(tests[i].res)); - } - if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) { - log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp); - log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", - i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); + } + if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) { + log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp); + log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n", + i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res)); + } } } } Index: icu-4.8.1.1/source/common/uloc.c =================================================================== --- icu-4.8.1.1.orig/source/common/uloc.c +++ icu-4.8.1.1/source/common/uloc.c @@ -2212,7 +2212,7 @@ _uloc_strtod(const char *start, char **e typedef struct { float q; int32_t dummy; /* to avoid uninitialized memory copy from qsort */ - char *locale; + char locale[ULOC_FULLNAME_CAPACITY+1]; } _acceptLangItem; static int32_t U_CALLCONV @@ -2267,7 +2267,6 @@ uloc_acceptLanguageFromHTTP(char *result int32_t i; int32_t l = (int32_t)uprv_strlen(httpAcceptLanguage); int32_t jSize; - char *tempstr; /* Use for null pointer check */ j = smallBuffer; jSize = sizeof(smallBuffer)/sizeof(smallBuffer[0]); @@ -2309,16 +2308,19 @@ uloc_acceptLanguageFromHTTP(char *result for(t=(paramEnd-1);(paramEnd>s)&&isspace(*t);t--) ; /* Check for null pointer from uprv_strndup */ - tempstr = uprv_strndup(s,(int32_t)((t+1)-s)); - if (tempstr == NULL) { - *status = U_MEMORY_ALLOCATION_ERROR; - return -1; - } - j[n].locale = tempstr; - uloc_canonicalize(j[n].locale,tmp,sizeof(tmp)/sizeof(tmp[0]),status); - if(strcmp(j[n].locale,tmp)) { - uprv_free(j[n].locale); - j[n].locale=uprv_strdup(tmp); + int32_t slen = ((t+1)-s); + if(slen > ULOC_FULLNAME_CAPACITY) { + *status = U_BUFFER_OVERFLOW_ERROR; + return -1; /* too big */ + } + uprv_strncpy(j[n].locale, s, slen); + j[n].locale[slen]=0; /* terminate */ + int32_t clen = uloc_canonicalize(j[n].locale,tmp,sizeof(tmp)/sizeof(tmp[0]),status); + if(U_FAILURE(*status)) return -1; + if((clen!=slen) || (uprv_strncmp(j[n].locale, tmp, slen))) { + /* canonicalization had an effect- copy back */ + uprv_strncpy(j[n].locale, tmp, clen); + j[n].locale[clen] = 0; /* terminate */ } #if defined(ULOC_DEBUG) /*fprintf(stderr,"%d: s <%s> q <%g>\n", n, j[n].locale, j[n].q);*/ @@ -2375,9 +2377,6 @@ uloc_acceptLanguageFromHTTP(char *result } res = uloc_acceptLanguage(result, resultAvailable, outResult, (const char**)strs, n, availableLocales, status); - for(i=0;i<n;i++) { - uprv_free(strs[i]); - } uprv_free(strs); if(j != smallBuffer) { #if defined(ULOC_DEBUG)