Blame posix/tst-regcomp-truncated.c

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