Blame posix/tst-regcomp-truncated.c

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