|
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 (®, 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>
|