]> sourceware.org Git - glibc.git/blame - posix/fnmatch.c
Test errno setting on strtod overflow in tst-strtod-round
[glibc.git] / posix / fnmatch.c
CommitLineData
dff8da6b 1/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
c84142e8 2 This file is part of the GNU C Library.
28f540f4 3
41bdb6e2
AJ
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
41bdb6e2 9 The GNU C Library is distributed in the hope that it will be useful,
c84142e8
UD
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
28f540f4 17
25286454
AZ
18#ifndef _LIBC
19# include <libc-config.h>
28f540f4
RM
20#endif
21
97aa195c
RM
22/* Enable GNU extensions in fnmatch.h. */
23#ifndef _GNU_SOURCE
25286454 24# define _GNU_SOURCE 1
97aa195c
RM
25#endif
26
25286454
AZ
27#include <fnmatch.h>
28
1fc82a56 29#include <assert.h>
28f540f4 30#include <errno.h>
28f540f4 31#include <ctype.h>
3f3dd810 32#include <string.h>
25286454 33#include <stdlib.h>
25286454
AZ
34#include <wchar.h>
35#include <wctype.h>
36#include <stddef.h>
37#include <stdbool.h>
28f540f4 38
acb5ee2e
UD
39/* We need some of the locale data (the collation sequence information)
40 but there is no interface to get this information in general. Therefore
41 we support a correct implementation only in glibc. */
42#ifdef _LIBC
43# include "../locale/localeinfo.h"
04ea3b0f 44# include "../locale/coll-lookup.h"
821a6bb4 45# include <shlib-compat.h>
acb5ee2e
UD
46
47# define CONCAT(a,b) __CONCAT(a,b)
25286454
AZ
48# define btowc __btowc
49# define iswctype __iswctype
4aebaa6b 50# define mbsrtowcs __mbsrtowcs
25286454
AZ
51# define mempcpy __mempcpy
52# define strnlen __strnlen
53# define towlower __towlower
54# define wcscat __wcscat
55# define wcslen __wcslen
56# define wctype __wctype
57# define wmemchr __wmemchr
58# define wmempcpy __wmempcpy
821a6bb4
UD
59# define fnmatch __fnmatch
60extern int fnmatch (const char *pattern, const char *string, int flags);
acb5ee2e
UD
61#endif
62
25286454 63#ifdef _LIBC
d7ee6bd8 64# if __GNUC__ >= 7
25286454
AZ
65# define FALLTHROUGH __attribute__ ((__fallthrough__))
66# else
67# define FALLTHROUGH ((void) 0)
68# endif
69#else
70# include "attribute.h"
71#endif
28f540f4 72
25286454
AZ
73#include <intprops.h>
74#include <flexmember.h>
a79328c7 75#include <scratch_buffer.h>
28f540f4 76
25286454
AZ
77#ifdef _LIBC
78typedef ptrdiff_t idx_t;
79#else
80# include "idx.h"
81#endif
28f540f4 82
25286454
AZ
83/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
84#define NO_LEADING_PERIOD(flags) \
85 ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
ba1ffaa1 86
25286454
AZ
87/* Provide support for user-defined character classes, based on the functions
88 from ISO C 90 amendment 1. */
89#ifdef CHARCLASS_NAME_MAX
90# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
91#else
a9ddb793
UD
92/* This shouldn't happen but some implementation might still have this
93 problem. Use a reasonable default value. */
25286454
AZ
94# define CHAR_CLASS_MAX_LENGTH 256
95#endif
1fc82a56 96
25286454 97#define IS_CHAR_CLASS(string) wctype (string)
a9ddb793
UD
98
99/* Avoid depending on library functions or files
100 whose names are inconsistent. */
ba1ffaa1 101
955994e1
UD
102/* Global variable. */
103static int posixly_correct;
104
6d52618b 105/* Note that this evaluates C many times. */
25286454
AZ
106#define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
107#define CHAR char
108#define UCHAR unsigned char
109#define INT int
110#define FCT internal_fnmatch
111#define EXT ext_match
112#define END end_pattern
113#define STRUCT fnmatch_struct
114#define L_(CS) CS
115#define BTOWC(C) btowc (C)
116#define STRLEN(S) strlen (S)
117#define STRCAT(D, S) strcat (D, S)
118#define MEMPCPY(D, S, N) mempcpy (D, S, N)
119#define MEMCHR(S, C, N) memchr (S, C, N)
120#define WIDE_CHAR_VERSION 0
121#ifdef _LIBC
8c0ab919
RM
122# include <locale/weight.h>
123# define FINDIDX findidx
25286454
AZ
124#endif
125#include "fnmatch_loop.c"
126
127
128#define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
129#define CHAR wchar_t
130#define UCHAR wint_t
131#define INT wint_t
132#define FCT internal_fnwmatch
133#define EXT ext_wmatch
134#define END end_wpattern
135#define L_(CS) L##CS
136#define BTOWC(C) (C)
137#define STRLEN(S) wcslen (S)
138#define STRCAT(D, S) wcscat (D, S)
139#define MEMPCPY(D, S, N) wmempcpy (D, S, N)
140#define MEMCHR(S, C, N) wmemchr (S, C, N)
141#define WIDE_CHAR_VERSION 1
142#ifdef _LIBC
8c0ab919
RM
143/* Change the name the header defines so it doesn't conflict with
144 the <locale/weight.h> version included above. */
25286454
AZ
145# define findidx findidxwc
146# include <locale/weightwc.h>
147# undef findidx
148# define FINDIDX findidxwc
149#endif
acb5ee2e 150
25286454 151#undef IS_CHAR_CLASS
1fc82a56 152/* We have to convert the wide character string in a multibyte string. But
5e463393
UD
153 we know that the character class names consist of alphanumeric characters
154 from the portable character set, and since the wide character encoding
155 for a member of the portable character set is the same code point as
156 its single-byte encoding, we can use a simplified method to convert the
157 string to a multibyte character string. */
1fc82a56
UD
158static wctype_t
159is_char_class (const wchar_t *wcs)
160{
161 char s[CHAR_CLASS_MAX_LENGTH + 1];
162 char *cp = s;
28f540f4 163
1fc82a56
UD
164 do
165 {
5e463393 166 /* Test for a printable character from the portable character set. */
25286454 167#ifdef _LIBC
5e463393 168 if (*wcs < 0x20 || *wcs > 0x7e
25286454
AZ
169 || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
170 return (wctype_t) 0;
171#else
5e463393 172 switch (*wcs)
25286454
AZ
173 {
174 case L' ': case L'!': case L'"': case L'#': case L'%':
175 case L'&': case L'\'': case L'(': case L')': case L'*':
176 case L'+': case L',': case L'-': case L'.': case L'/':
177 case L'0': case L'1': case L'2': case L'3': case L'4':
178 case L'5': case L'6': case L'7': case L'8': case L'9':
179 case L':': case L';': case L'<': case L'=': case L'>':
180 case L'?':
181 case L'A': case L'B': case L'C': case L'D': case L'E':
182 case L'F': case L'G': case L'H': case L'I': case L'J':
183 case L'K': case L'L': case L'M': case L'N': case L'O':
184 case L'P': case L'Q': case L'R': case L'S': case L'T':
185 case L'U': case L'V': case L'W': case L'X': case L'Y':
186 case L'Z':
187 case L'[': case L'\\': case L']': case L'^': case L'_':
188 case L'a': case L'b': case L'c': case L'd': case L'e':
189 case L'f': case L'g': case L'h': case L'i': case L'j':
190 case L'k': case L'l': case L'm': case L'n': case L'o':
191 case L'p': case L'q': case L'r': case L's': case L't':
192 case L'u': case L'v': case L'w': case L'x': case L'y':
193 case L'z': case L'{': case L'|': case L'}': case L'~':
194 break;
195 default:
196 return (wctype_t) 0;
197 }
198#endif
1fc82a56 199
5e463393
UD
200 /* Avoid overrunning the buffer. */
201 if (cp == s + CHAR_CLASS_MAX_LENGTH)
25286454 202 return (wctype_t) 0;
28f540f4 203
5e463393
UD
204 *cp++ = (char) *wcs++;
205 }
206 while (*wcs != L'\0');
28f540f4 207
5e463393 208 *cp = '\0';
ba1ffaa1 209
ea6eb383 210 return wctype (s);
5e463393 211}
25286454 212#define IS_CHAR_CLASS(string) is_char_class (string)
28f540f4 213
25286454 214#include "fnmatch_loop.c"
d8aaef00 215
a79328c7
AZ
216static int
217fnmatch_convert_to_wide (const char *str, struct scratch_buffer *buf,
218 size_t *n)
219{
220 mbstate_t ps;
221 memset (&ps, '\0', sizeof (ps));
222
223 size_t nw = buf->length / sizeof (wchar_t);
224 *n = strnlen (str, nw - 1);
225 if (__glibc_likely (*n < nw))
226 {
227 const char *p = str;
228 *n = mbsrtowcs (buf->data, &p, *n + 1, &ps);
229 if (__glibc_unlikely (*n == (size_t) -1))
230 /* Something wrong.
231 XXX Do we have to set 'errno' to something which mbsrtows hasn't
232 already done? */
233 return -1;
234 if (p == NULL)
235 return 0;
236 memset (&ps, '\0', sizeof (ps));
237 }
238
239 *n = mbsrtowcs (NULL, &str, 0, &ps);
240 if (__glibc_unlikely (*n == (size_t) -1))
241 return -1;
242 if (!scratch_buffer_set_array_size (buf, *n + 1, sizeof (wchar_t)))
243 {
244 __set_errno (ENOMEM);
245 return -2;
246 }
247 assert (mbsinit (&ps));
248 mbsrtowcs (buf->data, &str, *n + 1, &ps);
249 return 0;
250}
5e463393 251
d8aaef00 252int
9dd346ff 253fnmatch (const char *pattern, const char *string, int flags)
d8aaef00 254{
25286454 255 if (__glibc_unlikely (MB_CUR_MAX != 1))
955994e1 256 {
955994e1 257 size_t n;
a79328c7
AZ
258 struct scratch_buffer wpattern;
259 scratch_buffer_init (&wpattern);
260 struct scratch_buffer wstring;
261 scratch_buffer_init (&wstring);
262 int r;
263
264 /* Convert the strings into wide characters. Any conversion issue
265 fallback to the ascii version. */
266 r = fnmatch_convert_to_wide (pattern, &wpattern, &n);
267 if (r == 0)
25286454 268 {
a79328c7
AZ
269 r = fnmatch_convert_to_wide (string, &wstring, &n);
270 if (r == 0)
271 r = internal_fnwmatch (wpattern.data, wstring.data,
272 (wchar_t *) wstring.data + n,
4e32c8f5 273 flags & FNM_PERIOD, flags, NULL);
a79328c7 274 }
f15ce4d8 275
a79328c7
AZ
276 scratch_buffer_free (&wstring);
277 scratch_buffer_free (&wpattern);
f15ce4d8 278
a79328c7
AZ
279 if (r == -2 || r == 0)
280 return r;
955994e1 281 }
955994e1
UD
282
283 return internal_fnmatch (pattern, string, string + strlen (string),
4e32c8f5 284 flags & FNM_PERIOD, flags, NULL);
d8aaef00
UD
285}
286
25286454 287#undef fnmatch
821a6bb4 288versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
25286454 289#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
821a6bb4
UD
290strong_alias (__fnmatch, __fnmatch_old)
291compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
25286454 292#endif
a14f26ef 293libc_hidden_ver (__fnmatch, fnmatch)
This page took 0.721157 seconds and 6 git commands to generate.