1 |
Index: /source/common/uloc.cpp
|
2 |
===================================================================
|
3 |
--- /source/common/uloc.cpp (revision 39108)
|
4 |
+++ /source/common/uloc.cpp (revision 39109)
|
5 |
@@ -2247,5 +2247,5 @@
|
6 |
float q;
|
7 |
int32_t dummy; /* to avoid uninitialized memory copy from qsort */
|
8 |
- char *locale;
|
9 |
+ char locale[ULOC_FULLNAME_CAPACITY+1];
|
10 |
} _acceptLangItem;
|
11 |
|
12 |
@@ -2289,7 +2289,5 @@
|
13 |
UErrorCode *status)
|
14 |
{
|
15 |
- _acceptLangItem *j;
|
16 |
- _acceptLangItem smallBuffer[30];
|
17 |
- char **strs;
|
18 |
+ MaybeStackArray<_acceptLangItem, 4> items; // Struct for collecting items.
|
19 |
char tmp[ULOC_FULLNAME_CAPACITY +1];
|
20 |
int32_t n = 0;
|
21 |
@@ -2301,9 +2299,5 @@
|
22 |
int32_t i;
|
23 |
int32_t l = (int32_t)uprv_strlen(httpAcceptLanguage);
|
24 |
- int32_t jSize;
|
25 |
- char *tempstr; /* Use for null pointer check */
|
26 |
-
|
27 |
- j = smallBuffer;
|
28 |
- jSize = sizeof(smallBuffer)/sizeof(smallBuffer[0]);
|
29 |
+
|
30 |
if(U_FAILURE(*status)) {
|
31 |
return -1;
|
32 |
@@ -2333,25 +2327,27 @@
|
33 |
t++;
|
34 |
}
|
35 |
- j[n].q = (float)_uloc_strtod(t,NULL);
|
36 |
+ items[n].q = (float)_uloc_strtod(t,NULL);
|
37 |
} else {
|
38 |
/* no semicolon - it's 1.0 */
|
39 |
- j[n].q = 1.0f;
|
40 |
+ items[n].q = 1.0f;
|
41 |
paramEnd = itemEnd;
|
42 |
}
|
43 |
- j[n].dummy=0;
|
44 |
+ items[n].dummy=0;
|
45 |
/* eat spaces prior to semi */
|
46 |
for(t=(paramEnd-1);(paramEnd>s)&&isspace(*t);t--)
|
47 |
;
|
48 |
- /* Check for null pointer from uprv_strndup */
|
49 |
- tempstr = uprv_strndup(s,(int32_t)((t+1)-s));
|
50 |
- if (tempstr == NULL) {
|
51 |
- *status = U_MEMORY_ALLOCATION_ERROR;
|
52 |
- return -1;
|
53 |
- }
|
54 |
- j[n].locale = tempstr;
|
55 |
- uloc_canonicalize(j[n].locale,tmp,sizeof(tmp)/sizeof(tmp[0]),status);
|
56 |
- if(strcmp(j[n].locale,tmp)) {
|
57 |
- uprv_free(j[n].locale);
|
58 |
- j[n].locale=uprv_strdup(tmp);
|
59 |
+ int32_t slen = ((t+1)-s);
|
60 |
+ if(slen > ULOC_FULLNAME_CAPACITY) {
|
61 |
+ *status = U_BUFFER_OVERFLOW_ERROR;
|
62 |
+ return -1; // too big
|
63 |
+ }
|
64 |
+ uprv_strncpy(items[n].locale, s, slen);
|
65 |
+ items[n].locale[slen]=0; // terminate
|
66 |
+ int32_t clen = uloc_canonicalize(items[n].locale, tmp, sizeof(tmp)/sizeof(tmp[0])-1, status);
|
67 |
+ if(U_FAILURE(*status)) return -1;
|
68 |
+ if((clen!=slen) || (uprv_strncmp(items[n].locale, tmp, slen))) {
|
69 |
+ // canonicalization had an effect- copy back
|
70 |
+ uprv_strncpy(items[n].locale, tmp, clen);
|
71 |
+ items[n].locale[clen] = 0; // terminate
|
72 |
}
|
73 |
#if defined(ULOC_DEBUG)
|
74 |
@@ -2363,42 +2359,20 @@
|
75 |
s++;
|
76 |
}
|
77 |
- if(n>=jSize) {
|
78 |
- if(j==smallBuffer) { /* overflowed the small buffer. */
|
79 |
- j = static_cast<_acceptLangItem *>(uprv_malloc(sizeof(j[0])*(jSize*2)));
|
80 |
- if(j!=NULL) {
|
81 |
- uprv_memcpy(j,smallBuffer,sizeof(j[0])*jSize);
|
82 |
- }
|
83 |
+ if(n>=items.getCapacity()) { // If we need more items
|
84 |
+ if(NULL == items.resize(items.getCapacity()*2, items.getCapacity())) {
|
85 |
+ *status = U_MEMORY_ALLOCATION_ERROR;
|
86 |
+ return -1;
|
87 |
+ }
|
88 |
#if defined(ULOC_DEBUG)
|
89 |
- fprintf(stderr,"malloced at size %d\n", jSize);
|
90 |
+ fprintf(stderr,"malloced at size %d\n", items.getCapacity());
|
91 |
#endif
|
92 |
- } else {
|
93 |
- j = static_cast<_acceptLangItem *>(uprv_realloc(j, sizeof(j[0])*jSize*2));
|
94 |
-#if defined(ULOC_DEBUG)
|
95 |
- fprintf(stderr,"re-alloced at size %d\n", jSize);
|
96 |
-#endif
|
97 |
- }
|
98 |
- jSize *= 2;
|
99 |
- if(j==NULL) {
|
100 |
- *status = U_MEMORY_ALLOCATION_ERROR;
|
101 |
- return -1;
|
102 |
- }
|
103 |
- }
|
104 |
- }
|
105 |
- uprv_sortArray(j, n, sizeof(j[0]), uloc_acceptLanguageCompare, NULL, TRUE, status);
|
106 |
+ }
|
107 |
+ }
|
108 |
+ uprv_sortArray(items.getAlias(), n, sizeof(items[0]), uloc_acceptLanguageCompare, NULL, TRUE, status);
|
109 |
+ LocalArray<const char*> strs(new const char*[n]);
|
110 |
+ if (strs == NULL)
|
111 |
+ *status = U_MEMORY_ALLOCATION_ERROR;
|
112 |
if(U_FAILURE(*status)) {
|
113 |
- if(j != smallBuffer) {
|
114 |
-#if defined(ULOC_DEBUG)
|
115 |
- fprintf(stderr,"freeing j %p\n", j);
|
116 |
-#endif
|
117 |
- uprv_free(j);
|
118 |
- }
|
119 |
- return -1;
|
120 |
- }
|
121 |
- strs = static_cast<char **>(uprv_malloc((size_t)(sizeof(strs[0])*n)));
|
122 |
- /* Check for null pointer */
|
123 |
- if (strs == NULL) {
|
124 |
- uprv_free(j); /* Free to avoid memory leak */
|
125 |
- *status = U_MEMORY_ALLOCATION_ERROR;
|
126 |
- return -1;
|
127 |
+ return -1;
|
128 |
}
|
129 |
for(i=0;i<n;i++) {
|
130 |
@@ -2406,18 +2378,8 @@
|
131 |
/*fprintf(stderr,"%d: s <%s> q <%g>\n", i, j[i].locale, j[i].q);*/
|
132 |
#endif
|
133 |
- strs[i]=j[i].locale;
|
134 |
+ strs[i]=items[i].locale;
|
135 |
}
|
136 |
res = uloc_acceptLanguage(result, resultAvailable, outResult,
|
137 |
- (const char**)strs, n, availableLocales, status);
|
138 |
- for(i=0;i<n;i++) {
|
139 |
- uprv_free(strs[i]);
|
140 |
- }
|
141 |
- uprv_free(strs);
|
142 |
- if(j != smallBuffer) {
|
143 |
-#if defined(ULOC_DEBUG)
|
144 |
- fprintf(stderr,"freeing j %p\n", j);
|
145 |
-#endif
|
146 |
- uprv_free(j);
|
147 |
- }
|
148 |
+ strs.getAlias(), n, availableLocales, status);
|
149 |
return res;
|
150 |
}
|
151 |
Index: /source/test/cintltst/cloctst.c
|
152 |
===================================================================
|
153 |
--- /source/test/cintltst/cloctst.c (revision 39108)
|
154 |
+++ /source/test/cintltst/cloctst.c (revision 39109)
|
155 |
@@ -2776,14 +2776,18 @@
|
156 |
const char *expect; /**< The expected locale result */
|
157 |
UAcceptResult res; /**< The expected error code */
|
158 |
+ UErrorCode expectStatus; /**< expected status */
|
159 |
} tests[] = {
|
160 |
- /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID },
|
161 |
- /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID },
|
162 |
- /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK },
|
163 |
- /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED },
|
164 |
- /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID },
|
165 |
-
|
166 |
- /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID }, /* XF */
|
167 |
- /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK }, /* XF */
|
168 |
- /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK }, /* XF */
|
169 |
+ /*0*/{ 0, NULL, "mt_MT", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
|
170 |
+ /*1*/{ 1, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
|
171 |
+ /*2*/{ 2, NULL, "en", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR},
|
172 |
+ /*3*/{ 3, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR},
|
173 |
+ /*4*/{ 4, NULL, "es", ULOC_ACCEPT_VALID, U_ZERO_ERROR},
|
174 |
+ /*5*/{ 5, NULL, "en", ULOC_ACCEPT_VALID, U_ZERO_ERROR}, /* XF */
|
175 |
+ /*6*/{ 6, NULL, "ja", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */
|
176 |
+ /*7*/{ 7, NULL, "zh", ULOC_ACCEPT_FALLBACK, U_ZERO_ERROR}, /* XF */
|
177 |
+ /*8*/{ 8, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */
|
178 |
+ /*9*/{ 9, NULL, "", ULOC_ACCEPT_FAILED, U_ZERO_ERROR }, /* */
|
179 |
+ /*10*/{10, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */
|
180 |
+ /*11*/{11, NULL, "", ULOC_ACCEPT_FAILED, U_BUFFER_OVERFLOW_ERROR }, /* */
|
181 |
};
|
182 |
const int32_t numTests = sizeof(tests)/sizeof(tests[0]);
|
183 |
@@ -2801,8 +2805,23 @@
|
184 |
"xxx-yyy;q=.01, xxx-yyy;q=.01, xxx-yyy;q=.01, xx-yy;q=.1, "
|
185 |
"es",
|
186 |
-
|
187 |
/*5*/ "zh-xx;q=0.9, en;q=0.6",
|
188 |
/*6*/ "ja-JA",
|
189 |
/*7*/ "zh-xx;q=0.9",
|
190 |
+ /*08*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
191 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
192 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
193 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 156
|
194 |
+ /*09*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
195 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
196 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
197 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB", // 157 (this hits U_STRING_NOT_TERMINATED_WARNING )
|
198 |
+ /*10*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
199 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
200 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
201 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC", // 158
|
202 |
+ /*11*/ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
203 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
204 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
205 |
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", // 163 bytes
|
206 |
};
|
207 |
|
208 |
@@ -2819,5 +2838,9 @@
|
209 |
uenum_close(available);
|
210 |
log_verbose(" got %s, %s [%s]\n", tmp[0]?tmp:"(EMPTY)", acceptResult(outResult), u_errorName(status));
|
211 |
- if(outResult != tests[i].res) {
|
212 |
+ if(status != tests[i].expectStatus) {
|
213 |
+ log_err_status(status, "FAIL: expected status %s but got %s\n", u_errorName(tests[i].expectStatus), u_errorName(status));
|
214 |
+ } else if(U_SUCCESS(tests[i].expectStatus)) {
|
215 |
+ /* don't check content if expected failure */
|
216 |
+ if(outResult != tests[i].res) {
|
217 |
log_err_status(status, "FAIL: #%d: expected outResult of %s but got %s\n", i,
|
218 |
acceptResult( tests[i].res),
|
219 |
@@ -2825,9 +2848,10 @@
|
220 |
log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
|
221 |
i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect,acceptResult(tests[i].res));
|
222 |
- }
|
223 |
- if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
|
224 |
- log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp);
|
225 |
- log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
|
226 |
- i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
|
227 |
+ }
|
228 |
+ if((outResult>0)&&uprv_strcmp(tmp, tests[i].expect)) {
|
229 |
+ log_err_status(status, "FAIL: #%d: expected %s but got %s\n", i, tests[i].expect, tmp);
|
230 |
+ log_info("test #%d: http[%s], ICU[%s], expect %s, %s\n",
|
231 |
+ i, http[tests[i].httpSet], tests[i].icuSet, tests[i].expect, acceptResult(tests[i].res));
|
232 |
+ }
|
233 |
}
|
234 |
}
|