]>
Commit | Line | Data |
---|---|---|
12788f63 MT |
1 | 2011-03-18 Ulrich Drepper <drepper@gmail.com> |
2 | ||
3 | * posix/fnmatch.c (fnmatch): Check size of pattern in wide | |
4 | character representation. | |
5 | Partly based on a patch by Tomas Hoger <thoger@redhat.com>. | |
6 | ||
7 | 2010-11-11 Andreas Schwab <schwab@redhat.com> | |
8 | ||
9 | * posix/fnmatch_loop.c (NEW_PATTERN): Fix use of alloca. | |
10 | * posix/Makefile (tests): Add $(objpfx)tst-fnmatch-mem. | |
11 | (tst-fnmatch-ENV): Set MALLOC_TRACE. | |
12 | ($(objpfx)tst-fnmatch-mem): New rule. | |
13 | (generated): Add tst-fnmatch-mem and tst-fnmatch.mtrace. | |
14 | * posix/tst-fnmatch.c (main): Call mtrace. | |
15 | ||
16 | 2010-08-09 Ulrich Drepper <drepper@redhat.com> | |
17 | ||
18 | [BZ #11883] | |
19 | * posix/fnmatch.c: Keep track of alloca use and fall back on malloc. | |
20 | * posix/fnmatch_loop.c: Likewise. | |
21 | ||
22 | Index: glibc-2.12-2-gc4ccff1/posix/Makefile | |
23 | =================================================================== | |
24 | --- glibc-2.12-2-gc4ccff1.orig/posix/Makefile | |
25 | +++ glibc-2.12-2-gc4ccff1/posix/Makefile | |
26 | @@ -114,7 +114,8 @@ generated := $(addprefix wordexp-test-re | |
27 | tst-rxspencer-mem tst-rxspencer.mtrace tst-getconf.out \ | |
28 | tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \ | |
29 | bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \ | |
30 | - tst-vfork3-mem tst-vfork3.mtrace getconf.speclist | |
31 | + tst-vfork3-mem tst-vfork3.mtrace getconf.speclist \ | |
32 | + tst-fnmatch-mem tst-fnmatch.mtrace | |
33 | ||
34 | include ../Rules | |
35 | ||
36 | @@ -226,7 +227,7 @@ ifeq (no,$(cross-compiling)) | |
37 | tests: $(objpfx)bug-regex2-mem $(objpfx)bug-regex14-mem \ | |
38 | $(objpfx)bug-regex21-mem $(objpfx)tst-rxspencer-mem \ | |
39 | $(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem $(objpfx)tst-getconf.out \ | |
40 | - $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem | |
41 | + $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem $(objpfx)tst-fnmatch-mem | |
42 | xtests: $(objpfx)bug-ga2-mem | |
43 | endif | |
44 | ||
45 | @@ -238,6 +239,11 @@ annexc-CFLAGS = -O | |
46 | $(objpfx)annexc: annexc.c | |
47 | $(native-compile) | |
48 | ||
49 | +tst-fnmatch-ENV += MALLOC_TRACE=$(objpfx)tst-fnmatch.mtrace | |
50 | + | |
51 | +$(objpfx)tst-fnmatch-mem: $(objpfx)tst-fnmatch.out | |
52 | + $(common-objpfx)malloc/mtrace $(objpfx)tst-fnmatch.mtrace > $@ | |
53 | + | |
54 | bug-regex2-ENV = MALLOC_TRACE=$(objpfx)bug-regex2.mtrace | |
55 | ||
56 | $(objpfx)bug-regex2-mem: $(objpfx)bug-regex2.out | |
57 | Index: glibc-2.12-2-gc4ccff1/posix/fnmatch.c | |
58 | =================================================================== | |
59 | --- glibc-2.12-2-gc4ccff1.orig/posix/fnmatch.c | |
60 | +++ glibc-2.12-2-gc4ccff1/posix/fnmatch.c | |
61 | @@ -41,6 +41,12 @@ | |
62 | # include <stdlib.h> | |
63 | #endif | |
64 | ||
65 | +#ifdef _LIBC | |
66 | +# include <alloca.h> | |
67 | +#else | |
68 | +# define alloca_account(size., var) alloca (size) | |
69 | +#endif | |
70 | + | |
71 | /* For platform which support the ISO C amendement 1 functionality we | |
72 | support user defined character classes. */ | |
73 | #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) | |
74 | @@ -330,8 +336,11 @@ fnmatch (pattern, string, flags) | |
75 | mbstate_t ps; | |
76 | size_t n; | |
77 | const char *p; | |
78 | + wchar_t *wpattern_malloc = NULL; | |
79 | wchar_t *wpattern; | |
80 | + wchar_t *wstring_malloc = NULL; | |
81 | wchar_t *wstring; | |
82 | + size_t alloca_used = 0; | |
83 | ||
84 | /* Convert the strings into wide characters. */ | |
85 | memset (&ps, '\0', sizeof (ps)); | |
86 | @@ -343,7 +352,8 @@ fnmatch (pattern, string, flags) | |
87 | #endif | |
88 | if (__builtin_expect (n < 1024, 1)) | |
89 | { | |
90 | - wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); | |
91 | + wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), | |
92 | + alloca_used); | |
93 | n = mbsrtowcs (wpattern, &p, n + 1, &ps); | |
94 | if (__builtin_expect (n == (size_t) -1, 0)) | |
95 | /* Something wrong. | |
96 | @@ -365,8 +375,16 @@ fnmatch (pattern, string, flags) | |
97 | XXX Do we have to set `errno' to something which mbsrtows hasn't | |
98 | already done? */ | |
99 | return -1; | |
100 | - wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); | |
101 | + if (__builtin_expect (n >= (size_t) -1 / sizeof (wchar_t), 0)) | |
102 | + { | |
103 | + __set_errno (ENOMEM); | |
104 | + return -2; | |
105 | + } | |
106 | + wpattern_malloc = wpattern | |
107 | + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); | |
108 | assert (mbsinit (&ps)); | |
109 | + if (wpattern == NULL) | |
110 | + return -2; | |
111 | (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps); | |
112 | } | |
113 | ||
114 | @@ -379,13 +397,18 @@ fnmatch (pattern, string, flags) | |
115 | p = string; | |
116 | if (__builtin_expect (n < 1024, 1)) | |
117 | { | |
118 | - wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); | |
119 | + wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), | |
120 | + alloca_used); | |
121 | n = mbsrtowcs (wstring, &p, n + 1, &ps); | |
122 | if (__builtin_expect (n == (size_t) -1, 0)) | |
123 | - /* Something wrong. | |
124 | - XXX Do we have to set `errno' to something which mbsrtows hasn't | |
125 | - already done? */ | |
126 | - return -1; | |
127 | + { | |
128 | + /* Something wrong. | |
129 | + XXX Do we have to set `errno' to something which | |
130 | + mbsrtows hasn't already done? */ | |
131 | + free_return: | |
132 | + free (wpattern_malloc); | |
133 | + return -1; | |
134 | + } | |
135 | if (p) | |
136 | { | |
137 | memset (&ps, '\0', sizeof (ps)); | |
138 | @@ -400,19 +423,38 @@ fnmatch (pattern, string, flags) | |
139 | /* Something wrong. | |
140 | XXX Do we have to set `errno' to something which mbsrtows hasn't | |
141 | already done? */ | |
142 | - return -1; | |
143 | - wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); | |
144 | + goto free_return; | |
145 | + if (__builtin_expect (n >= (size_t) -1 / sizeof (wchar_t), 0)) | |
146 | + { | |
147 | + free (wpattern_malloc); | |
148 | + __set_errno (ENOMEM); | |
149 | + return -2; | |
150 | + } | |
151 | + | |
152 | + wstring_malloc = wstring | |
153 | + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); | |
154 | + if (wstring == NULL) | |
155 | + { | |
156 | + free (wpattern_malloc); | |
157 | + return -2; | |
158 | + } | |
159 | assert (mbsinit (&ps)); | |
160 | (void) mbsrtowcs (wstring, &string, n + 1, &ps); | |
161 | } | |
162 | ||
163 | - return internal_fnwmatch (wpattern, wstring, wstring + n, | |
164 | - flags & FNM_PERIOD, flags, NULL); | |
165 | + int res = internal_fnwmatch (wpattern, wstring, wstring + n, | |
166 | + flags & FNM_PERIOD, flags, NULL, | |
167 | + alloca_used); | |
168 | + | |
169 | + free (wstring_malloc); | |
170 | + free (wpattern_malloc); | |
171 | + | |
172 | + return res; | |
173 | } | |
174 | # endif /* mbstate_t and mbsrtowcs or _LIBC. */ | |
175 | ||
176 | return internal_fnmatch (pattern, string, string + strlen (string), | |
177 | - flags & FNM_PERIOD, flags, NULL); | |
178 | + flags & FNM_PERIOD, flags, NULL, 0); | |
179 | } | |
180 | ||
181 | # ifdef _LIBC | |
182 | Index: glibc-2.12-2-gc4ccff1/posix/fnmatch_loop.c | |
183 | =================================================================== | |
184 | --- glibc-2.12-2-gc4ccff1.orig/posix/fnmatch_loop.c | |
185 | +++ glibc-2.12-2-gc4ccff1/posix/fnmatch_loop.c | |
186 | @@ -28,22 +28,24 @@ struct STRUCT | |
187 | it matches, nonzero if not. */ | |
188 | static int FCT (const CHAR *pattern, const CHAR *string, | |
189 | const CHAR *string_end, int no_leading_period, int flags, | |
190 | - struct STRUCT *ends) | |
191 | + struct STRUCT *ends, size_t alloca_used) | |
192 | internal_function; | |
193 | static int EXT (INT opt, const CHAR *pattern, const CHAR *string, | |
194 | - const CHAR *string_end, int no_leading_period, int flags) | |
195 | + const CHAR *string_end, int no_leading_period, int flags, | |
196 | + size_t alloca_used) | |
197 | internal_function; | |
198 | static const CHAR *END (const CHAR *patternp) internal_function; | |
199 | ||
200 | static int | |
201 | internal_function | |
202 | -FCT (pattern, string, string_end, no_leading_period, flags, ends) | |
203 | +FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used) | |
204 | const CHAR *pattern; | |
205 | const CHAR *string; | |
206 | const CHAR *string_end; | |
207 | int no_leading_period; | |
208 | int flags; | |
209 | struct STRUCT *ends; | |
210 | + size_t alloca_used; | |
211 | { | |
212 | register const CHAR *p = pattern, *n = string; | |
213 | register UCHAR c; | |
214 | @@ -67,10 +69,8 @@ FCT (pattern, string, string_end, no_lea | |
215 | case L('?'): | |
216 | if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') | |
217 | { | |
218 | - int res; | |
219 | - | |
220 | - res = EXT (c, p, n, string_end, no_leading_period, | |
221 | - flags); | |
222 | + int res = EXT (c, p, n, string_end, no_leading_period, | |
223 | + flags, alloca_used); | |
224 | if (res != -1) | |
225 | return res; | |
226 | } | |
227 | @@ -99,10 +99,8 @@ FCT (pattern, string, string_end, no_lea | |
228 | case L('*'): | |
229 | if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') | |
230 | { | |
231 | - int res; | |
232 | - | |
233 | - res = EXT (c, p, n, string_end, no_leading_period, | |
234 | - flags); | |
235 | + int res = EXT (c, p, n, string_end, no_leading_period, | |
236 | + flags, alloca_used); | |
237 | if (res != -1) | |
238 | return res; | |
239 | } | |
240 | @@ -191,7 +189,7 @@ FCT (pattern, string, string_end, no_lea | |
241 | ||
242 | for (--p; n < endp; ++n, no_leading_period = 0) | |
243 | if (FCT (p, n, string_end, no_leading_period, flags2, | |
244 | - &end) == 0) | |
245 | + &end, alloca_used) == 0) | |
246 | goto found; | |
247 | } | |
248 | else if (c == L('/') && (flags & FNM_FILE_NAME)) | |
249 | @@ -200,7 +198,7 @@ FCT (pattern, string, string_end, no_lea | |
250 | ++n; | |
251 | if (n < string_end && *n == L('/') | |
252 | && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags, | |
253 | - NULL) == 0)) | |
254 | + NULL, alloca_used) == 0)) | |
255 | return 0; | |
256 | } | |
257 | else | |
258 | @@ -214,7 +212,7 @@ FCT (pattern, string, string_end, no_lea | |
259 | for (--p; n < endp; ++n, no_leading_period = 0) | |
260 | if (FOLD ((UCHAR) *n) == c | |
261 | && (FCT (p, n, string_end, no_leading_period, flags2, | |
262 | - &end) == 0)) | |
263 | + &end, alloca_used) == 0)) | |
264 | { | |
265 | found: | |
266 | if (end.pattern == NULL) | |
267 | @@ -749,7 +747,7 @@ FCT (pattern, string, string_end, no_lea | |
268 | _NL_COLLATE_SYMB_EXTRAMB); | |
269 | ||
270 | /* Locate the character in the hashing | |
271 | - table. */ | |
272 | + table. */ | |
273 | hash = elem_hash (str, c1); | |
274 | ||
275 | idx = 0; | |
276 | @@ -971,9 +969,8 @@ FCT (pattern, string, string_end, no_lea | |
277 | case L('!'): | |
278 | if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') | |
279 | { | |
280 | - int res; | |
281 | - | |
282 | - res = EXT (c, p, n, string_end, no_leading_period, flags); | |
283 | + int res = EXT (c, p, n, string_end, no_leading_period, flags, | |
284 | + alloca_used); | |
285 | if (res != -1) | |
286 | return res; | |
287 | } | |
288 | @@ -1052,26 +1049,32 @@ END (const CHAR *pattern) | |
289 | static int | |
290 | internal_function | |
291 | EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, | |
292 | - int no_leading_period, int flags) | |
293 | + int no_leading_period, int flags, size_t alloca_used) | |
294 | { | |
295 | const CHAR *startp; | |
296 | int level; | |
297 | struct patternlist | |
298 | { | |
299 | struct patternlist *next; | |
300 | + CHAR malloced; | |
301 | CHAR str[0]; | |
302 | } *list = NULL; | |
303 | struct patternlist **lastp = &list; | |
304 | size_t pattern_len = STRLEN (pattern); | |
305 | + int any_malloced = 0; | |
306 | const CHAR *p; | |
307 | const CHAR *rs; | |
308 | + int retval = 0; | |
309 | ||
310 | /* Parse the pattern. Store the individual parts in the list. */ | |
311 | level = 0; | |
312 | for (startp = p = pattern + 1; level >= 0; ++p) | |
313 | if (*p == L('\0')) | |
314 | - /* This is an invalid pattern. */ | |
315 | - return -1; | |
316 | + { | |
317 | + /* This is an invalid pattern. */ | |
318 | + retval = -1; | |
319 | + goto out; | |
320 | + } | |
321 | else if (*p == L('[')) | |
322 | { | |
323 | /* Handle brackets special. */ | |
324 | @@ -1088,8 +1091,11 @@ EXT (INT opt, const CHAR *pattern, const | |
325 | /* Skip over all characters of the list. */ | |
326 | while (*p != L(']')) | |
327 | if (*p++ == L('\0')) | |
328 | - /* This is no valid pattern. */ | |
329 | - return -1; | |
330 | + { | |
331 | + /* This is no valid pattern. */ | |
332 | + retval = -1; | |
333 | + goto out; | |
334 | + } | |
335 | } | |
336 | else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@') | |
337 | || *p == L('!')) && p[1] == L('(')) | |
338 | @@ -1102,15 +1108,25 @@ EXT (INT opt, const CHAR *pattern, const | |
339 | /* This means we found the end of the pattern. */ | |
340 | #define NEW_PATTERN \ | |
341 | struct patternlist *newp; \ | |
342 | - \ | |
343 | - if (opt == L('?') || opt == L('@')) \ | |
344 | - newp = alloca (sizeof (struct patternlist) \ | |
345 | - + (pattern_len * sizeof (CHAR))); \ | |
346 | + size_t slen = (opt == L('?') || opt == L('@') \ | |
347 | + ? pattern_len : (p - startp + 1)); \ | |
348 | + slen = sizeof (struct patternlist) + (slen * sizeof (CHAR)); \ | |
349 | + int malloced = ! __libc_use_alloca (alloca_used + slen); \ | |
350 | + if (__builtin_expect (malloced, 0)) \ | |
351 | + { \ | |
352 | + newp = malloc (slen); \ | |
353 | + if (newp == NULL) \ | |
354 | + { \ | |
355 | + retval = -2; \ | |
356 | + goto out; \ | |
357 | + } \ | |
358 | + any_malloced = 1; \ | |
359 | + } \ | |
360 | else \ | |
361 | - newp = alloca (sizeof (struct patternlist) \ | |
362 | - + ((p - startp + 1) * sizeof (CHAR))); \ | |
363 | - *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \ | |
364 | + newp = alloca_account (slen, alloca_used); \ | |
365 | newp->next = NULL; \ | |
366 | + newp->malloced = malloced; \ | |
367 | + *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \ | |
368 | *lastp = newp; \ | |
369 | lastp = &newp->next | |
370 | NEW_PATTERN; | |
371 | @@ -1131,8 +1147,9 @@ EXT (INT opt, const CHAR *pattern, const | |
372 | switch (opt) | |
373 | { | |
374 | case L('*'): | |
375 | - if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0) | |
376 | - return 0; | |
377 | + if (FCT (p, string, string_end, no_leading_period, flags, NULL, | |
378 | + alloca_used) == 0) | |
379 | + goto success; | |
380 | /* FALLTHROUGH */ | |
381 | ||
382 | case L('+'): | |
383 | @@ -1143,7 +1160,7 @@ EXT (INT opt, const CHAR *pattern, const | |
384 | current pattern. */ | |
385 | if (FCT (list->str, string, rs, no_leading_period, | |
386 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, | |
387 | - NULL) == 0 | |
388 | + NULL, alloca_used) == 0 | |
389 | /* This was successful. Now match the rest with the rest | |
390 | of the pattern. */ | |
391 | && (FCT (p, rs, string_end, | |
392 | @@ -1151,7 +1168,7 @@ EXT (INT opt, const CHAR *pattern, const | |
393 | ? no_leading_period | |
394 | : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, | |
395 | flags & FNM_FILE_NAME | |
396 | - ? flags : flags & ~FNM_PERIOD, NULL) == 0 | |
397 | + ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0 | |
398 | /* This didn't work. Try the whole pattern. */ | |
399 | || (rs != string | |
400 | && FCT (pattern - 1, rs, string_end, | |
401 | @@ -1160,18 +1177,21 @@ EXT (INT opt, const CHAR *pattern, const | |
402 | : (rs[-1] == '/' && NO_LEADING_PERIOD (flags) | |
403 | ? 1 : 0), | |
404 | flags & FNM_FILE_NAME | |
405 | - ? flags : flags & ~FNM_PERIOD, NULL) == 0))) | |
406 | + ? flags : flags & ~FNM_PERIOD, NULL, | |
407 | + alloca_used) == 0))) | |
408 | /* It worked. Signal success. */ | |
409 | - return 0; | |
410 | + goto success; | |
411 | } | |
412 | while ((list = list->next) != NULL); | |
413 | ||
414 | /* None of the patterns lead to a match. */ | |
415 | - return FNM_NOMATCH; | |
416 | + retval = FNM_NOMATCH; | |
417 | + break; | |
418 | ||
419 | case L('?'): | |
420 | - if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0) | |
421 | - return 0; | |
422 | + if (FCT (p, string, string_end, no_leading_period, flags, NULL, | |
423 | + alloca_used) == 0) | |
424 | + goto success; | |
425 | /* FALLTHROUGH */ | |
426 | ||
427 | case L('@'): | |
428 | @@ -1183,13 +1203,14 @@ EXT (INT opt, const CHAR *pattern, const | |
429 | if (FCT (STRCAT (list->str, p), string, string_end, | |
430 | no_leading_period, | |
431 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, | |
432 | - NULL) == 0) | |
433 | + NULL, alloca_used) == 0) | |
434 | /* It worked. Signal success. */ | |
435 | - return 0; | |
436 | + goto success; | |
437 | while ((list = list->next) != NULL); | |
438 | ||
439 | /* None of the patterns lead to a match. */ | |
440 | - return FNM_NOMATCH; | |
441 | + retval = FNM_NOMATCH; | |
442 | + break; | |
443 | ||
444 | case L('!'): | |
445 | for (rs = string; rs <= string_end; ++rs) | |
446 | @@ -1199,7 +1220,7 @@ EXT (INT opt, const CHAR *pattern, const | |
447 | for (runp = list; runp != NULL; runp = runp->next) | |
448 | if (FCT (runp->str, string, rs, no_leading_period, | |
449 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, | |
450 | - NULL) == 0) | |
451 | + NULL, alloca_used) == 0) | |
452 | break; | |
453 | ||
454 | /* If none of the patterns matched see whether the rest does. */ | |
455 | @@ -1209,21 +1230,34 @@ EXT (INT opt, const CHAR *pattern, const | |
456 | ? no_leading_period | |
457 | : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, | |
458 | flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, | |
459 | - NULL) == 0)) | |
460 | + NULL, alloca_used) == 0)) | |
461 | /* This is successful. */ | |
462 | - return 0; | |
463 | + goto success; | |
464 | } | |
465 | ||
466 | /* None of the patterns together with the rest of the pattern | |
467 | lead to a match. */ | |
468 | - return FNM_NOMATCH; | |
469 | + retval = FNM_NOMATCH; | |
470 | + break; | |
471 | ||
472 | default: | |
473 | assert (! "Invalid extended matching operator"); | |
474 | + retval = -1; | |
475 | break; | |
476 | } | |
477 | ||
478 | - return -1; | |
479 | + success: | |
480 | + out: | |
481 | + if (any_malloced) | |
482 | + while (list != NULL) | |
483 | + { | |
484 | + struct patternlist *old = list; | |
485 | + list = list->next; | |
486 | + if (old->malloced) | |
487 | + free (old); | |
488 | + } | |
489 | + | |
490 | + return retval; | |
491 | } | |
492 | ||
493 | ||
494 | Index: glibc-2.12-2-gc4ccff1/posix/tst-fnmatch.c | |
495 | =================================================================== | |
496 | --- glibc-2.12-2-gc4ccff1.orig/posix/tst-fnmatch.c | |
497 | +++ glibc-2.12-2-gc4ccff1/posix/tst-fnmatch.c | |
498 | @@ -25,6 +25,7 @@ | |
499 | #include <stdlib.h> | |
500 | #include <string.h> | |
501 | #include <sys/types.h> | |
502 | +#include <mcheck.h> | |
503 | ||
504 | ||
505 | static char *next_input (char **line, int first, int last); | |
506 | @@ -46,6 +47,8 @@ main (void) | |
507 | size_t escpatternlen = 0; | |
508 | int nr = 0; | |
509 | ||
510 | + mtrace (); | |
511 | + | |
512 | /* Read lines from stdin with the following format: | |
513 | ||
514 | locale input-string match-string flags result |