Blame posix/tst-regcomp-truncated.c

Packit Service ec9266
/* Test compilation of truncated regular expressions.
Packit Service ec9266
   Copyright (C) 2018 Free Software Foundation, Inc.
Packit Service ec9266
   This file is part of the GNU C Library.
Packit Service ec9266
Packit Service ec9266
   The GNU C Library is free software; you can redistribute it and/or
Packit Service ec9266
   modify it under the terms of the GNU Lesser General Public
Packit Service ec9266
   License as published by the Free Software Foundation; either
Packit Service ec9266
   version 2.1 of the License, or (at your option) any later version.
Packit Service ec9266
Packit Service ec9266
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service ec9266
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service ec9266
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service ec9266
   Lesser General Public License for more details.
Packit Service ec9266
Packit Service ec9266
   You should have received a copy of the GNU Lesser General Public
Packit Service ec9266
   License along with the GNU C Library; if not, see
Packit Service ec9266
   <http://www.gnu.org/licenses/>.  */
Packit Service ec9266
Packit Service ec9266
/* This test constructs various patterns in an attempt to trigger
Packit Service ec9266
   over-reading the regular expression compiler, such as bug
Packit Service ec9266
   23578.  */
Packit Service ec9266
Packit Service ec9266
#include <array_length.h>
Packit Service ec9266
#include <errno.h>
Packit Service ec9266
#include <locale.h>
Packit Service ec9266
#include <regex.h>
Packit Service ec9266
#include <stdio.h>
Packit Service ec9266
#include <stdlib.h>
Packit Service ec9266
#include <string.h>
Packit Service ec9266
#include <support/check.h>
Packit Service ec9266
#include <support/next_to_fault.h>
Packit Service ec9266
#include <support/support.h>
Packit Service ec9266
#include <support/test-driver.h>
Packit Service ec9266
#include <wchar.h>
Packit Service ec9266
Packit Service ec9266
/* Locales to test.  */
Packit Service ec9266
static const char locales[][17] =
Packit Service ec9266
  {
Packit Service ec9266
    "C",
Packit Service ec9266
    "en_US.UTF-8",
Packit Service ec9266
    "de_DE.ISO-8859-1",
Packit Service ec9266
  };
Packit Service ec9266
Packit Service ec9266
/* Syntax options.  Will be combined with other flags.  */
Packit Service ec9266
static const reg_syntax_t syntaxes[] =
Packit Service ec9266
  {
Packit Service ec9266
    RE_SYNTAX_EMACS,
Packit Service ec9266
    RE_SYNTAX_AWK,
Packit Service ec9266
    RE_SYNTAX_GNU_AWK,
Packit Service ec9266
    RE_SYNTAX_POSIX_AWK,
Packit Service ec9266
    RE_SYNTAX_GREP,
Packit Service ec9266
    RE_SYNTAX_EGREP,
Packit Service ec9266
    RE_SYNTAX_POSIX_EGREP,
Packit Service ec9266
    RE_SYNTAX_POSIX_BASIC,
Packit Service ec9266
    RE_SYNTAX_POSIX_EXTENDED,
Packit Service ec9266
    RE_SYNTAX_POSIX_MINIMAL_EXTENDED,
Packit Service ec9266
  };
Packit Service ec9266
Packit Service ec9266
/* Trailing characters placed after the initial character.  */
Packit Service ec9266
static const char trailing_strings[][4] =
Packit Service ec9266
  {
Packit Service ec9266
    "",
Packit Service ec9266
    "[",
Packit Service ec9266
    "\\",
Packit Service ec9266
    "[\\",
Packit Service ec9266
    "(",
Packit Service ec9266
    "(\\",
Packit Service ec9266
    "\\(",
Packit Service ec9266
  };
Packit Service ec9266
Packit Service ec9266
static int
Packit Service ec9266
do_test (void)
Packit Service ec9266
{
Packit Service ec9266
  /* Staging buffer for the constructed regular expression.  */
Packit Service ec9266
  char buffer[16];
Packit Service ec9266
Packit Service ec9266
  /* Allocation used to detect over-reading by the regular expression
Packit Service ec9266
     compiler.  */
Packit Service ec9266
  struct support_next_to_fault ntf
Packit Service ec9266
    = support_next_to_fault_allocate (sizeof (buffer));
Packit Service ec9266
Packit Service ec9266
  /* Arbitrary Unicode codepoint at which we stop generating
Packit Service ec9266
     characters.  We do not probe the whole range because that would
Packit Service ec9266
     take too long due to combinatorical exploision as the result of
Packit Service ec9266
     combination with other flags.  */
Packit Service ec9266
  static const wchar_t last_character = 0xfff;
Packit Service ec9266
Packit Service ec9266
  for (size_t locale_idx = 0; locale_idx < array_length (locales);
Packit Service ec9266
       ++ locale_idx)
Packit Service ec9266
    {
Packit Service ec9266
      if (setlocale (LC_ALL, locales[locale_idx]) == NULL)
Packit Service ec9266
        {
Packit Service ec9266
          support_record_failure ();
Packit Service ec9266
          printf ("error: setlocale (\"%s\"): %m", locales[locale_idx]);
Packit Service ec9266
          continue;
Packit Service ec9266
        }
Packit Service ec9266
      if (test_verbose > 0)
Packit Service ec9266
        printf ("info: testing locale \"%s\"\n", locales[locale_idx]);
Packit Service ec9266
Packit Service ec9266
      for (wchar_t wc = 0; wc <= last_character; ++wc)
Packit Service ec9266
        {
Packit Service ec9266
          char *after_wc;
Packit Service ec9266
          if (wc == 0)
Packit Service ec9266
            {
Packit Service ec9266
              /* wcrtomb treats L'\0' in a special way.  */
Packit Service ec9266
              *buffer = '\0';
Packit Service ec9266
              after_wc = &buffer[1];
Packit Service ec9266
            }
Packit Service ec9266
          else
Packit Service ec9266
            {
Packit Service ec9266
              mbstate_t ps = { };
Packit Service ec9266
              size_t ret = wcrtomb (buffer, wc, &ps);
Packit Service ec9266
              if (ret == (size_t) -1)
Packit Service ec9266
                {
Packit Service ec9266
                  /* EILSEQ means that the target character set
Packit Service ec9266
                     cannot encode the character.  */
Packit Service ec9266
                  if (errno != EILSEQ)
Packit Service ec9266
                    {
Packit Service ec9266
                      support_record_failure ();
Packit Service ec9266
                      printf ("error: wcrtomb (0x%x) failed: %m\n",
Packit Service ec9266
                              (unsigned) wc);
Packit Service ec9266
                    }
Packit Service ec9266
                  continue;
Packit Service ec9266
                }
Packit Service ec9266
              TEST_VERIFY_EXIT (ret != 0);
Packit Service ec9266
              after_wc = &buffer[ret];
Packit Service ec9266
            }
Packit Service ec9266
Packit Service ec9266
          for (size_t trailing_idx = 0;
Packit Service ec9266
               trailing_idx < array_length (trailing_strings);
Packit Service ec9266
               ++trailing_idx)
Packit Service ec9266
            {
Packit Service ec9266
              char *after_trailing
Packit Service ec9266
                = stpcpy (after_wc, trailing_strings[trailing_idx]);
Packit Service ec9266
Packit Service ec9266
              for (int do_nul = 0; do_nul < 2; ++do_nul)
Packit Service ec9266
                {
Packit Service ec9266
                  char *after_nul;
Packit Service ec9266
                  if (do_nul)
Packit Service ec9266
                    {
Packit Service ec9266
                      *after_trailing = '\0';
Packit Service ec9266
                      after_nul = &after_trailing[1];
Packit Service ec9266
                    }
Packit Service ec9266
                  else
Packit Service ec9266
                    after_nul = after_trailing;
Packit Service ec9266
Packit Service ec9266
                  size_t length = after_nul - buffer;
Packit Service ec9266
Packit Service ec9266
                  /* Make sure that the faulting region starts
Packit Service ec9266
                     after the used portion of the buffer.  */
Packit Service ec9266
                  char *ntf_start = ntf.buffer + sizeof (buffer) - length;
Packit Service ec9266
                  memcpy (ntf_start, buffer, length);
Packit Service ec9266
Packit Service ec9266
                  for (const reg_syntax_t *psyntax = syntaxes;
Packit Service ec9266
                       psyntax < array_end (syntaxes); ++psyntax)
Packit Service ec9266
                    for (int do_icase = 0; do_icase < 2; ++do_icase)
Packit Service ec9266
                      {
Packit Service ec9266
                        re_syntax_options = *psyntax;
Packit Service ec9266
                        if (do_icase)
Packit Service ec9266
                          re_syntax_options |= RE_ICASE;
Packit Service ec9266
Packit Service ec9266
                        regex_t reg;
Packit Service ec9266
                        memset (&reg, 0, sizeof (reg));
Packit Service ec9266
                        const char *msg = re_compile_pattern
Packit Service ec9266
                          (ntf_start, length, ®);
Packit Service ec9266
                        if (msg != NULL)
Packit Service ec9266
                          {
Packit Service ec9266
                            if (test_verbose > 0)
Packit Service ec9266
                              {
Packit Service ec9266
                                char *quoted = support_quote_blob
Packit Service ec9266
                                  (buffer, length);
Packit Service ec9266
                                printf ("info: compilation failed for pattern"
Packit Service ec9266
                                        " \"%s\", syntax 0x%lx: %s\n",
Packit Service ec9266
                                        quoted, re_syntax_options, msg);
Packit Service ec9266
                                free (quoted);
Packit Service ec9266
                              }
Packit Service ec9266
                          }
Packit Service ec9266
                        else
Packit Service ec9266
                          regfree (®);
Packit Service ec9266
                      }
Packit Service ec9266
                }
Packit Service ec9266
            }
Packit Service ec9266
        }
Packit Service ec9266
    }
Packit Service ec9266
Packit Service ec9266
  support_next_to_fault_free (&ntf;;
Packit Service ec9266
Packit Service ec9266
  return 0;
Packit Service ec9266
}
Packit Service ec9266
Packit Service ec9266
#include <support/test-driver.c>