aboutsummaryrefslogtreecommitdiffstats
path: root/main/icu/CVE-2016-6293.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/icu/CVE-2016-6293.patch')
-rw-r--r--main/icu/CVE-2016-6293.patch232
1 files changed, 232 insertions, 0 deletions
diff --git a/main/icu/CVE-2016-6293.patch b/main/icu/CVE-2016-6293.patch
new file mode 100644
index 0000000000..fc4562c1d0
--- /dev/null
+++ b/main/icu/CVE-2016-6293.patch
@@ -0,0 +1,232 @@
+Index: /icu/trunk/source/common/uloc.cpp
+===================================================================
+--- source/common/uloc.cpp (revision 39108)
++++ source/common/uloc.cpp (revision 39109)
+@@ -2249,5 +2249,5 @@
+ float q;
+ int32_t dummy; /* to avoid uninitialized memory copy from qsort */
+- char *locale;
++ char locale[ULOC_FULLNAME_CAPACITY+1];
+ } _acceptLangItem;
+
+@@ -2291,7 +2291,5 @@
+ 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;
+@@ -2303,9 +2301,5 @@
+ 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;
+@@ -2335,25 +2329,27 @@
+ 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)
+@@ -2365,42 +2361,18 @@
+ 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<const char*> 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<char **>(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<n;i++) {
+@@ -2408,18 +2380,8 @@
+ /*fprintf(stderr,"%d: s <%s> 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;i<n;i++) {
+- uprv_free(strs[i]);
+- }
+- uprv_free(strs);
+- if(j != smallBuffer) {
+-#if defined(ULOC_DEBUG)
+- fprintf(stderr,"freeing j %p\n", j);
+-#endif
+- uprv_free(j);
+- }
++ strs.getAlias(), n, availableLocales, status);
+ return res;
+ }
+Index: /icu/trunk/source/test/cintltst/cloctst.c
+===================================================================
+--- source/test/cintltst/cloctst.c (revision 39108)
++++ source/test/cintltst/cloctst.c (revision 39109)
+@@ -2778,14 +2778,18 @@
+ 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 = UPRV_LENGTHOF(tests);
+@@ -2803,8 +2807,23 @@
+ "xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
+ "es",
+-
+ /*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
+ };
+
+@@ -2821,5 +2840,9 @@
+ uenum_close(available);
+ log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status));
+- if(outResult != 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),
+@@ -2827,9 +2850,10 @@
+ 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));
++ }
+ }
+ }