diff --git a/icu.spec b/icu.spec index 8591b2d..5b77f67 100644 --- a/icu.spec +++ b/icu.spec @@ -2,7 +2,7 @@ Name: icu Version: 57.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: International Components for Unicode License: MIT and UCD and Public Domain @@ -19,6 +19,7 @@ Patch3: icu.7601.Indic-ccmp.patch Patch4: gennorm2-man.patch Patch5: icuinfo-man.patch Patch6: armv7hl-disable-tests.patch +Patch7: rhbz1360340-icu-changeset-39109.patch %description Tools and utilities for developing with icu. @@ -67,6 +68,7 @@ BuildArch: noarch %ifarch armv7hl %patch6 -p1 -b .armv7hl-disable-tests.patch %endif +%patch7 -p1 -b .rhbz1360340-icu-changeset-39109.patch %build @@ -195,6 +197,9 @@ LD_LIBRARY_PATH=lib:stubdata:tools/ctestfw:$LD_LIBRARY_PATH bin/uconv -l %changelog +* Tue Nov 01 2016 Eike Rathke - 57.1-2 +- Resolves: rhbz#1360340 CVE-2016-6293 + * Fri Apr 15 2016 Eike Rathke - 57.1-1 - upgrade to upstream ICU 57.1 diff --git a/rhbz1360340-icu-changeset-39109.patch b/rhbz1360340-icu-changeset-39109.patch new file mode 100644 index 0000000..90f4d1e --- /dev/null +++ b/rhbz1360340-icu-changeset-39109.patch @@ -0,0 +1,244 @@ +# Offsets corected from https://ssl.icu-project.org/trac/changeset/39109 +diff -ru icu.orig/source/common/uloc.cpp icu/source/common/uloc.cpp +--- icu.orig/source/common/uloc.cpp 2016-03-23 21:50:12.000000000 +0100 ++++ icu/source/common/uloc.cpp 2016-11-01 15:21:16.542151312 +0100 +@@ -2246,7 +2246,7 @@ + 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 +@@ -2288,9 +2288,7 @@ + UEnumeration* availableLocales, + UErrorCode *status) + { +- _acceptLangItem *j; +- _acceptLangItem smallBuffer[30]; +- char **strs; ++ MaybeStackArray<_acceptLangItem, 4> items; // Struct for collecting items. + char tmp[ULOC_FULLNAME_CAPACITY +1]; + int32_t n = 0; + const char *itemEnd; +@@ -2300,11 +2298,7 @@ + int32_t res; + int32_t i; + int32_t l = (int32_t)uprv_strlen(httpAcceptLanguage); +- int32_t jSize; +- char *tempstr; /* Use for null pointer check */ + +- j = smallBuffer; +- jSize = UPRV_LENGTHOF(smallBuffer); + if(U_FAILURE(*status)) { + return -1; + } +@@ -2332,27 +2326,29 @@ + while(isspace(*t)) { + t++; + } +- j[n].q = (float)_uloc_strtod(t,NULL); ++ items[n].q = (float)_uloc_strtod(t,NULL); + } else { + /* no semicolon - it's 1.0 */ +- j[n].q = 1.0f; ++ items[n].q = 1.0f; + paramEnd = itemEnd; + } +- j[n].dummy=0; ++ items[n].dummy=0; + /* eat spaces prior to semi */ + 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,UPRV_LENGTHOF(tmp),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(items[n].locale, s, slen); ++ items[n].locale[slen]=0; // terminate ++ int32_t clen = uloc_canonicalize(items[n].locale, tmp, UPRV_LENGTHOF(tmp)-1, status); ++ if(U_FAILURE(*status)) return -1; ++ if((clen!=slen) || (uprv_strncmp(items[n].locale, tmp, slen))) { ++ // canonicalization had an effect- copy back ++ uprv_strncpy(items[n].locale, tmp, clen); ++ items[n].locale[clen] = 0; // terminate + } + #if defined(ULOC_DEBUG) + /*fprintf(stderr,"%d: s <%s> q <%g>\n", n, j[n].locale, j[n].q);*/ +@@ -2362,63 +2358,29 @@ + while(*s==',') { /* eat duplicate commas */ + s++; + } +- if(n>=jSize) { +- if(j==smallBuffer) { /* overflowed the small buffer. */ +- j = static_cast<_acceptLangItem *>(uprv_malloc(sizeof(j[0])*(jSize*2))); +- if(j!=NULL) { +- uprv_memcpy(j,smallBuffer,sizeof(j[0])*jSize); +- } ++ if(n>=items.getCapacity()) { // If we need more items ++ if(NULL == items.resize(items.getCapacity()*2, items.getCapacity())) { ++ *status = U_MEMORY_ALLOCATION_ERROR; ++ return -1; ++ } + #if defined(ULOC_DEBUG) +- fprintf(stderr,"malloced at size %d\n", jSize); ++ fprintf(stderr,"malloced at size %d\n", items.getCapacity()); + #endif +- } else { +- j = static_cast<_acceptLangItem *>(uprv_realloc(j, sizeof(j[0])*jSize*2)); +-#if defined(ULOC_DEBUG) +- fprintf(stderr,"re-alloced at size %d\n", jSize); +-#endif +- } +- jSize *= 2; +- if(j==NULL) { +- *status = U_MEMORY_ALLOCATION_ERROR; +- return -1; +- } + } + } +- uprv_sortArray(j, n, sizeof(j[0]), uloc_acceptLanguageCompare, NULL, TRUE, status); ++ uprv_sortArray(items.getAlias(), n, sizeof(items[0]), uloc_acceptLanguageCompare, NULL, TRUE, status); ++ LocalArray strs(new const char*[n], *status); + if(U_FAILURE(*status)) { +- if(j != smallBuffer) { +-#if defined(ULOC_DEBUG) +- fprintf(stderr,"freeing j %p\n", j); +-#endif +- uprv_free(j); +- } +- return -1; +- } +- strs = static_cast(uprv_malloc((size_t)(sizeof(strs[0])*n))); +- /* Check for null pointer */ +- if (strs == NULL) { +- uprv_free(j); /* Free to avoid memory leak */ +- *status = U_MEMORY_ALLOCATION_ERROR; +- return -1; ++ return -1; + } + for(i=0;i q <%g>\n", i, j[i].locale, j[i].q);*/ + #endif +- strs[i]=j[i].locale; ++ strs[i]=items[i].locale; + } + res = uloc_acceptLanguage(result, resultAvailable, outResult, +- (const char**)strs, n, availableLocales, status); +- for(i=0;i0)&&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)); ++ } + } + } + }