Blame posix/tst-regcomp-truncated.c

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