Blame lib/fnmatch.c

Packit 709fb3
/* Copyright (C) 1991-1993, 1996-2007, 2009-2017 Free Software Foundation, Inc.
Packit 709fb3
Packit 709fb3
   This program is free software; you can redistribute it and/or modify
Packit 709fb3
   it under the terms of the GNU General Public License as published by
Packit 709fb3
   the Free Software Foundation; either version 3, or (at your option)
Packit 709fb3
   any later version.
Packit 709fb3
Packit 709fb3
   This program is distributed in the hope that it will be useful,
Packit 709fb3
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 709fb3
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 709fb3
   GNU General Public License for more details.
Packit 709fb3
Packit 709fb3
   You should have received a copy of the GNU General Public License
Packit 709fb3
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit 709fb3
Packit 709fb3
#ifndef _LIBC
Packit 709fb3
# include <config.h>
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
/* Enable GNU extensions in fnmatch.h.  */
Packit 709fb3
#ifndef _GNU_SOURCE
Packit 709fb3
# define _GNU_SOURCE    1
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
#include <fnmatch.h>
Packit 709fb3
Packit 709fb3
#include <alloca.h>
Packit 709fb3
#include <assert.h>
Packit 709fb3
#include <ctype.h>
Packit 709fb3
#include <errno.h>
Packit 709fb3
#include <stddef.h>
Packit 709fb3
#include <stdbool.h>
Packit 709fb3
#include <stdlib.h>
Packit 709fb3
#include <string.h>
Packit 709fb3
Packit 709fb3
#define WIDE_CHAR_SUPPORT \
Packit 709fb3
  (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \
Packit 709fb3
   && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY))
Packit 709fb3
Packit 709fb3
/* For platform which support the ISO C amendment 1 functionality we
Packit 709fb3
   support user defined character classes.  */
Packit 709fb3
#if defined _LIBC || WIDE_CHAR_SUPPORT
Packit 709fb3
# include <wctype.h>
Packit 709fb3
# include <wchar.h>
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
/* We need some of the locale data (the collation sequence information)
Packit 709fb3
   but there is no interface to get this information in general.  Therefore
Packit 709fb3
   we support a correct implementation only in glibc.  */
Packit 709fb3
#ifdef _LIBC
Packit 709fb3
# include "../locale/localeinfo.h"
Packit 709fb3
# include "../locale/elem-hash.h"
Packit 709fb3
# include "../locale/coll-lookup.h"
Packit 709fb3
# include <shlib-compat.h>
Packit 709fb3
Packit 709fb3
# define CONCAT(a,b) __CONCAT(a,b)
Packit 709fb3
# define mbsrtowcs __mbsrtowcs
Packit 709fb3
# define fnmatch __fnmatch
Packit 709fb3
extern int fnmatch (const char *pattern, const char *string, int flags);
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
#ifndef SIZE_MAX
Packit 709fb3
# define SIZE_MAX ((size_t) -1)
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
#include "flexmember.h"
Packit 709fb3
Packit 709fb3
#ifndef FALLTHROUGH
Packit 709fb3
# if __GNUC__ < 7
Packit 709fb3
#  define FALLTHROUGH ((void) 0)
Packit 709fb3
# else
Packit 709fb3
#  define FALLTHROUGH __attribute__ ((__fallthrough__))
Packit 709fb3
# endif
Packit 709fb3
#endif
Packit 709fb3
Packit 709fb3
/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
Packit 709fb3
#define NO_LEADING_PERIOD(flags) \
Packit 709fb3
  ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
Packit 709fb3
Packit 709fb3
/* Comment out all this code if we are using the GNU C Library, and are not
Packit 709fb3
   actually compiling the library itself, and have not detected a bug
Packit 709fb3
   in the library.  This code is part of the GNU C
Packit 709fb3
   Library, but also included in many other GNU distributions.  Compiling
Packit 709fb3
   and linking in this code is a waste when using the GNU C library
Packit 709fb3
   (especially if it is a shared library).  Rather than having every GNU
Packit 709fb3
   program understand 'configure --with-gnu-libc' and omit the object files,
Packit 709fb3
   it is simpler to just do this in the source for each such file.  */
Packit 709fb3
Packit 709fb3
#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU
Packit 709fb3
Packit 709fb3
Packit 709fb3
# if ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK))
Packit 709fb3
#  define isblank(c) ((c) == ' ' || (c) == '\t')
Packit 709fb3
# endif
Packit 709fb3
Packit 709fb3
# define STREQ(s1, s2) (strcmp (s1, s2) == 0)
Packit 709fb3
Packit 709fb3
# if defined _LIBC || WIDE_CHAR_SUPPORT
Packit 709fb3
/* The GNU C library provides support for user-defined character classes
Packit 709fb3
   and the functions from ISO C amendment 1.  */
Packit 709fb3
#  ifdef CHARCLASS_NAME_MAX
Packit 709fb3
#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
Packit 709fb3
#  else
Packit 709fb3
/* This shouldn't happen but some implementation might still have this
Packit 709fb3
   problem.  Use a reasonable default value.  */
Packit 709fb3
#   define CHAR_CLASS_MAX_LENGTH 256
Packit 709fb3
#  endif
Packit 709fb3
Packit 709fb3
#  ifdef _LIBC
Packit 709fb3
#   define IS_CHAR_CLASS(string) __wctype (string)
Packit 709fb3
#  else
Packit 709fb3
#   define IS_CHAR_CLASS(string) wctype (string)
Packit 709fb3
#  endif
Packit 709fb3
Packit 709fb3
#  ifdef _LIBC
Packit 709fb3
#   define ISWCTYPE(WC, WT)     __iswctype (WC, WT)
Packit 709fb3
#  else
Packit 709fb3
#   define ISWCTYPE(WC, WT)     iswctype (WC, WT)
Packit 709fb3
#  endif
Packit 709fb3
Packit 709fb3
#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
Packit 709fb3
/* In this case we are implementing the multibyte character handling.  */
Packit 709fb3
#   define HANDLE_MULTIBYTE     1
Packit 709fb3
#  endif
Packit 709fb3
Packit 709fb3
# else
Packit 709fb3
#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, 'xdigit'.  */
Packit 709fb3
Packit 709fb3
#  define IS_CHAR_CLASS(string)                                               \
Packit 709fb3
   (STREQ (string, "alpha") || STREQ (string, "upper")                        \
Packit 709fb3
    || STREQ (string, "lower") || STREQ (string, "digit")                     \
Packit 709fb3
    || STREQ (string, "alnum") || STREQ (string, "xdigit")                    \
Packit 709fb3
    || STREQ (string, "space") || STREQ (string, "print")                     \
Packit 709fb3
    || STREQ (string, "punct") || STREQ (string, "graph")                     \
Packit 709fb3
    || STREQ (string, "cntrl") || STREQ (string, "blank"))
Packit 709fb3
# endif
Packit 709fb3
Packit 709fb3
/* Avoid depending on library functions or files
Packit 709fb3
   whose names are inconsistent.  */
Packit 709fb3
Packit 709fb3
/* Global variable.  */
Packit 709fb3
static int posixly_correct;
Packit 709fb3
Packit 709fb3
# ifndef internal_function
Packit 709fb3
/* Inside GNU libc we mark some function in a special way.  In other
Packit 709fb3
   environments simply ignore the marking.  */
Packit 709fb3
#  define internal_function
Packit 709fb3
# endif
Packit 709fb3
Packit 709fb3
/* Note that this evaluates C many times.  */
Packit 709fb3
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
Packit 709fb3
# define CHAR   char
Packit 709fb3
# define UCHAR  unsigned char
Packit 709fb3
# define INT    int
Packit 709fb3
# define FCT    internal_fnmatch
Packit 709fb3
# define EXT    ext_match
Packit 709fb3
# define END    end_pattern
Packit 709fb3
# define L_(CS) CS
Packit 709fb3
# ifdef _LIBC
Packit 709fb3
#  define BTOWC(C)      __btowc (C)
Packit 709fb3
# else
Packit 709fb3
#  define BTOWC(C)      btowc (C)
Packit 709fb3
# endif
Packit 709fb3
# define STRLEN(S) strlen (S)
Packit 709fb3
# define STRCAT(D, S) strcat (D, S)
Packit 709fb3
# ifdef _LIBC
Packit 709fb3
#  define MEMPCPY(D, S, N) __mempcpy (D, S, N)
Packit 709fb3
# else
Packit 709fb3
#  if HAVE_MEMPCPY
Packit 709fb3
#   define MEMPCPY(D, S, N) mempcpy (D, S, N)
Packit 709fb3
#  else
Packit 709fb3
#   define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
Packit 709fb3
#  endif
Packit 709fb3
# endif
Packit 709fb3
# define MEMCHR(S, C, N) memchr (S, C, N)
Packit 709fb3
# include "fnmatch_loop.c"
Packit 709fb3
Packit 709fb3
Packit 709fb3
# if HANDLE_MULTIBYTE
Packit 709fb3
#  define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
Packit 709fb3
#  define CHAR  wchar_t
Packit 709fb3
#  define UCHAR wint_t
Packit 709fb3
#  define INT   wint_t
Packit 709fb3
#  define FCT   internal_fnwmatch
Packit 709fb3
#  define EXT   ext_wmatch
Packit 709fb3
#  define END   end_wpattern
Packit 709fb3
#  define L_(CS)        L##CS
Packit 709fb3
#  define BTOWC(C)      (C)
Packit 709fb3
#  ifdef _LIBC
Packit 709fb3
#   define STRLEN(S) __wcslen (S)
Packit 709fb3
#   define STRCAT(D, S) __wcscat (D, S)
Packit 709fb3
#   define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
Packit 709fb3
#  else
Packit 709fb3
#   define STRLEN(S) wcslen (S)
Packit 709fb3
#   define STRCAT(D, S) wcscat (D, S)
Packit 709fb3
#   if HAVE_WMEMPCPY
Packit 709fb3
#    define MEMPCPY(D, S, N) wmempcpy (D, S, N)
Packit 709fb3
#   else
Packit 709fb3
#    define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N))
Packit 709fb3
#   endif
Packit 709fb3
#  endif
Packit 709fb3
#  define MEMCHR(S, C, N) wmemchr (S, C, N)
Packit 709fb3
#  define WIDE_CHAR_VERSION 1
Packit 709fb3
Packit 709fb3
#  undef IS_CHAR_CLASS
Packit 709fb3
/* We have to convert the wide character string in a multibyte string.  But
Packit 709fb3
   we know that the character class names consist of alphanumeric characters
Packit 709fb3
   from the portable character set, and since the wide character encoding
Packit 709fb3
   for a member of the portable character set is the same code point as
Packit 709fb3
   its single-byte encoding, we can use a simplified method to convert the
Packit 709fb3
   string to a multibyte character string.  */
Packit 709fb3
static wctype_t
Packit 709fb3
is_char_class (const wchar_t *wcs)
Packit 709fb3
{
Packit 709fb3
  char s[CHAR_CLASS_MAX_LENGTH + 1];
Packit 709fb3
  char *cp = s;
Packit 709fb3
Packit 709fb3
  do
Packit 709fb3
    {
Packit 709fb3
      /* Test for a printable character from the portable character set.  */
Packit 709fb3
#  ifdef _LIBC
Packit 709fb3
      if (*wcs < 0x20 || *wcs > 0x7e
Packit 709fb3
          || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
Packit 709fb3
        return (wctype_t) 0;
Packit 709fb3
#  else
Packit 709fb3
      switch (*wcs)
Packit 709fb3
        {
Packit 709fb3
        case L' ': case L'!': case L'"': case L'#': case L'%':
Packit 709fb3
        case L'&': case L'\'': case L'(': case L')': case L'*':
Packit 709fb3
        case L'+': case L',': case L'-': case L'.': case L'/':
Packit 709fb3
        case L'0': case L'1': case L'2': case L'3': case L'4':
Packit 709fb3
        case L'5': case L'6': case L'7': case L'8': case L'9':
Packit 709fb3
        case L':': case L';': case L'<': case L'=': case L'>':
Packit 709fb3
        case L'?':
Packit 709fb3
        case L'A': case L'B': case L'C': case L'D': case L'E':
Packit 709fb3
        case L'F': case L'G': case L'H': case L'I': case L'J':
Packit 709fb3
        case L'K': case L'L': case L'M': case L'N': case L'O':
Packit 709fb3
        case L'P': case L'Q': case L'R': case L'S': case L'T':
Packit 709fb3
        case L'U': case L'V': case L'W': case L'X': case L'Y':
Packit 709fb3
        case L'Z':
Packit 709fb3
        case L'[': case L'\\': case L']': case L'^': case L'_':
Packit 709fb3
        case L'a': case L'b': case L'c': case L'd': case L'e':
Packit 709fb3
        case L'f': case L'g': case L'h': case L'i': case L'j':
Packit 709fb3
        case L'k': case L'l': case L'm': case L'n': case L'o':
Packit 709fb3
        case L'p': case L'q': case L'r': case L's': case L't':
Packit 709fb3
        case L'u': case L'v': case L'w': case L'x': case L'y':
Packit 709fb3
        case L'z': case L'{': case L'|': case L'}': case L'~':
Packit 709fb3
          break;
Packit 709fb3
        default:
Packit 709fb3
          return (wctype_t) 0;
Packit 709fb3
        }
Packit 709fb3
#  endif
Packit 709fb3
Packit 709fb3
      /* Avoid overrunning the buffer.  */
Packit 709fb3
      if (cp == s + CHAR_CLASS_MAX_LENGTH)
Packit 709fb3
        return (wctype_t) 0;
Packit 709fb3
Packit 709fb3
      *cp++ = (char) *wcs++;
Packit 709fb3
    }
Packit 709fb3
  while (*wcs != L'\0');
Packit 709fb3
Packit 709fb3
  *cp = '\0';
Packit 709fb3
Packit 709fb3
#  ifdef _LIBC
Packit 709fb3
  return __wctype (s);
Packit 709fb3
#  else
Packit 709fb3
  return wctype (s);
Packit 709fb3
#  endif
Packit 709fb3
}
Packit 709fb3
#  define IS_CHAR_CLASS(string) is_char_class (string)
Packit 709fb3
Packit 709fb3
#  include "fnmatch_loop.c"
Packit 709fb3
# endif
Packit 709fb3
Packit 709fb3
Packit 709fb3
int
Packit 709fb3
fnmatch (const char *pattern, const char *string, int flags)
Packit 709fb3
{
Packit 709fb3
# if HANDLE_MULTIBYTE
Packit 709fb3
#  define ALLOCA_LIMIT 2000
Packit 709fb3
  if (__builtin_expect (MB_CUR_MAX, 1) != 1)
Packit 709fb3
    {
Packit 709fb3
      mbstate_t ps;
Packit 709fb3
      size_t patsize;
Packit 709fb3
      size_t strsize;
Packit 709fb3
      size_t totsize;
Packit 709fb3
      wchar_t *wpattern;
Packit 709fb3
      wchar_t *wstring;
Packit 709fb3
      int res;
Packit 709fb3
Packit 709fb3
      /* Calculate the size needed to convert the strings to
Packit 709fb3
         wide characters.  */
Packit 709fb3
      memset (&ps, '\0', sizeof (ps));
Packit 709fb3
      patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
Packit 709fb3
      if (__builtin_expect (patsize != 0, 1))
Packit 709fb3
        {
Packit 709fb3
          assert (mbsinit (&ps);;
Packit 709fb3
          strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
Packit 709fb3
          if (__builtin_expect (strsize != 0, 1))
Packit 709fb3
            {
Packit 709fb3
              assert (mbsinit (&ps);;
Packit 709fb3
              totsize = patsize + strsize;
Packit 709fb3
              if (__builtin_expect (! (patsize <= totsize
Packit 709fb3
                                       && totsize <= SIZE_MAX / sizeof (wchar_t)),
Packit 709fb3
                                    0))
Packit 709fb3
                {
Packit 709fb3
                  errno = ENOMEM;
Packit 709fb3
                  return -1;
Packit 709fb3
                }
Packit 709fb3
Packit 709fb3
              /* Allocate room for the wide characters.  */
Packit 709fb3
              if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
Packit 709fb3
                wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
Packit 709fb3
              else
Packit 709fb3
                {
Packit 709fb3
                  wpattern = malloc (totsize * sizeof (wchar_t));
Packit 709fb3
                  if (__builtin_expect (! wpattern, 0))
Packit 709fb3
                    {
Packit 709fb3
                      errno = ENOMEM;
Packit 709fb3
                      return -1;
Packit 709fb3
                    }
Packit 709fb3
                }
Packit 709fb3
              wstring = wpattern + patsize;
Packit 709fb3
Packit 709fb3
              /* Convert the strings into wide characters.  */
Packit 709fb3
              mbsrtowcs (wpattern, &pattern, patsize, &ps);
Packit 709fb3
              assert (mbsinit (&ps);;
Packit 709fb3
              mbsrtowcs (wstring, &string, strsize, &ps);
Packit 709fb3
Packit 709fb3
              res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
Packit 709fb3
                                       flags & FNM_PERIOD, flags);
Packit 709fb3
Packit 709fb3
              if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
Packit 709fb3
                free (wpattern);
Packit 709fb3
              return res;
Packit 709fb3
            }
Packit 709fb3
        }
Packit 709fb3
    }
Packit 709fb3
Packit 709fb3
# endif /* HANDLE_MULTIBYTE */
Packit 709fb3
Packit 709fb3
  return internal_fnmatch (pattern, string, string + strlen (string),
Packit 709fb3
                           flags & FNM_PERIOD, flags);
Packit 709fb3
}
Packit 709fb3
Packit 709fb3
# ifdef _LIBC
Packit 709fb3
#  undef fnmatch
Packit 709fb3
versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
Packit 709fb3
#  if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
Packit 709fb3
strong_alias (__fnmatch, __fnmatch_old)
Packit 709fb3
compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
Packit 709fb3
#  endif
Packit 709fb3
libc_hidden_ver (__fnmatch, fnmatch)
Packit 709fb3
# endif
Packit 709fb3
Packit 709fb3
#endif  /* _LIBC or not __GNU_LIBRARY__.  */