1/* Copyright (C) 1991-2022 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 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. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library; if not, see 16 <https://www.gnu.org/licenses/>. */ 17 18#ifndef _LIBC 19# include <libc-config.h> 20#endif 21 22/* Enable GNU extensions in fnmatch.h. */ 23#ifndef _GNU_SOURCE 24# define _GNU_SOURCE 1 25#endif 26 27#include <fnmatch.h> 28 29#include <assert.h> 30#include <errno.h> 31#include <ctype.h> 32#include <string.h> 33#include <stdlib.h> 34#if defined _LIBC || HAVE_ALLOCA 35# include <alloca.h> 36#endif 37#include <wchar.h> 38#include <wctype.h> 39#include <stddef.h> 40#include <stdbool.h> 41 42/* We need some of the locale data (the collation sequence information) 43 but there is no interface to get this information in general. Therefore 44 we support a correct implementation only in glibc. */ 45#ifdef _LIBC 46# include "../locale/localeinfo.h" 47# include "../locale/coll-lookup.h" 48# include <shlib-compat.h> 49 50# define CONCAT(a,b) __CONCAT(a,b) 51# define btowc __btowc 52# define iswctype __iswctype 53# define mbsrtowcs __mbsrtowcs 54# define mempcpy __mempcpy 55# define strnlen __strnlen 56# define towlower __towlower 57# define wcscat __wcscat 58# define wcslen __wcslen 59# define wctype __wctype 60# define wmemchr __wmemchr 61# define wmempcpy __wmempcpy 62# define fnmatch __fnmatch 63extern int fnmatch (const char *pattern, const char *string, int flags); 64#endif 65 66#ifdef _LIBC 67# if __GNUC__ >= 7 68# define FALLTHROUGH __attribute__ ((__fallthrough__)) 69# else 70# define FALLTHROUGH ((void) 0) 71# endif 72#else 73# include "attribute.h" 74#endif 75 76#include <intprops.h> 77#include <flexmember.h> 78 79#ifdef _LIBC 80typedef ptrdiff_t idx_t; 81#else 82# include "idx.h" 83#endif 84 85/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ 86#define NO_LEADING_PERIOD(flags) \ 87 ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) 88 89#ifndef _LIBC 90# if HAVE_ALLOCA 91/* The OS usually guarantees only one guard page at the bottom of the stack, 92 and a page size can be as small as 4096 bytes. So we cannot safely 93 allocate anything larger than 4096 bytes. Also care for the possibility 94 of a few compiler-allocated temporary stack slots. */ 95# define __libc_use_alloca(n) ((n) < 4032) 96# else 97/* Just use malloc. */ 98# define __libc_use_alloca(n) false 99# undef alloca 100# define alloca(n) malloc (n) 101# endif 102# define alloca_account(size, avar) ((avar) += (size), alloca (size)) 103#endif 104 105/* Provide support for user-defined character classes, based on the functions 106 from ISO C 90 amendment 1. */ 107#ifdef CHARCLASS_NAME_MAX 108# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX 109#else 110/* This shouldn't happen but some implementation might still have this 111 problem. Use a reasonable default value. */ 112# define CHAR_CLASS_MAX_LENGTH 256 113#endif 114 115#define IS_CHAR_CLASS(string) wctype (string) 116 117/* Avoid depending on library functions or files 118 whose names are inconsistent. */ 119 120/* Global variable. */ 121static int posixly_correct; 122 123/* Note that this evaluates C many times. */ 124#define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) 125#define CHAR char 126#define UCHAR unsigned char 127#define INT int 128#define FCT internal_fnmatch 129#define EXT ext_match 130#define END end_pattern 131#define STRUCT fnmatch_struct 132#define L_(CS) CS 133#define BTOWC(C) btowc (C) 134#define STRLEN(S) strlen (S) 135#define STRCAT(D, S) strcat (D, S) 136#define MEMPCPY(D, S, N) mempcpy (D, S, N) 137#define MEMCHR(S, C, N) memchr (S, C, N) 138#define WIDE_CHAR_VERSION 0 139#ifdef _LIBC 140# include <locale/weight.h> 141# define FINDIDX findidx 142#endif 143#include "fnmatch_loop.c" 144 145 146#define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) 147#define CHAR wchar_t 148#define UCHAR wint_t 149#define INT wint_t 150#define FCT internal_fnwmatch 151#define EXT ext_wmatch 152#define END end_wpattern 153#define L_(CS) L##CS 154#define BTOWC(C) (C) 155#define STRLEN(S) wcslen (S) 156#define STRCAT(D, S) wcscat (D, S) 157#define MEMPCPY(D, S, N) wmempcpy (D, S, N) 158#define MEMCHR(S, C, N) wmemchr (S, C, N) 159#define WIDE_CHAR_VERSION 1 160#ifdef _LIBC 161/* Change the name the header defines so it doesn't conflict with 162 the <locale/weight.h> version included above. */ 163# define findidx findidxwc 164# include <locale/weightwc.h> 165# undef findidx 166# define FINDIDX findidxwc 167#endif 168 169#undef IS_CHAR_CLASS 170/* We have to convert the wide character string in a multibyte string. But 171 we know that the character class names consist of alphanumeric characters 172 from the portable character set, and since the wide character encoding 173 for a member of the portable character set is the same code point as 174 its single-byte encoding, we can use a simplified method to convert the 175 string to a multibyte character string. */ 176static wctype_t 177is_char_class (const wchar_t *wcs) 178{ 179 char s[CHAR_CLASS_MAX_LENGTH + 1]; 180 char *cp = s; 181 182 do 183 { 184 /* Test for a printable character from the portable character set. */ 185#ifdef _LIBC 186 if (*wcs < 0x20 || *wcs > 0x7e 187 || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) 188 return (wctype_t) 0; 189#else 190 switch (*wcs) 191 { 192 case L' ': case L'!': case L'"': case L'#': case L'%': 193 case L'&': case L'\'': case L'(': case L')': case L'*': 194 case L'+': case L',': case L'-': case L'.': case L'/': 195 case L'0': case L'1': case L'2': case L'3': case L'4': 196 case L'5': case L'6': case L'7': case L'8': case L'9': 197 case L':': case L';': case L'<': case L'=': case L'>': 198 case L'?': 199 case L'A': case L'B': case L'C': case L'D': case L'E': 200 case L'F': case L'G': case L'H': case L'I': case L'J': 201 case L'K': case L'L': case L'M': case L'N': case L'O': 202 case L'P': case L'Q': case L'R': case L'S': case L'T': 203 case L'U': case L'V': case L'W': case L'X': case L'Y': 204 case L'Z': 205 case L'[': case L'\\': case L']': case L'^': case L'_': 206 case L'a': case L'b': case L'c': case L'd': case L'e': 207 case L'f': case L'g': case L'h': case L'i': case L'j': 208 case L'k': case L'l': case L'm': case L'n': case L'o': 209 case L'p': case L'q': case L'r': case L's': case L't': 210 case L'u': case L'v': case L'w': case L'x': case L'y': 211 case L'z': case L'{': case L'|': case L'}': case L'~': 212 break; 213 default: 214 return (wctype_t) 0; 215 } 216#endif 217 218 /* Avoid overrunning the buffer. */ 219 if (cp == s + CHAR_CLASS_MAX_LENGTH) 220 return (wctype_t) 0; 221 222 *cp++ = (char) *wcs++; 223 } 224 while (*wcs != L'\0'); 225 226 *cp = '\0'; 227 228 return wctype (s); 229} 230#define IS_CHAR_CLASS(string) is_char_class (string) 231 232#include "fnmatch_loop.c" 233 234 235int 236fnmatch (const char *pattern, const char *string, int flags) 237{ 238 if (__glibc_unlikely (MB_CUR_MAX != 1)) 239 { 240 mbstate_t ps; 241 size_t n; 242 const char *p; 243 wchar_t *wpattern_malloc = NULL; 244 wchar_t *wpattern; 245 wchar_t *wstring_malloc = NULL; 246 wchar_t *wstring; 247 size_t alloca_used = 0; 248 249 /* Convert the strings into wide characters. */ 250 memset (&ps, '\0', sizeof (ps)); 251 p = pattern; 252 n = strnlen (pattern, 1024); 253 if (__glibc_likely (n < 1024)) 254 { 255 wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), 256 alloca_used); 257 n = mbsrtowcs (wpattern, &p, n + 1, &ps); 258 if (__glibc_unlikely (n == (size_t) -1)) 259 /* Something wrong. 260 XXX Do we have to set 'errno' to something which mbsrtows hasn't 261 already done? */ 262 return -1; 263 if (p) 264 { 265 memset (&ps, '\0', sizeof (ps)); 266 goto prepare_wpattern; 267 } 268 } 269 else 270 { 271 prepare_wpattern: 272 n = mbsrtowcs (NULL, &pattern, 0, &ps); 273 if (__glibc_unlikely (n == (size_t) -1)) 274 /* Something wrong. 275 XXX Do we have to set 'errno' to something which mbsrtows hasn't 276 already done? */ 277 return -1; 278 if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) 279 { 280 __set_errno (ENOMEM); 281 return -2; 282 } 283 wpattern_malloc = wpattern 284 = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); 285 assert (mbsinit (&ps)); 286 if (wpattern == NULL) 287 return -2; 288 (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps); 289 } 290 291 assert (mbsinit (&ps)); 292 n = strnlen (string, 1024); 293 p = string; 294 if (__glibc_likely (n < 1024)) 295 { 296 wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), 297 alloca_used); 298 n = mbsrtowcs (wstring, &p, n + 1, &ps); 299 if (__glibc_unlikely (n == (size_t) -1)) 300 { 301 /* Something wrong. 302 XXX Do we have to set 'errno' to something which 303 mbsrtows hasn't already done? */ 304 free_return: 305 free (wpattern_malloc); 306 return -1; 307 } 308 if (p) 309 { 310 memset (&ps, '\0', sizeof (ps)); 311 goto prepare_wstring; 312 } 313 } 314 else 315 { 316 prepare_wstring: 317 n = mbsrtowcs (NULL, &string, 0, &ps); 318 if (__glibc_unlikely (n == (size_t) -1)) 319 /* Something wrong. 320 XXX Do we have to set 'errno' to something which mbsrtows hasn't 321 already done? */ 322 goto free_return; 323 if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) 324 { 325 free (wpattern_malloc); 326 __set_errno (ENOMEM); 327 return -2; 328 } 329 330 wstring_malloc = wstring 331 = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); 332 if (wstring == NULL) 333 { 334 free (wpattern_malloc); 335 return -2; 336 } 337 assert (mbsinit (&ps)); 338 (void) mbsrtowcs (wstring, &string, n + 1, &ps); 339 } 340 341 int res = internal_fnwmatch (wpattern, wstring, wstring + n, 342 flags & FNM_PERIOD, flags, NULL, 343 alloca_used); 344 345 free (wstring_malloc); 346 free (wpattern_malloc); 347 348 return res; 349 } 350 351 return internal_fnmatch (pattern, string, string + strlen (string), 352 flags & FNM_PERIOD, flags, NULL, 0); 353} 354 355#undef fnmatch 356versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); 357#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) 358strong_alias (__fnmatch, __fnmatch_old) 359compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); 360#endif 361libc_hidden_ver (__fnmatch, fnmatch) 362