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