Blame posix/tst-regcomp-truncated.c

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